mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +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 */; };
|
||||
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1352BA702D1ABC30000A9AF9 /* URLSession.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 */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
|
@ -77,6 +78,7 @@
|
|||
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>"; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -152,6 +154,7 @@
|
|||
132417912D1319E800B4F2D2 /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13C9821D2D2152A0007A0132 /* GitHub */,
|
||||
1308CFBA2D19843E004CD38C /* CustomPlayer */,
|
||||
132417922D1319E800B4F2D2 /* Miru */,
|
||||
132417942D1319E800B4F2D2 /* Extensions */,
|
||||
|
|
@ -276,6 +279,14 @@
|
|||
path = EpisodesCell;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13C9821D2D2152A0007A0132 /* GitHub */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13C9821E2D2152B1007A0132 /* GitHubRelease.swift */,
|
||||
);
|
||||
path = GitHub;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
|
@ -381,6 +392,7 @@
|
|||
1324179E2D1319E800B4F2D2 /* MiruDataStruct.swift in Sources */,
|
||||
1308CFBE2D19844D004CD38C /* MusicProgressSlider.swift in Sources */,
|
||||
132417D52D13240200B4F2D2 /* EpisodeCell.swift in Sources */,
|
||||
13C9821F2D2152B1007A0132 /* GitHubRelease.swift in Sources */,
|
||||
1352BA712D1ABC30000A9AF9 /* URLSession.swift in Sources */,
|
||||
132417A02D1319E800B4F2D2 /* HistoryManager.swift in Sources */,
|
||||
);
|
||||
|
|
@ -528,7 +540,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
@ -561,7 +573,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.cranci.Sora;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -29,6 +29,84 @@ struct ContentView: View {
|
|||
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>
|
||||
</dict>
|
||||
</array>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</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