mirror of
https://github.com/cranci1/Sora.git
synced 2026-04-21 08:32:00 +00:00
github update notice
Some checks are pending
Build and Release IPA / Build IPA and Mac Catalyst (push) Waiting to run
Some checks are pending
Build and Release IPA / Build IPA and Mac Catalyst (push) Waiting to run
This commit is contained in:
parent
6cd4df40b9
commit
0891e7a2c6
5 changed files with 220 additions and 6 deletions
|
|
@ -40,6 +40,7 @@
|
||||||
132417D92D1328B900B4F2D2 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D82D1328B900B4F2D2 /* VideoPlayerView.swift */; };
|
132417D92D1328B900B4F2D2 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132417D82D1328B900B4F2D2 /* VideoPlayerView.swift */; };
|
||||||
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1352BA702D1ABC30000A9AF9 /* URLSession.swift */; };
|
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1352BA702D1ABC30000A9AF9 /* URLSession.swift */; };
|
||||||
13B3A4B22D1477F100BCC0D5 /* StorageSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */; };
|
13B3A4B22D1477F100BCC0D5 /* StorageSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */; };
|
||||||
|
13C9821F2D2152B1007A0132 /* GitHubRelease.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C9821E2D2152B1007A0132 /* GitHubRelease.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
|
@ -77,6 +78,7 @@
|
||||||
1352BA6F2D1AB113000A9AF9 /* Sora.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sora.entitlements; sourceTree = "<group>"; };
|
1352BA6F2D1AB113000A9AF9 /* Sora.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Sora.entitlements; sourceTree = "<group>"; };
|
||||||
1352BA702D1ABC30000A9AF9 /* URLSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSession.swift; sourceTree = "<group>"; };
|
1352BA702D1ABC30000A9AF9 /* URLSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSession.swift; sourceTree = "<group>"; };
|
||||||
13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageSettingsView.swift; sourceTree = "<group>"; };
|
13B3A4B12D1477F100BCC0D5 /* StorageSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageSettingsView.swift; sourceTree = "<group>"; };
|
||||||
|
13C9821E2D2152B1007A0132 /* GitHubRelease.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHubRelease.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -152,6 +154,7 @@
|
||||||
132417912D1319E800B4F2D2 /* Utils */ = {
|
132417912D1319E800B4F2D2 /* Utils */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
13C9821D2D2152A0007A0132 /* GitHub */,
|
||||||
1308CFBA2D19843E004CD38C /* CustomPlayer */,
|
1308CFBA2D19843E004CD38C /* CustomPlayer */,
|
||||||
132417922D1319E800B4F2D2 /* Miru */,
|
132417922D1319E800B4F2D2 /* Miru */,
|
||||||
132417942D1319E800B4F2D2 /* Extensions */,
|
132417942D1319E800B4F2D2 /* Extensions */,
|
||||||
|
|
@ -276,6 +279,14 @@
|
||||||
path = EpisodesCell;
|
path = EpisodesCell;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
13C9821D2D2152A0007A0132 /* GitHub */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
13C9821E2D2152B1007A0132 /* GitHubRelease.swift */,
|
||||||
|
);
|
||||||
|
path = GitHub;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
|
@ -381,6 +392,7 @@
|
||||||
1324179E2D1319E800B4F2D2 /* MiruDataStruct.swift in Sources */,
|
1324179E2D1319E800B4F2D2 /* MiruDataStruct.swift in Sources */,
|
||||||
1308CFBE2D19844D004CD38C /* MusicProgressSlider.swift in Sources */,
|
1308CFBE2D19844D004CD38C /* MusicProgressSlider.swift in Sources */,
|
||||||
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */,
|
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */,
|
||||||
|
13C9821F2D2152B1007A0132 /* GitHubRelease.swift in Sources */,
|
||||||
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */,
|
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */,
|
||||||
132417A02D1319E800B4F2D2 /* HistoryManager.swift in Sources */,
|
132417A02D1319E800B4F2D2 /* HistoryManager.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
@ -528,7 +540,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTS_MACCATALYST = YES;
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
|
@ -561,7 +573,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SUPPORTS_MACCATALYST = YES;
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -29,6 +29,84 @@ struct ContentView: View {
|
||||||
Label("Settings", systemImage: "gearshape")
|
Label("Settings", systemImage: "gearshape")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onAppear {
|
||||||
|
checkForUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkForUpdate() {
|
||||||
|
fetchLatestRelease { release in
|
||||||
|
guard let release = release else { return }
|
||||||
|
|
||||||
|
let latestVersion = release.tagName
|
||||||
|
let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0.0"
|
||||||
|
|
||||||
|
if latestVersion.compare(currentVersion, options: .numeric) == .orderedDescending {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
showUpdateAlert(release: release)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchLatestRelease(completion: @escaping (GitHubRelease?) -> Void) {
|
||||||
|
let url = URL(string: "https://api.github.com/repos/cranci1/Sora/releases/latest")!
|
||||||
|
|
||||||
|
URLSession.shared.dataTask(with: url) { data, response, error in
|
||||||
|
guard let data = data, error == nil else {
|
||||||
|
completion(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let release = try? JSONDecoder().decode(GitHubRelease.self, from: data)
|
||||||
|
completion(release)
|
||||||
|
}.resume()
|
||||||
|
}
|
||||||
|
|
||||||
|
func showUpdateAlert(release: GitHubRelease) {
|
||||||
|
let alert = UIAlertController(title: "Update Available", message: "A new version (\(release.tagName)) is available. Would you like to update Sora?", preferredStyle: .alert)
|
||||||
|
|
||||||
|
alert.addAction(UIAlertAction(title: "Update", style: .default, handler: { _ in
|
||||||
|
self.showInstallOptionsAlert(release: release)
|
||||||
|
}))
|
||||||
|
|
||||||
|
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||||
|
|
||||||
|
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||||
|
let rootViewController = windowScene.windows.first?.rootViewController {
|
||||||
|
rootViewController.present(alert, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func showInstallOptionsAlert(release: GitHubRelease) {
|
||||||
|
let installAlert = UIAlertController(title: "Install Update", message: "Choose an installation method:", preferredStyle: .alert)
|
||||||
|
|
||||||
|
let downloadUrl = release.assets.first?.browserDownloadUrl ?? ""
|
||||||
|
|
||||||
|
installAlert.addAction(UIAlertAction(title: "Install in AltStore", style: .default, handler: { _ in
|
||||||
|
if let url = URL(string: "altstore://install?url=\(downloadUrl)") {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
installAlert.addAction(UIAlertAction(title: "Install in Sidestore", style: .default, handler: { _ in
|
||||||
|
if let url = URL(string: "sidestore://install?url=\(downloadUrl)") {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
installAlert.addAction(UIAlertAction(title: "Open in Safari", style: .default, handler: { _ in
|
||||||
|
if let url = URL(string: downloadUrl) {
|
||||||
|
UIApplication.shared.open(url)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
installAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
|
||||||
|
|
||||||
|
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||||
|
let rootViewController = windowScene.windows.first?.rootViewController {
|
||||||
|
rootViewController.present(installAlert, animated: true, completion: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>audio</string>
|
<string>audio</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
124
Sora/Utils/GitHub/GitHubRelease.swift
Normal file
124
Sora/Utils/GitHub/GitHubRelease.swift
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
//
|
||||||
|
// GitHubRelease.swift
|
||||||
|
// Sora
|
||||||
|
//
|
||||||
|
// Created by Francesco on 29/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct GitHubRelease: Codable {
|
||||||
|
let url: String
|
||||||
|
let assetsUrl: String
|
||||||
|
let uploadUrl: String
|
||||||
|
let htmlUrl: String
|
||||||
|
let id: Int
|
||||||
|
let author: Author
|
||||||
|
let nodeId: String
|
||||||
|
let tagName: String
|
||||||
|
let targetCommitish: String
|
||||||
|
let name: String
|
||||||
|
let draft: Bool
|
||||||
|
let prerelease: Bool
|
||||||
|
let createdAt: String
|
||||||
|
let publishedAt: String
|
||||||
|
let assets: [Asset]
|
||||||
|
let tarballUrl: String
|
||||||
|
let zipballUrl: String
|
||||||
|
let body: String
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case url
|
||||||
|
case assetsUrl = "assets_url"
|
||||||
|
case uploadUrl = "upload_url"
|
||||||
|
case htmlUrl = "html_url"
|
||||||
|
case id
|
||||||
|
case author
|
||||||
|
case nodeId = "node_id"
|
||||||
|
case tagName = "tag_name"
|
||||||
|
case targetCommitish = "target_commitish"
|
||||||
|
case name
|
||||||
|
case draft
|
||||||
|
case prerelease
|
||||||
|
case createdAt = "created_at"
|
||||||
|
case publishedAt = "published_at"
|
||||||
|
case assets
|
||||||
|
case tarballUrl = "tarball_url"
|
||||||
|
case zipballUrl = "zipball_url"
|
||||||
|
case body
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Author: Codable {
|
||||||
|
let login: String
|
||||||
|
let id: Int
|
||||||
|
let nodeId: String
|
||||||
|
let avatarUrl: String
|
||||||
|
let gravatarId: String
|
||||||
|
let url: String
|
||||||
|
let htmlUrl: String
|
||||||
|
let followersUrl: String
|
||||||
|
let followingUrl: String
|
||||||
|
let gistsUrl: String
|
||||||
|
let starredUrl: String
|
||||||
|
let subscriptionsUrl: String
|
||||||
|
let organizationsUrl: String
|
||||||
|
let reposUrl: String
|
||||||
|
let eventsUrl: String
|
||||||
|
let receivedEventsUrl: String
|
||||||
|
let type: String
|
||||||
|
let siteAdmin: Bool
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case login
|
||||||
|
case id
|
||||||
|
case nodeId = "node_id"
|
||||||
|
case avatarUrl = "avatar_url"
|
||||||
|
case gravatarId = "gravatar_id"
|
||||||
|
case url
|
||||||
|
case htmlUrl = "html_url"
|
||||||
|
case followersUrl = "followers_url"
|
||||||
|
case followingUrl = "following_url"
|
||||||
|
case gistsUrl = "gists_url"
|
||||||
|
case starredUrl = "starred_url"
|
||||||
|
case subscriptionsUrl = "subscriptions_url"
|
||||||
|
case organizationsUrl = "organizations_url"
|
||||||
|
case reposUrl = "repos_url"
|
||||||
|
case eventsUrl = "events_url"
|
||||||
|
case receivedEventsUrl = "received_events_url"
|
||||||
|
case type
|
||||||
|
case siteAdmin = "site_admin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Asset: Codable {
|
||||||
|
let url: String
|
||||||
|
let id: Int
|
||||||
|
let nodeId: String
|
||||||
|
let name: String
|
||||||
|
let label: String?
|
||||||
|
let uploader: Author
|
||||||
|
let contentType: String
|
||||||
|
let state: String
|
||||||
|
let size: Int
|
||||||
|
let downloadCount: Int
|
||||||
|
let createdAt: String
|
||||||
|
let updatedAt: String
|
||||||
|
let browserDownloadUrl: String
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case url
|
||||||
|
case id
|
||||||
|
case nodeId = "node_id"
|
||||||
|
case name
|
||||||
|
case label
|
||||||
|
case uploader
|
||||||
|
case contentType = "content_type"
|
||||||
|
case state
|
||||||
|
case size
|
||||||
|
case downloadCount = "download_count"
|
||||||
|
case createdAt = "created_at"
|
||||||
|
case updatedAt = "updated_at"
|
||||||
|
case browserDownloadUrl = "browser_download_url"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue