From b2fb9fbe2b05dcf2f263191625fea30889528ae3 Mon Sep 17 00:00:00 2001 From: Ethan Pippin Date: Fri, 15 Oct 2021 09:35:32 -0600 Subject: [PATCH] Add BasicAppSettingsView, refactor, and organize --- JellyfinPlayer.xcodeproj/project.pbxproj | 46 +++++++++++++++--- JellyfinPlayer/JellyfinPlayer.entitlements | 8 ---- .../Views/BasicAppSettingsView.swift | 47 +++++++++++++++++++ JellyfinPlayer/Views/ServerListView.swift | 18 ++++++- JellyfinPlayer/Views/SettingsView.swift | 6 +-- .../BasicAppSettingsCoordinator.swift | 23 +++++++++ .../ConnectToServerCoodinator.swift | 1 + Shared/Coordinators/FilterCoordinator.swift | 2 + Shared/Coordinators/HomeCoordinator.swift | 1 + Shared/Coordinators/ItemCoordinator.swift | 1 + Shared/Coordinators/LibraryCoordinator.swift | 5 +- .../Coordinators/LibraryListCoordinator.swift | 1 + Shared/Coordinators/SearchCoordinator.swift | 3 +- .../Coordinators/ServerListCoordinator.swift | 6 +++ Shared/Coordinators/SettingsCoordinator.swift | 1 + Shared/Coordinators/UserListCoordinator.swift | 1 + .../Coordinators/UserSignInCoordinator.swift | 1 + .../Coordinators/VideoPlayerCoordinator.swift | 4 +- Shared/Objects/AppAppearance.swift | 32 +++++++++++++ Shared/Objects/Bitrates.swift | 15 ++++++ Shared/Objects/TrackLanguage.swift | 17 +++++++ .../BasicAppSettingsViewModel.swift | 16 +++++++ Shared/ViewModels/SettingsViewModel.swift | 42 ----------------- WidgetExtension/WidgetExtension.entitlements | 8 +--- 24 files changed, 232 insertions(+), 73 deletions(-) create mode 100644 JellyfinPlayer/Views/BasicAppSettingsView.swift create mode 100644 Shared/Coordinators/BasicAppSettingsCoordinator.swift create mode 100644 Shared/Objects/AppAppearance.swift create mode 100644 Shared/Objects/Bitrates.swift create mode 100644 Shared/Objects/TrackLanguage.swift create mode 100644 Shared/ViewModels/BasicAppSettingsViewModel.swift diff --git a/JellyfinPlayer.xcodeproj/project.pbxproj b/JellyfinPlayer.xcodeproj/project.pbxproj index 0785991d..798012e5 100644 --- a/JellyfinPlayer.xcodeproj/project.pbxproj +++ b/JellyfinPlayer.xcodeproj/project.pbxproj @@ -318,6 +318,17 @@ E1AD105C26D9ABDD003E4A08 /* PillHStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105B26D9ABDD003E4A08 /* PillHStackView.swift */; }; E1AD105F26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */; }; E1AD106226D9B7CD003E4A08 /* ItemPortraitHeaderOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1AD106126D9B7CD003E4A08 /* ItemPortraitHeaderOverlayView.swift */; }; + E1D4BF7C2719D05000A11E64 /* BasicAppSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF7B2719D05000A11E64 /* BasicAppSettingsView.swift */; }; + E1D4BF7E2719D1DD00A11E64 /* BasicAppSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF7D2719D1DC00A11E64 /* BasicAppSettingsViewModel.swift */; }; + E1D4BF7F2719D1DD00A11E64 /* BasicAppSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF7D2719D1DC00A11E64 /* BasicAppSettingsViewModel.swift */; }; + E1D4BF812719D22800A11E64 /* AppAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF802719D22800A11E64 /* AppAppearance.swift */; }; + E1D4BF822719D22800A11E64 /* AppAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF802719D22800A11E64 /* AppAppearance.swift */; }; + E1D4BF842719D25A00A11E64 /* TrackLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF832719D25A00A11E64 /* TrackLanguage.swift */; }; + E1D4BF852719D25A00A11E64 /* TrackLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF832719D25A00A11E64 /* TrackLanguage.swift */; }; + E1D4BF872719D27100A11E64 /* Bitrates.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF862719D27100A11E64 /* Bitrates.swift */; }; + E1D4BF882719D27100A11E64 /* Bitrates.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF862719D27100A11E64 /* Bitrates.swift */; }; + E1D4BF8A2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF892719D3D000A11E64 /* BasicAppSettingsCoordinator.swift */; }; + E1D4BF8B2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF892719D3D000A11E64 /* BasicAppSettingsCoordinator.swift */; }; E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; }; E1F0204F26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; }; E1FCD08826C35A0D007C8DCF /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD08726C35A0D007C8DCF /* NetworkError.swift */; }; @@ -499,7 +510,6 @@ 628B95282670CABE0091AF3B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 628B952A2670CABE0091AF3B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 628B95362670CB800091AF3B /* JellyfinWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinWidget.swift; sourceTree = ""; }; - 628B953B2670D1FC0091AF3B /* WidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WidgetExtension.entitlements; sourceTree = ""; }; 62C29E9E26D1016600C1D2E7 /* iOSMainCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSMainCoordinator.swift; sourceTree = ""; }; 62C29EA026D102A500C1D2E7 /* iOSMainTabCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSMainTabCoordinator.swift; sourceTree = ""; }; 62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectToServerCoodinator.swift; sourceTree = ""; }; @@ -566,6 +576,12 @@ E1AD105B26D9ABDD003E4A08 /* PillHStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillHStackView.swift; sourceTree = ""; }; E1AD105E26D9ADDD003E4A08 /* NameGUIDPairExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NameGUIDPairExtensions.swift; sourceTree = ""; }; E1AD106126D9B7CD003E4A08 /* ItemPortraitHeaderOverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPortraitHeaderOverlayView.swift; sourceTree = ""; }; + E1D4BF7B2719D05000A11E64 /* BasicAppSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicAppSettingsView.swift; sourceTree = ""; }; + E1D4BF7D2719D1DC00A11E64 /* BasicAppSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicAppSettingsViewModel.swift; sourceTree = ""; }; + E1D4BF802719D22800A11E64 /* AppAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAppearance.swift; sourceTree = ""; }; + E1D4BF832719D25A00A11E64 /* TrackLanguage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackLanguage.swift; sourceTree = ""; }; + E1D4BF862719D27100A11E64 /* Bitrates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bitrates.swift; sourceTree = ""; }; + E1D4BF892719D3D000A11E64 /* BasicAppSettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicAppSettingsCoordinator.swift; sourceTree = ""; }; E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerJumpLength.swift; sourceTree = ""; }; E1FCD08726C35A0D007C8DCF /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; E1FCD09526C47118007C8DCF /* ErrorMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorMessage.swift; sourceTree = ""; }; @@ -654,6 +670,7 @@ 532175392671BCED005491E6 /* ViewModels */ = { isa = PBXGroup; children = ( + E1D4BF7D2719D1DC00A11E64 /* BasicAppSettingsViewModel.swift */, 625CB5762678C34300530A6E /* ConnectToServerViewModel.swift */, 62E632E5267D3F5B0063E547 /* EpisodeItemViewModel.swift */, 625CB5722678C32A00530A6E /* HomeViewModel.swift */, @@ -770,11 +787,14 @@ 535870AB2669D8D300D05A09 /* Objects */ = { isa = PBXGroup; children = ( + E1D4BF802719D22800A11E64 /* AppAppearance.swift */, + E1D4BF862719D27100A11E64 /* Bitrates.swift */, E1AD104926D94822003E4A08 /* DetailItem.swift */, 53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */, 62EC353326766B03000E9F2D /* DeviceRotationViewModifier.swift */, - E193D4D727193CAC00900D82 /* PortraitImageStackable.swift */, E193D4DA27193CCA00900D82 /* PillStackable.swift */, + E193D4D727193CAC00900D82 /* PortraitImageStackable.swift */, + E1D4BF832719D25A00A11E64 /* TrackLanguage.swift */, 535870AC2669D8DD00D05A09 /* Typings.swift */, E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */, ); @@ -1019,7 +1039,6 @@ 628B95252670CABD0091AF3B /* WidgetExtension */ = { isa = PBXGroup; children = ( - 628B953B2670D1FC0091AF3B /* WidgetExtension.entitlements */, 628B95362670CB800091AF3B /* JellyfinWidget.swift */, 628B95262670CABD0091AF3B /* NextUpWidget.swift */, 628B95282670CABE0091AF3B /* Assets.xcassets */, @@ -1032,6 +1051,7 @@ isa = PBXGroup; children = ( 62C29EA226D1030F00C1D2E7 /* ConnectToServerCoodinator.swift */, + E1D4BF892719D3D000A11E64 /* BasicAppSettingsCoordinator.swift */, 6220D0B926D6092100B8E046 /* FilterCoordinator.swift */, 62C29EA526D1036A00C1D2E7 /* HomeCoordinator.swift */, E193D5412719404B00900D82 /* MainCoordinator */, @@ -1143,6 +1163,7 @@ E13DD3D027165886009D4DAF /* Views */ = { isa = PBXGroup; children = ( + E1D4BF7B2719D05000A11E64 /* BasicAppSettingsView.swift */, 5338F74D263B61370014BF09 /* ConnectToServerView.swift */, 5389276D263C25100035E14B /* ContinueWatchingView.swift */, 625CB56E2678C23300530A6E /* HomeView.swift */, @@ -1631,6 +1652,7 @@ 53116A17268B919A003024C9 /* SeriesItemView.swift in Sources */, E13DD3F027178F87009D4DAF /* SwiftfinNotificationCenter.swift in Sources */, 531690E7267ABD79005D8AB9 /* HomeView.swift in Sources */, + E1D4BF8B2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */, E13DD3FA2717E961009D4DAF /* UserListViewModel.swift in Sources */, 53ABFDDE267974E300886593 /* SplashView.swift in Sources */, 53ABFDE8267974EF00886593 /* SplashViewModel.swift in Sources */, @@ -1672,6 +1694,7 @@ E193D53927193F8E00900D82 /* SearchCoordinator.swift in Sources */, E193D4D927193CAC00900D82 /* PortraitImageStackable.swift in Sources */, 535870A52669D8AE00D05A09 /* ParallaxHeader.swift in Sources */, + E1D4BF852719D25A00A11E64 /* TrackLanguage.swift in Sources */, 53272532268BF09D0035FBF1 /* MediaViewActionButton.swift in Sources */, 531690F0267ABF72005D8AB9 /* NextUpView.swift in Sources */, E193D53427193F7F00900D82 /* HomeCoordinator.swift in Sources */, @@ -1686,6 +1709,7 @@ 5310695B2684E7EE00CFFDBA /* AudioView.swift in Sources */, 5398514726B64E4100101B49 /* SearchBarView.swift in Sources */, 091B5A8D268315D400D78B61 /* ServerDiscovery.swift in Sources */, + E1D4BF882719D27100A11E64 /* Bitrates.swift in Sources */, E193D5432719407E00900D82 /* tvOSMainCoordinator.swift in Sources */, 53ABFDE7267974EF00886593 /* ConnectToServerViewModel.swift in Sources */, 5398514626B64DBB00101B49 /* SearchablePickerView.swift in Sources */, @@ -1699,6 +1723,7 @@ 53ABFDE5267974EF00886593 /* ViewModel.swift in Sources */, C45B29BB26FAC5B600CEF5E0 /* ColorExtension.swift in Sources */, 531069582684E7EE00CFFDBA /* MediaInfoView.swift in Sources */, + E1D4BF822719D22800A11E64 /* AppAppearance.swift in Sources */, 53272537268C1DBB0035FBF1 /* SeasonItemView.swift in Sources */, 09389CC526814E4500AE350E /* DeviceProfileBuilder.swift in Sources */, E193D53C27193F9500900D82 /* UserListCoordinator.swift in Sources */, @@ -1717,6 +1742,7 @@ 536D3D74267BA8170004248C /* BackgroundManager.swift in Sources */, 535870632669D21600D05A09 /* JellyfinPlayer_tvOSApp.swift in Sources */, E193D547271941C500900D82 /* UserListView.swift in Sources */, + E1D4BF7F2719D1DD00A11E64 /* BasicAppSettingsViewModel.swift in Sources */, E193D53227193F7B00900D82 /* ConnectToServerCoodinator.swift in Sources */, 53ABFDE4267974EF00886593 /* LibraryListViewModel.swift in Sources */, 5364F456266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */, @@ -1736,6 +1762,7 @@ 5364F455266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */, E18845F526DD631E00B0C5B7 /* BaseItemDto+Stackable.swift in Sources */, 5364F455266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */, + E1D4BF7E2719D1DD00A11E64 /* BasicAppSettingsViewModel.swift in Sources */, 6220D0B426D5ED8000B8E046 /* LibraryCoordinator.swift in Sources */, 6220D0C026D61C5000B8E046 /* ItemCoordinator.swift in Sources */, E13DD3F227179378009D4DAF /* UserSignInCoordinator.swift in Sources */, @@ -1796,11 +1823,13 @@ 6220D0CC26D640C400B8E046 /* AppURLHandler.swift in Sources */, 62E632F3267D54030063E547 /* ItemViewModel.swift in Sources */, 53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */, + E1D4BF842719D25A00A11E64 /* TrackLanguage.swift in Sources */, E14F7D0726DB36EF007C3AE6 /* ItemPortraitMainView.swift in Sources */, E1AD106226D9B7CD003E4A08 /* ItemPortraitHeaderOverlayView.swift in Sources */, 53E4E649263F725B00F67C6B /* MultiSelectorView.swift in Sources */, 6220D0C626D62D8700B8E046 /* VideoPlayerCoordinator.swift in Sources */, E11B1B6C2718CD68006DA3E8 /* JellyfinAPIError.swift in Sources */, + E1D4BF812719D22800A11E64 /* AppAppearance.swift in Sources */, 621338B32660A07800A81A2A /* LazyView.swift in Sources */, 6220D0B126D5EC9900B8E046 /* SettingsCoordinator.swift in Sources */, 62C29EA626D1036A00C1D2E7 /* HomeCoordinator.swift in Sources */, @@ -1813,6 +1842,7 @@ E193D4DB27193CCA00900D82 /* PillStackable.swift in Sources */, E193D4D827193CAC00900D82 /* PortraitImageStackable.swift in Sources */, 624C21752685CF60007F1390 /* SearchablePickerView.swift in Sources */, + E1D4BF7C2719D05000A11E64 /* BasicAppSettingsView.swift in Sources */, E173DA5026D048D600CC4EB7 /* ServerDetailView.swift in Sources */, 62EC352F267666A5000E9F2D /* SessionManager.swift in Sources */, 62E632E3267D3BA60063E547 /* MovieItemViewModel.swift in Sources */, @@ -1828,10 +1858,12 @@ 6267B3DA2671138200A7371D /* ImageExtensions.swift in Sources */, 62EC353426766B03000E9F2D /* DeviceRotationViewModifier.swift in Sources */, 5389277C263CC3DB0035E14B /* BlurHashDecode.swift in Sources */, + E1D4BF8A2719D3D000A11E64 /* BasicAppSettingsCoordinator.swift in Sources */, E13DD3F92717E961009D4DAF /* UserListViewModel.swift in Sources */, 539B2DA5263BA5B8007FF1A4 /* SettingsView.swift in Sources */, 5338F74E263B61370014BF09 /* ConnectToServerView.swift in Sources */, 09389CC726819B4600AE350E /* VideoPlayerModel.swift in Sources */, + E1D4BF872719D27100A11E64 /* Bitrates.swift in Sources */, 6220D0B726D5EE1100B8E046 /* SearchCoordinator.swift in Sources */, E13DD3EF27178F87009D4DAF /* SwiftfinNotificationCenter.swift in Sources */, 5377CBF5263B596A003A4E83 /* JellyfinPlayerApp.swift in Sources */, @@ -2205,7 +2237,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 60; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 9R8RREG67J; + DEVELOPMENT_TEAM = TY84JMYEFE; ENABLE_BITCODE = NO; ENABLE_PREVIEWS = YES; EXCLUDED_ARCHS = ""; @@ -2217,7 +2249,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0.0; - PRODUCT_BUNDLE_IDENTIFIER = me.vigue.jellyfin; + PRODUCT_BUNDLE_IDENTIFIER = pips.swiftfin; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SUPPORTS_MACCATALYST = NO; @@ -2273,7 +2305,7 @@ CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 60; - DEVELOPMENT_TEAM = 9R8RREG67J; + DEVELOPMENT_TEAM = TY84JMYEFE; INFOPLIST_FILE = WidgetExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -2282,7 +2314,7 @@ "@executable_path/../../Frameworks", ); MARKETING_VERSION = 1.0.0; - PRODUCT_BUNDLE_IDENTIFIER = me.vigue.jellyfin.widget; + PRODUCT_BUNDLE_IDENTIFIER = pips.swiftfin.widget; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; diff --git a/JellyfinPlayer/JellyfinPlayer.entitlements b/JellyfinPlayer/JellyfinPlayer.entitlements index 77250fef..bc04cfb9 100644 --- a/JellyfinPlayer/JellyfinPlayer.entitlements +++ b/JellyfinPlayer/JellyfinPlayer.entitlements @@ -2,14 +2,6 @@ - com.apple.developer.coremedia.hls.low-latency - - com.apple.security.app-sandbox - - com.apple.security.application-groups - - group.me.vigue.jellyfin.mobileclient - com.apple.security.network.client diff --git a/JellyfinPlayer/Views/BasicAppSettingsView.swift b/JellyfinPlayer/Views/BasicAppSettingsView.swift new file mode 100644 index 00000000..db04156b --- /dev/null +++ b/JellyfinPlayer/Views/BasicAppSettingsView.swift @@ -0,0 +1,47 @@ +// + /* + * SwiftFin is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright 2021 Aiden Vigue & Jellyfin Contributors + */ + +import Defaults +import Stinsen +import SwiftUI + +struct BasicAppSettingsView: View { + + @EnvironmentObject var basicAppSettingsRouter: BasicAppSettingsCoordinator.Router + @ObservedObject var viewModel: BasicAppSettingsViewModel + + @Default(.appAppearance) var appAppearance + + var body: some View { + Form { + Section { + Picker(NSLocalizedString("Appearance", comment: ""), selection: $appAppearance) { + ForEach(self.viewModel.appearances, id: \.self) { appearance in + Text(appearance.localizedName).tag(appearance.rawValue) + } + }.onChange(of: appAppearance, perform: { _ in + UIApplication.shared.windows.first?.overrideUserInterfaceStyle = appAppearance.style + }) + } header: { + Text("Accessibility") + } + + } + .navigationBarTitle("Settings", displayMode: .inline) + .toolbar { + ToolbarItemGroup(placement: .navigationBarLeading) { + Button { + basicAppSettingsRouter.dismissCoordinator() + } label: { + Image(systemName: "xmark.circle.fill") + } + } + } + } +} diff --git a/JellyfinPlayer/Views/ServerListView.swift b/JellyfinPlayer/Views/ServerListView.swift index 7460dfd6..f2c2a6b3 100644 --- a/JellyfinPlayer/Views/ServerListView.swift +++ b/JellyfinPlayer/Views/ServerListView.swift @@ -102,7 +102,7 @@ struct ServerListView: View { } @ViewBuilder - private var toolbarContent: some View { + private var trailingToolbarContent: some View { if viewModel.servers.isEmpty { EmptyView() } else { @@ -114,14 +114,28 @@ struct ServerListView: View { } } + @ViewBuilder + private var leadingToolbarContent: some View { + Button { + serverListRouter.route(to: \.basicAppSettings) + } label: { + Image(systemName: "gear") + } + } + var body: some View { innerBody .navigationTitle("Servers") .toolbar { ToolbarItemGroup(placement: .navigationBarTrailing) { - toolbarContent + trailingToolbarContent } } + .toolbar(content: { + ToolbarItemGroup(placement: .navigationBarLeading) { + leadingToolbarContent + } + }) .onAppear { viewModel.fetchServers() } diff --git a/JellyfinPlayer/Views/SettingsView.swift b/JellyfinPlayer/Views/SettingsView.swift index 9e353407..7b7a9ff5 100644 --- a/JellyfinPlayer/Views/SettingsView.swift +++ b/JellyfinPlayer/Views/SettingsView.swift @@ -11,9 +11,8 @@ import Stinsen import SwiftUI struct SettingsView: View { + @EnvironmentObject var settingsRouter: SettingsCoordinator.Router - @Environment(\.managedObjectContext) private var viewContext - @ObservedObject var viewModel: SettingsViewModel @Default(.inNetworkBandwidth) var inNetworkStreamBitrate @@ -82,6 +81,7 @@ struct SettingsView: View { .font(.callout) } } + Section(header: Text("Playback")) { Picker("Default local quality", selection: $inNetworkStreamBitrate) { ForEach(self.viewModel.bitrates, id: \.self) { bitrate in @@ -144,7 +144,7 @@ struct SettingsView: View { Button { settingsRouter.dismissCoordinator() } label: { - Image(systemName: "xmark") + Image(systemName: "xmark.circle.fill") } } } diff --git a/Shared/Coordinators/BasicAppSettingsCoordinator.swift b/Shared/Coordinators/BasicAppSettingsCoordinator.swift new file mode 100644 index 00000000..d9ee38bb --- /dev/null +++ b/Shared/Coordinators/BasicAppSettingsCoordinator.swift @@ -0,0 +1,23 @@ +// + /* + * SwiftFin is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright 2021 Aiden Vigue & Jellyfin Contributors + */ + +import Foundation +import Stinsen +import SwiftUI + +final class BasicAppSettingsCoordinator: NavigationCoordinatable { + + let stack = NavigationStack(initial: \BasicAppSettingsCoordinator.start) + + @Root var start = makeStart + + @ViewBuilder func makeStart() -> some View { + BasicAppSettingsView(viewModel: BasicAppSettingsViewModel()) + } +} diff --git a/Shared/Coordinators/ConnectToServerCoodinator.swift b/Shared/Coordinators/ConnectToServerCoodinator.swift index 20c4a862..45d47f03 100644 --- a/Shared/Coordinators/ConnectToServerCoodinator.swift +++ b/Shared/Coordinators/ConnectToServerCoodinator.swift @@ -12,6 +12,7 @@ import Stinsen import SwiftUI final class ConnectToServerCoodinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \ConnectToServerCoodinator.start) @Root var start = makeStart diff --git a/Shared/Coordinators/FilterCoordinator.swift b/Shared/Coordinators/FilterCoordinator.swift index 48496d14..fa845d0c 100644 --- a/Shared/Coordinators/FilterCoordinator.swift +++ b/Shared/Coordinators/FilterCoordinator.swift @@ -14,7 +14,9 @@ import SwiftUI typealias FilterCoordinatorParams = (filters: Binding, enabledFilterType: [FilterType], parentId: String) final class FilterCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \FilterCoordinator.start) + @Root var start = makeStart @Binding var filters: LibraryFilters diff --git a/Shared/Coordinators/HomeCoordinator.swift b/Shared/Coordinators/HomeCoordinator.swift index be38b278..31837271 100644 --- a/Shared/Coordinators/HomeCoordinator.swift +++ b/Shared/Coordinators/HomeCoordinator.swift @@ -13,6 +13,7 @@ import Stinsen import SwiftUI final class HomeCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \HomeCoordinator.start) @Root var start = makeStart diff --git a/Shared/Coordinators/ItemCoordinator.swift b/Shared/Coordinators/ItemCoordinator.swift index d8f4588f..5e578efb 100644 --- a/Shared/Coordinators/ItemCoordinator.swift +++ b/Shared/Coordinators/ItemCoordinator.swift @@ -13,6 +13,7 @@ import Stinsen import SwiftUI final class ItemCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \ItemCoordinator.start) @Root var start = makeStart diff --git a/Shared/Coordinators/LibraryCoordinator.swift b/Shared/Coordinators/LibraryCoordinator.swift index 47f45978..c90234c5 100644 --- a/Shared/Coordinators/LibraryCoordinator.swift +++ b/Shared/Coordinators/LibraryCoordinator.swift @@ -15,6 +15,7 @@ import SwiftUI typealias LibraryCoordinatorParams = (viewModel: LibraryViewModel, title: String) final class LibraryCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \LibraryCoordinator.start) @Root var start = makeStart @@ -22,8 +23,8 @@ final class LibraryCoordinator: NavigationCoordinatable { @Route(.modal) var filter = makeFilter @Route(.push) var item = makeItem - var viewModel: LibraryViewModel - var title: String + let viewModel: LibraryViewModel + let title: String init(viewModel: LibraryViewModel, title: String) { self.viewModel = viewModel diff --git a/Shared/Coordinators/LibraryListCoordinator.swift b/Shared/Coordinators/LibraryListCoordinator.swift index 2ff63ad5..88377644 100644 --- a/Shared/Coordinators/LibraryListCoordinator.swift +++ b/Shared/Coordinators/LibraryListCoordinator.swift @@ -12,6 +12,7 @@ import Stinsen import SwiftUI final class LibraryListCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \LibraryListCoordinator.start) @Root var start = makeStart diff --git a/Shared/Coordinators/SearchCoordinator.swift b/Shared/Coordinators/SearchCoordinator.swift index 60c761d2..9d66e6b4 100644 --- a/Shared/Coordinators/SearchCoordinator.swift +++ b/Shared/Coordinators/SearchCoordinator.swift @@ -13,12 +13,13 @@ import SwiftUI import JellyfinAPI final class SearchCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \SearchCoordinator.start) @Root var start = makeStart @Route(.push) var item = makeItem - var viewModel: LibrarySearchViewModel + let viewModel: LibrarySearchViewModel init(viewModel: LibrarySearchViewModel) { self.viewModel = viewModel diff --git a/Shared/Coordinators/ServerListCoordinator.swift b/Shared/Coordinators/ServerListCoordinator.swift index c4d75acf..d60abebd 100644 --- a/Shared/Coordinators/ServerListCoordinator.swift +++ b/Shared/Coordinators/ServerListCoordinator.swift @@ -12,11 +12,13 @@ import Stinsen import SwiftUI final class ServerListCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \ServerListCoordinator.start) @Root var start = makeStart @Route(.push) var connectToServer = makeConnectToServer @Route(.push) var userList = makeUserList + @Route(.modal) var basicAppSettings = makeBasicAppSettings func makeConnectToServer() -> ConnectToServerCoodinator { ConnectToServerCoodinator() @@ -26,6 +28,10 @@ final class ServerListCoordinator: NavigationCoordinatable { UserListCoordinator(viewModel: .init(server: server)) } + func makeBasicAppSettings() -> NavigationViewCoordinator { + NavigationViewCoordinator(BasicAppSettingsCoordinator()) + } + @ViewBuilder func makeStart() -> some View { ServerListView(viewModel: ServerListViewModel()) } diff --git a/Shared/Coordinators/SettingsCoordinator.swift b/Shared/Coordinators/SettingsCoordinator.swift index cbf6b1e0..0b8f8a23 100644 --- a/Shared/Coordinators/SettingsCoordinator.swift +++ b/Shared/Coordinators/SettingsCoordinator.swift @@ -12,6 +12,7 @@ import Stinsen import SwiftUI final class SettingsCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \SettingsCoordinator.start) @Root var start = makeStart diff --git a/Shared/Coordinators/UserListCoordinator.swift b/Shared/Coordinators/UserListCoordinator.swift index 5409f4af..ff728bb6 100644 --- a/Shared/Coordinators/UserListCoordinator.swift +++ b/Shared/Coordinators/UserListCoordinator.swift @@ -12,6 +12,7 @@ import Stinsen import SwiftUI final class UserListCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \UserListCoordinator.start) @Root var start = makeStart diff --git a/Shared/Coordinators/UserSignInCoordinator.swift b/Shared/Coordinators/UserSignInCoordinator.swift index 83cf6cd7..f4e03a87 100644 --- a/Shared/Coordinators/UserSignInCoordinator.swift +++ b/Shared/Coordinators/UserSignInCoordinator.swift @@ -12,6 +12,7 @@ import Stinsen import SwiftUI final class UserSignInCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \UserSignInCoordinator.start) @Root var start = makeStart diff --git a/Shared/Coordinators/VideoPlayerCoordinator.swift b/Shared/Coordinators/VideoPlayerCoordinator.swift index ebe38123..921d52f9 100644 --- a/Shared/Coordinators/VideoPlayerCoordinator.swift +++ b/Shared/Coordinators/VideoPlayerCoordinator.swift @@ -13,10 +13,12 @@ import Stinsen import SwiftUI final class VideoPlayerCoordinator: NavigationCoordinatable { + let stack = NavigationStack(initial: \VideoPlayerCoordinator.start) @Root var start = makeStart - var item: BaseItemDto + + let item: BaseItemDto init(item: BaseItemDto) { self.item = item diff --git a/Shared/Objects/AppAppearance.swift b/Shared/Objects/AppAppearance.swift new file mode 100644 index 00000000..a3bc58a5 --- /dev/null +++ b/Shared/Objects/AppAppearance.swift @@ -0,0 +1,32 @@ +// + /* + * SwiftFin is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright 2021 Aiden Vigue & Jellyfin Contributors + */ + +import Defaults +import SwiftUI + +enum AppAppearance: String, CaseIterable, Defaults.Serializable { + case system + case dark + case light + + var localizedName: String { + return NSLocalizedString(self.rawValue.capitalized, comment: "") + } + + var style: UIUserInterfaceStyle { + switch self { + case .system: + return .unspecified + case .dark: + return .dark + case .light: + return .light + } + } +} diff --git a/Shared/Objects/Bitrates.swift b/Shared/Objects/Bitrates.swift new file mode 100644 index 00000000..6a07989f --- /dev/null +++ b/Shared/Objects/Bitrates.swift @@ -0,0 +1,15 @@ +// + /* + * SwiftFin is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright 2021 Aiden Vigue & Jellyfin Contributors + */ + +import Foundation + +struct Bitrates: Codable, Hashable { + public var name: String + public var value: Int +} diff --git a/Shared/Objects/TrackLanguage.swift b/Shared/Objects/TrackLanguage.swift new file mode 100644 index 00000000..03833245 --- /dev/null +++ b/Shared/Objects/TrackLanguage.swift @@ -0,0 +1,17 @@ +// + /* + * SwiftFin is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright 2021 Aiden Vigue & Jellyfin Contributors + */ + +import Foundation + +struct TrackLanguage: Hashable { + var name: String + var isoCode: String + + static let auto = TrackLanguage(name: "Auto", isoCode: "Auto") +} diff --git a/Shared/ViewModels/BasicAppSettingsViewModel.swift b/Shared/ViewModels/BasicAppSettingsViewModel.swift new file mode 100644 index 00000000..8da35595 --- /dev/null +++ b/Shared/ViewModels/BasicAppSettingsViewModel.swift @@ -0,0 +1,16 @@ +// + /* + * SwiftFin is subject to the terms of the Mozilla Public + * License, v2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright 2021 Aiden Vigue & Jellyfin Contributors + */ + +import SwiftUI + +final class BasicAppSettingsViewModel: ViewModel { + + let appearances = AppAppearance.allCases + +} diff --git a/Shared/ViewModels/SettingsViewModel.swift b/Shared/ViewModels/SettingsViewModel.swift index 86f6a56a..5cedb82f 100644 --- a/Shared/ViewModels/SettingsViewModel.swift +++ b/Shared/ViewModels/SettingsViewModel.swift @@ -11,48 +11,6 @@ import Foundation import SwiftUI import Defaults -struct UserSettings: Decodable { - var LocalMaxBitrate: Int - var RemoteMaxBitrate: Int - var AutoSelectSubtitles: Bool - var AutoSelectSubtitlesLangcode: String - var SubtitlePositionOffset: Int - var SubtitleFontName: String -} - -struct Bitrates: Codable, Hashable { - public var name: String - public var value: Int -} - -struct TrackLanguage: Hashable { - var name: String - var isoCode: String - - static let auto = TrackLanguage(name: "Auto", isoCode: "Auto") -} - -enum AppAppearance: String, CaseIterable, Defaults.Serializable { - case system - case dark - case light - - var localizedName: String { - return NSLocalizedString(self.rawValue.capitalized, comment: "") - } - - var style: UIUserInterfaceStyle { - switch self { - case .system: - return .unspecified - case .dark: - return .dark - case .light: - return .light - } - } -} - final class SettingsViewModel: ObservableObject { let currentLocale = Locale.current var bitrates: [Bitrates] = [] diff --git a/WidgetExtension/WidgetExtension.entitlements b/WidgetExtension/WidgetExtension.entitlements index b164e1cb..2eb7e333 100644 --- a/WidgetExtension/WidgetExtension.entitlements +++ b/WidgetExtension/WidgetExtension.entitlements @@ -3,12 +3,6 @@ com.apple.security.application-groups - - group.me.vigue.jellyfin.mobileclient - - keychain-access-groups - - $(AppIdentifierPrefix)me.vigue.jellyfin.sharedKeychain - +