diff --git a/Sora/Assets.xcassets/AppIcon.appiconset/darkmode.png b/Sora/Assets.xcassets/AppIcon.appiconset/darkmode.png deleted file mode 100644 index c8f6f6f..0000000 Binary files a/Sora/Assets.xcassets/AppIcon.appiconset/darkmode.png and /dev/null differ diff --git a/Sora/Assets.xcassets/AppIcon.appiconset/lightmode.png b/Sora/Assets.xcassets/AppIcon.appiconset/lightmode.png deleted file mode 100644 index 7256d08..0000000 Binary files a/Sora/Assets.xcassets/AppIcon.appiconset/lightmode.png and /dev/null differ diff --git a/Sora/Assets.xcassets/AppIcon.appiconset/tinting.png b/Sora/Assets.xcassets/AppIcon.appiconset/tinting.png deleted file mode 100644 index f55a3d9..0000000 Binary files a/Sora/Assets.xcassets/AppIcon.appiconset/tinting.png and /dev/null differ diff --git a/Sora/Assets.xcassets/AppIcon.appiconset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/Contents.json similarity index 100% rename from Sora/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/Contents.json diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/darkmode.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/darkmode.png new file mode 100644 index 0000000..dc6328e Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/darkmode.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/lightmode.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/lightmode.png new file mode 100644 index 0000000..272905b Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/lightmode.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/tinting.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/tinting.png new file mode 100644 index 0000000..e9d0104 Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Default.appiconset/tinting.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Default_Preview.imageset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Default_Preview.imageset/Contents.json new file mode 100644 index 0000000..b85e601 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/AppIcon_Default_Preview.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "preview.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Default_Preview.imageset/preview.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Default_Preview.imageset/preview.png new file mode 100644 index 0000000..2f2be91 Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Default_Preview.imageset/preview.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Original.appiconset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Original.appiconset/Contents.json new file mode 100644 index 0000000..adc0a20 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/AppIcon_Original.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "original.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Original.appiconset/original.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Original.appiconset/original.png new file mode 100644 index 0000000..c45e62a Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Original.appiconset/original.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Original_Preview.imageset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Original_Preview.imageset/Contents.json new file mode 100644 index 0000000..b85e601 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/AppIcon_Original_Preview.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "preview.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Original_Preview.imageset/preview.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Original_Preview.imageset/preview.png new file mode 100644 index 0000000..460e487 Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Original_Preview.imageset/preview.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/Contents.json new file mode 100644 index 0000000..c7a15f9 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "filename" : "lightmode.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "darkmode.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "filename" : "tinting.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/darkmode.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/darkmode.png new file mode 100644 index 0000000..a84929a Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/darkmode.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/lightmode.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/lightmode.png new file mode 100644 index 0000000..7df252d Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/lightmode.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/tinting.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/tinting.png new file mode 100644 index 0000000..0adc458 Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel.appiconset/tinting.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel_Preview.imageset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel_Preview.imageset/Contents.json new file mode 100644 index 0000000..b85e601 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel_Preview.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "preview.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel_Preview.imageset/preview.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel_Preview.imageset/preview.png new file mode 100644 index 0000000..1a5a0c8 Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pixel_Preview.imageset/preview.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/Contents.json new file mode 100644 index 0000000..c7a15f9 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "filename" : "lightmode.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "darkmode.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "filename" : "tinting.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/darkmode.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/darkmode.png new file mode 100644 index 0000000..106c655 Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/darkmode.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/lightmode.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/lightmode.png new file mode 100644 index 0000000..451a2e8 Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/lightmode.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/tinting.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/tinting.png new file mode 100644 index 0000000..d911fdb Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride.appiconset/tinting.png differ diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pride_Preview.imageset/Contents.json b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride_Preview.imageset/Contents.json new file mode 100644 index 0000000..b85e601 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride_Preview.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "preview.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Assets.xcassets/AppIcons/AppIcon_Pride_Preview.imageset/preview.png b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride_Preview.imageset/preview.png new file mode 100644 index 0000000..7a6110b Binary files /dev/null and b/Sora/Assets.xcassets/AppIcons/AppIcon_Pride_Preview.imageset/preview.png differ diff --git a/Sora/Assets.xcassets/AppIcons/Contents.json b/Sora/Assets.xcassets/AppIcons/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Sora/Assets.xcassets/AppIcons/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sora/Views/SettingsView/SettingsSubViews/SettingsViewAlternateAppIconPicker.swift b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewAlternateAppIconPicker.swift new file mode 100644 index 0000000..83d5a8f --- /dev/null +++ b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewAlternateAppIconPicker.swift @@ -0,0 +1,71 @@ +// +// SettingsViewAlternateAppIconPicker.swift +// Sulfur +// +// Created by Dominic on 20.04.25. +// + +import SwiftUI + +struct SettingsViewAlternateAppIconPicker: View { + @Binding var isPresented: Bool + @AppStorage("currentAppIcon") private var currentAppIcon = "Default" + + let icons: [(name: String, icon: String)] = [ + ("Default", "Default"), + ("Original", "Original"), + ("Pixel", "Pixel"), + ("Pride", "Pride") + ] + + var body: some View { + VStack { + Text("Select an App Icon") + .font(.headline) + .padding() + + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 20) { + ForEach(icons, id: \.name) { icon in + VStack { + Image("AppIcon_\(icon.icon)_Preview", bundle: .main) + .resizable() + .scaledToFit() + .frame(width: 60, height: 60) + .cornerRadius(10) + .shadow(radius: 6) + .padding() + .background( + currentAppIcon == icon.name ? Color.accentColor.opacity(0.3) : Color.clear + ) + .cornerRadius(10) + .accessibilityLabel("Alternative App Icon") + Text(icon.name) + .font(.caption) + .foregroundColor(currentAppIcon == icon.name ? .accentColor : .primary) + } + .accessibilityAddTraits(.isButton) + .onTapGesture { + currentAppIcon = icon.name + setAppIcon(named: icon.icon) + } + } + } + .padding() + } + Spacer() + } + .modifier(HideToolbarModifier()) + } + + private func setAppIcon(named iconName: String) { + if UIApplication.shared.supportsAlternateIcons { + UIApplication.shared.setAlternateIconName(iconName == "Default" ? nil : "AppIcon_\(iconName)", completionHandler: { error in + isPresented = false + if let error { + Logger.shared.log("Failed to set alternate icon: \(error.localizedDescription)", type: .error) + } + }) + } + } +} diff --git a/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift index 79bbbff..0738fc1 100644 --- a/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift +++ b/Sora/Views/SettingsView/SettingsSubViews/SettingsViewGeneral.swift @@ -16,11 +16,13 @@ struct SettingsViewGeneral: View { @AppStorage("metadataProviders") private var metadataProviders: String = "AniList" @AppStorage("mediaColumnsPortrait") private var mediaColumnsPortrait: Int = 2 @AppStorage("mediaColumnsLandscape") private var mediaColumnsLandscape: Int = 4 + @AppStorage("currentAppIcon") private var currentAppIcon = "Default" @AppStorage("episodeSortOrder") private var episodeSortOrder: String = "Ascending" private let metadataProvidersList = ["AniList"] private let sortOrderOptions = ["Ascending", "Descending"] @EnvironmentObject var settings: Settings + @State private var showAppIconPicker = false var body: some View { Form { @@ -35,6 +37,18 @@ struct SettingsViewGeneral: View { } .pickerStyle(SegmentedPickerStyle()) } + + HStack { + Text("App Icon") + Spacer() + Button(action: { + showAppIconPicker.toggle() + }) { + Text(currentAppIcon.isEmpty ? "Default" : currentAppIcon) + .font(.body) + .foregroundColor(.accentColor) + } + } } Section(header: Text("Media View"), footer: Text("The episode range controls how many episodes appear on each page. Episodes are grouped into sets (like 1-25, 26-50, and so on), allowing you to navigate through them more easily.\n\nFor episode metadata it is refering to the episode thumbnail and title, since sometimes it can contain spoilers.")) { @@ -108,5 +122,14 @@ struct SettingsViewGeneral: View { } } .navigationTitle("General") + .sheet(isPresented: $showAppIconPicker) { + if #available(iOS 16.0, *) { + SettingsViewAlternateAppIconPicker(isPresented: $showAppIconPicker) + .presentationDetents([.height(200)]) + } else { + SettingsViewAlternateAppIconPicker(isPresented: $showAppIconPicker) + } + } + .modifier(HideToolbarModifier()) } } diff --git a/Sora/Views/SettingsView/SettingsView.swift b/Sora/Views/SettingsView/SettingsView.swift index 2b75991..32b77cd 100644 --- a/Sora/Views/SettingsView/SettingsView.swift +++ b/Sora/Views/SettingsView/SettingsView.swift @@ -8,6 +8,8 @@ import SwiftUI struct SettingsView: View { + let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "ALPHA" + var body: some View { NavigationView { Form { @@ -92,7 +94,7 @@ struct SettingsView: View { } } } - Section(footer: Text("Running Sora 0.3.0 - cranci1")) {} + Section(footer: Text("Running Sora \(version) - cranci1")) {} } .navigationTitle("Settings") } diff --git a/Sulfur.xcodeproj/project.pbxproj b/Sulfur.xcodeproj/project.pbxproj index 0a9d096..b887f93 100644 --- a/Sulfur.xcodeproj/project.pbxproj +++ b/Sulfur.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 132AF1212D99951700A0140B /* JSController-Streams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132AF1202D99951700A0140B /* JSController-Streams.swift */; }; 132AF1232D9995C300A0140B /* JSController-Details.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132AF1222D9995C300A0140B /* JSController-Details.swift */; }; 132AF1252D9995F900A0140B /* JSController-Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132AF1242D9995F900A0140B /* JSController-Search.swift */; }; + 132FC5B32DE31DAE009A80F7 /* SettingsViewAlternateAppIconPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132FC5B22DE31DAD009A80F7 /* SettingsViewAlternateAppIconPicker.swift */; }; 133D7C6E2D2BE2500075467E /* SoraApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6D2D2BE2500075467E /* SoraApp.swift */; }; 133D7C702D2BE2500075467E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133D7C6F2D2BE2500075467E /* ContentView.swift */; }; 133D7C722D2BE2520075467E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 133D7C712D2BE2520075467E /* Assets.xcassets */; }; @@ -96,6 +97,7 @@ 132AF1202D99951700A0140B /* JSController-Streams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Streams.swift"; sourceTree = ""; }; 132AF1222D9995C300A0140B /* JSController-Details.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Details.swift"; sourceTree = ""; }; 132AF1242D9995F900A0140B /* JSController-Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Search.swift"; sourceTree = ""; }; + 132FC5B22DE31DAD009A80F7 /* SettingsViewAlternateAppIconPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewAlternateAppIconPicker.swift; sourceTree = ""; }; 133D7C6A2D2BE2500075467E /* Sulfur.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sulfur.app; sourceTree = BUILT_PRODUCTS_DIR; }; 133D7C6D2D2BE2500075467E /* SoraApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoraApp.swift; sourceTree = ""; }; 133D7C6F2D2BE2500075467E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -276,6 +278,7 @@ 133D7C832D2BE2630075467E /* SettingsSubViews */ = { isa = PBXGroup; children = ( + 132FC5B22DE31DAD009A80F7 /* SettingsViewAlternateAppIconPicker.swift */, 1E9FF1D22D403E42008AC100 /* SettingsViewLoggerFilter.swift */, 1399FAD32D3AB38C00E97C31 /* SettingsViewLogger.swift */, 133D7C842D2BE2630075467E /* SettingsViewModule.swift */, @@ -652,6 +655,7 @@ 13EA2BD52D32D97400C1EBD7 /* CustomPlayer.swift in Sources */, 727220712DD642B100C2A4A2 /* JSController-StreamTypeDownload.swift in Sources */, 727220722DD642B100C2A4A2 /* JSController+MP4Download.swift in Sources */, + 132FC5B32DE31DAE009A80F7 /* SettingsViewAlternateAppIconPicker.swift in Sources */, 1399FAD42D3AB38C00E97C31 /* SettingsViewLogger.swift in Sources */, 72AC3A012DD4DAEB00C60B96 /* ImagePrefetchManager.swift in Sources */, 72AC3A022DD4DAEB00C60B96 /* EpisodeMetadataManager.swift in Sources */,