mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +00:00
Fix simulator crash & add conditional support for iOS 26+ native TabView (#209)
* add ability to use native tabbar on ios 26 or later * add tabview lcalization * fix library / home tab label and localization * add missing localization & german translation
This commit is contained in:
parent
82eec0688f
commit
78df4df73b
7 changed files with 121 additions and 87 deletions
|
|
@ -16,37 +16,45 @@ struct ContentView_Previews: PreviewProvider {
|
|||
}
|
||||
|
||||
struct ContentView: View {
|
||||
@AppStorage("useNativeTabBar") private var useNativeTabBar: Bool = false
|
||||
@StateObject private var tabBarController = TabBarController()
|
||||
@State var selectedTab: Int = 0
|
||||
@State var lastTab: Int = 0
|
||||
@State private var searchQuery: String = ""
|
||||
|
||||
let tabs: [TabItem] = [
|
||||
TabItem(icon: "square.stack", title: ""),
|
||||
TabItem(icon: "arrow.down.circle", title: ""),
|
||||
TabItem(icon: "gearshape", title: ""),
|
||||
TabItem(icon: "magnifyingglass", title: "")
|
||||
TabItem(icon: "square.stack", title: NSLocalizedString("LibraryTab", comment: "")),
|
||||
TabItem(icon: "arrow.down.circle", title: NSLocalizedString("DownloadsTab", comment: "")),
|
||||
TabItem(icon: "gearshape", title: NSLocalizedString("SettingsTab", comment: "")),
|
||||
TabItem(icon: "magnifyingglass", title: NSLocalizedString("SearchTab", comment: ""))
|
||||
]
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .bottom) {
|
||||
switch selectedTab {
|
||||
case 0:
|
||||
LibraryView()
|
||||
.environmentObject(tabBarController)
|
||||
case 1:
|
||||
DownloadView()
|
||||
.environmentObject(tabBarController)
|
||||
case 2:
|
||||
SettingsView()
|
||||
.environmentObject(tabBarController)
|
||||
case 3:
|
||||
SearchView(searchQuery: $searchQuery)
|
||||
.environmentObject(tabBarController)
|
||||
default:
|
||||
LibraryView()
|
||||
.environmentObject(tabBarController)
|
||||
private func tabView(for index: Int) -> some View {
|
||||
switch index {
|
||||
case 1: return AnyView(DownloadView())
|
||||
case 2: return AnyView(SettingsView())
|
||||
case 3: return AnyView(SearchView(searchQuery: $searchQuery))
|
||||
default: return AnyView(LibraryView())
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if #available(iOS 26, *), useNativeTabBar == true {
|
||||
TabView {
|
||||
ForEach(Array(tabs.enumerated()), id: \.offset) { index, item in
|
||||
Tab(item.title, systemImage: item.icon, role: index == 3 ? .search : nil) {
|
||||
tabView(for: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
.searchable(text: $searchQuery)
|
||||
.environmentObject(tabBarController)
|
||||
} else {
|
||||
ZStack(alignment: .bottom) {
|
||||
Group {
|
||||
tabView(for: selectedTab)
|
||||
}
|
||||
.environmentObject(tabBarController)
|
||||
|
||||
TabBar(
|
||||
tabs: tabs,
|
||||
|
|
@ -60,4 +68,5 @@ struct ContentView: View {
|
|||
.ignoresSafeArea(.keyboard, edges: .bottom)
|
||||
.padding(.bottom, -20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@
|
|||
"Copied to Clipboard" = "In die Zwischenablage kopiert";
|
||||
"Copy to Clipboard" = "In die Zwischenablage kopieren";
|
||||
"Copy URL" = "URL kopieren";
|
||||
"Collections" = "Sammlungen";
|
||||
"No Collections" = "Keine Sammlungen vorhanden";
|
||||
"Create a collection to organize your bookmarks" = "Erstelle eine Sammlung für mehr Organisation";
|
||||
|
||||
/* Episodes */
|
||||
"%lld Episodes" = "%lld Folgen";
|
||||
|
|
@ -84,7 +87,7 @@
|
|||
"Download Episode" = "Folge herunterladen";
|
||||
"Download Summary" = "Download-Übersicht";
|
||||
"Download This Episode" = "Diese Folge herunterladen";
|
||||
"Downloaded" = "Heruntergeladen";
|
||||
"Downloaded" = "Geladen";
|
||||
"Downloaded Shows" = "Heruntergeladene Serien";
|
||||
"Downloading" = "Lädt herunter";
|
||||
"Downloads" = "Downloads";
|
||||
|
|
@ -115,6 +118,7 @@
|
|||
"General events and activities." = "Allgemeine Aktivitäten.";
|
||||
"General Preferences" = "Allgemeine Einstellungen";
|
||||
"Hide Splash Screen" = "Startbildschirm ausblenden";
|
||||
"Use Native Tab Bar" = "System Bar verwenden";
|
||||
"HLS video downloading." = "HLS Video-Downloads.";
|
||||
"Hold Speed" = "Geschwindigkeit halten";
|
||||
|
||||
|
|
@ -383,6 +387,12 @@
|
|||
"Library cleared successfully" = "Bibliothek erfolgreich geleert";
|
||||
"All downloads deleted successfully" = "Alle Downloads erfolgreich gelöscht";
|
||||
|
||||
/* TabView */
|
||||
"LibraryTab" = "Bibliothek";
|
||||
"DownloadsTab" = "Downloads";
|
||||
"SettingsTab" = "Einstellungen";
|
||||
"SearchTab" = "Suchen";
|
||||
|
||||
/* New additions */
|
||||
"Recent searches" = "Letzte Suchanfragen";
|
||||
"me frfr" = "Ich, ohne Witz";
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@
|
|||
"Copied to Clipboard" = "Copied to Clipboard";
|
||||
"Copy to Clipboard" = "Copy to Clipboard";
|
||||
"Copy URL" = "Copy URL";
|
||||
"Collections" = "Collections";
|
||||
"No Collections" = "No Collections";
|
||||
"Create a collection to organize your bookmarks" = "Create a collection to organize your bookmarks";
|
||||
|
||||
/* Episodes */
|
||||
"%lld Episodes" = "%lld Episodes";
|
||||
|
|
@ -115,6 +118,7 @@
|
|||
"General events and activities." = "General events and activities.";
|
||||
"General Preferences" = "General Preferences";
|
||||
"Hide Splash Screen" = "Hide Splash Screen";
|
||||
"Use Native Tab Bar" = "Use Native Tabs";
|
||||
"HLS video downloading." = "HLS video downloading.";
|
||||
"Hold Speed" = "Hold Speed";
|
||||
|
||||
|
|
@ -384,6 +388,12 @@
|
|||
"Library cleared successfully" = "Library cleared successfully";
|
||||
"All downloads deleted successfully" = "All downloads deleted successfully";
|
||||
|
||||
/* TabView */
|
||||
"LibraryTab" = "Library";
|
||||
"DownloadsTab" = "Downloads";
|
||||
"SettingsTab" = "Settings";
|
||||
"SearchTab" = "Search";
|
||||
|
||||
/* New additions */
|
||||
"Recent searches" = "Recent searches";
|
||||
"me frfr" = "me frfr";
|
||||
|
|
|
|||
|
|
@ -23,12 +23,17 @@ class DownloadManager: NSObject, ObservableObject {
|
|||
}
|
||||
|
||||
private func initializeDownloadSession() {
|
||||
#if targetEnvironment(simulator)
|
||||
Logger.shared.log("Download Sessions are not available on Simulator", type: "Error")
|
||||
#else
|
||||
let configuration = URLSessionConfiguration.background(withIdentifier: "hls-downloader")
|
||||
|
||||
assetDownloadURLSession = AVAssetDownloadURLSession(
|
||||
configuration: configuration,
|
||||
assetDownloadDelegate: self,
|
||||
delegateQueue: .main
|
||||
)
|
||||
#endif
|
||||
}
|
||||
|
||||
func downloadAsset(from url: URL) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ extension JSController {
|
|||
private static var progressUpdateTimer: Timer?
|
||||
|
||||
func initializeDownloadSession() {
|
||||
#if targetEnvironment(simulator)
|
||||
Logger.shared.log("Download Sessions are not available on Simulator", type: "Error")
|
||||
#else
|
||||
// Create a unique identifier for the background session
|
||||
let sessionIdentifier = "hls-downloader-\(UUID().uuidString)"
|
||||
|
||||
|
|
@ -61,6 +64,8 @@ extension JSController {
|
|||
)
|
||||
|
||||
print("Download session initialized with ID: \(sessionIdentifier)")
|
||||
#endif
|
||||
|
||||
loadSavedAssets()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,7 +227,6 @@ struct TabBar: View {
|
|||
}
|
||||
}
|
||||
}) {
|
||||
if tab.title.isEmpty {
|
||||
Image(systemName: tab.icon + (selectedTab == index ? ".fill" : ""))
|
||||
.frame(width: 28, height: 28)
|
||||
.matchedGeometryEffect(id: tab.icon, in: animation)
|
||||
|
|
@ -236,24 +235,6 @@ struct TabBar: View {
|
|||
.padding(.horizontal, 10)
|
||||
.frame(width: 70)
|
||||
.opacity(selectedTab == index ? 1 : 0.5)
|
||||
} else {
|
||||
VStack {
|
||||
Image(systemName: tab.icon + (selectedTab == index ? ".fill" : ""))
|
||||
.frame(width: 36, height: 18)
|
||||
.matchedGeometryEffect(id: tab.icon, in: animation)
|
||||
.foregroundStyle(selectedTab == index ? .black : .gray)
|
||||
|
||||
Text(tab.title)
|
||||
.font(.caption)
|
||||
.frame(width: 60)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal, 10)
|
||||
.frame(width: 80)
|
||||
.opacity(selectedTab == index ? 1 : 0.5)
|
||||
}
|
||||
}
|
||||
.background(
|
||||
selectedTab == index ?
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ struct SettingsViewGeneral: View {
|
|||
@AppStorage("fetchEpisodeMetadata") private var fetchEpisodeMetadata: Bool = true
|
||||
@AppStorage("analyticsEnabled") private var analyticsEnabled: Bool = false
|
||||
@AppStorage("hideSplashScreen") private var hideSplashScreenEnable: Bool = false
|
||||
@AppStorage("useNativeTabBar") private var useNativeTabBar: Bool = false
|
||||
@AppStorage("metadataProvidersOrder") private var metadataProvidersOrderData: Data = {
|
||||
try! JSONEncoder().encode(["TMDB","AniList"])
|
||||
}()
|
||||
|
|
@ -172,6 +173,10 @@ struct SettingsViewGeneral: View {
|
|||
@EnvironmentObject var settings: Settings
|
||||
@State private var showRestartAlert = false
|
||||
|
||||
private let isiOS26OrLater: Bool = {
|
||||
if #available(iOS 26, *) { return true } else { return false }
|
||||
}()
|
||||
|
||||
var body: some View {
|
||||
ScrollView(showsIndicators: false) {
|
||||
VStack(spacing: 24) {
|
||||
|
|
@ -194,9 +199,18 @@ struct SettingsViewGeneral: View {
|
|||
icon: "wand.and.rays.inverse",
|
||||
title: NSLocalizedString("Hide Splash Screen", comment: ""),
|
||||
isOn: $hideSplashScreenEnable,
|
||||
showDivider: isiOS26OrLater
|
||||
)
|
||||
|
||||
if isiOS26OrLater {
|
||||
SettingsToggleRow(
|
||||
icon: "inset.filled.bottomthird.rectangle",
|
||||
title: NSLocalizedString("Use Native Tab Bar", comment: ""),
|
||||
isOn: $useNativeTabBar,
|
||||
showDivider: false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SettingsSection(title: NSLocalizedString("Language", comment: "")) {
|
||||
SettingsPickerRow(
|
||||
|
|
|
|||
Loading…
Reference in a new issue