From 256b1671c1144c14a0080101636fbbad2608c196 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Sun, 13 Nov 2022 12:14:05 +0100 Subject: [PATCH] Reorder locations settings --- Shared/Settings/AdvancedSettings.swift | 92 --------------- Shared/Settings/InstanceForm.swift | 2 +- Shared/Settings/LocationsSettings.swift | 144 ++++++++++++++++++++++++ Shared/Settings/SettingsView.swift | 23 +++- Yattee.xcodeproj/project.pbxproj | 8 ++ 5 files changed, 172 insertions(+), 97 deletions(-) create mode 100644 Shared/Settings/LocationsSettings.swift diff --git a/Shared/Settings/AdvancedSettings.swift b/Shared/Settings/AdvancedSettings.swift index fd8f3cd8..88db4b95 100644 --- a/Shared/Settings/AdvancedSettings.swift +++ b/Shared/Settings/AdvancedSettings.swift @@ -2,7 +2,6 @@ import Defaults import SwiftUI struct AdvancedSettings: View { - @Default(.instancesManifest) private var instancesManifest @Default(.showMPVPlaybackStats) private var showMPVPlaybackStats @Default(.mpvCacheSecs) private var mpvCacheSecs @Default(.mpvCachePauseWait) private var mpvCachePauseWait @@ -25,12 +24,10 @@ struct AdvancedSettings: View { VStack(alignment: .leading) { #if os(macOS) advancedSettings - locationsSettings Spacer() #else List { advancedSettings - locationsSettings } #if os(iOS) .sheet(isPresented: $presentingShareSheet) { @@ -41,17 +38,9 @@ struct AdvancedSettings: View { #endif #endif } - .onAppear(perform: loadCountries) .onChange(of: countryOfPublicInstances) { newCountry in InstancesManifest.shared.setPublicAccount(newCountry, accounts: accounts, asCurrent: accounts.current?.isPublic ?? true) } - .onChange(of: instancesManifest) { _ in - countryOfPublicInstances = nil - if let account = accounts.current, account.isPublic { - accounts.setCurrent(nil) - } - countries.removeAll() - } .sheet(isPresented: $presentingInstanceForm) { InstanceForm(savedInstanceID: $savedFormInstanceID) } @@ -103,17 +92,6 @@ struct AdvancedSettings: View { logButton } } - - Section(header: manifestHeader) { - TextField("URL", text: $instancesManifest) - Button("Reload manifest", action: loadCountries) - .disabled(instancesManifest.isEmpty) - #if !os(macOS) - .keyboardType(.webSearch) - #endif - .disableAutocorrection(true) - } - .padding(.bottom, 4) } @ViewBuilder var mpvFooter: some View { @@ -137,10 +115,6 @@ struct AdvancedSettings: View { .foregroundColor(.secondary) } - var manifestHeader: some View { - SettingsHeader(text: "Locations Manifest".localized()) - } - var showMPVPlaybackStatsToggle: some View { Toggle("Show playback statistics", isOn: $showMPVPlaybackStats) } @@ -159,72 +133,6 @@ struct AdvancedSettings: View { } #endif - @ViewBuilder var locationsSettings: some View { - if !InstancesManifest.shared.manifestURL.isNil, !countries.isEmpty { - Section(header: SettingsHeader(text: "Public Locations".localized()), footer: countryFooter) { - Picker("Country", selection: $countryOfPublicInstances) { - Text("Don't use public locations").tag(String?.none) - ForEach(countries, id: \.self) { country in - Text(country).tag(Optional(country)) - } - } - #if os(tvOS) - .pickerStyle(.inline) - #endif - .disabled(countries.isEmpty) - - Button { - InstancesManifest.shared.changePublicAccount(accounts, settings: settings) - } label: { - if let account = accounts.current, account.isPublic { - Text("Switch to other public location") - } else { - Text("Switch to public locations") - } - } - .disabled(countryOfPublicInstances.isNil) - } - } - - Section(header: SettingsHeader(text: "Custom Locations".localized())) { - #if os(macOS) - InstancesSettings() - .environmentObject(settings) - #else - ForEach(instances) { instance in - AccountsNavigationLink(instance: instance) - } - addInstanceButton - #endif - } - } - - @ViewBuilder var countryFooter: some View { - if let account = accounts.current { - let locationType = account.isPublic ? (account.country ?? "Unknown") : "Custom".localized() - let description = account.isPublic ? account.url : account.instance?.description ?? "unknown".localized() - - Text("Current: \(locationType)\n\(description)") - .foregroundColor(.secondary) - #if os(macOS) - .padding(.bottom, 10) - #endif - } - } - - func loadCountries() { - InstancesManifest.shared.configure() - InstancesManifest.shared.instancesList?.load() - .onSuccess { response in - if let instances: [ManifestedInstance] = response.typedContent() { - self.countries = instances.map(\.country).unique().sorted() - } - } - .onFailure { _ in - settings.presentAlert(title: "Could not load locations manifest".localized()) - } - } - private var addInstanceButton: some View { Button { presentingInstanceForm = true diff --git a/Shared/Settings/InstanceForm.swift b/Shared/Settings/InstanceForm.swift index 6fe27011..a7d97825 100644 --- a/Shared/Settings/InstanceForm.swift +++ b/Shared/Settings/InstanceForm.swift @@ -74,7 +74,7 @@ struct InstanceForm: View { Group { TextField("Name", text: $name) - TextField("URL", text: $url) + TextField("Address", text: $url) #if !os(macOS) .autocapitalization(.none) diff --git a/Shared/Settings/LocationsSettings.swift b/Shared/Settings/LocationsSettings.swift new file mode 100644 index 00000000..79f7db6f --- /dev/null +++ b/Shared/Settings/LocationsSettings.swift @@ -0,0 +1,144 @@ +import Defaults +import SwiftUI + +struct LocationsSettings: View { + @State private var countries = [String]() + @State private var presentingInstanceForm = false + @State private var savedFormInstanceID: Instance.ID? + + @EnvironmentObject private var accounts + @EnvironmentObject private var navigation + @EnvironmentObject private var model + + @Default(.countryOfPublicInstances) private var countryOfPublicInstances + @Default(.instances) private var instances + @Default(.instancesManifest) private var instancesManifest + + var body: some View { + VStack(alignment: .leading) { + #if os(macOS) + settings + Spacer() + #else + List { + settings + } + #if os(iOS) + .listStyle(.insetGrouped) + #endif + #endif + } + .onAppear(perform: loadCountries) + .onChange(of: countryOfPublicInstances) { newCountry in + InstancesManifest.shared.setPublicAccount(newCountry, accounts: accounts, asCurrent: accounts.current?.isPublic ?? true) + } + .onChange(of: instancesManifest) { _ in + countryOfPublicInstances = nil + if let account = accounts.current, account.isPublic { + accounts.setCurrent(nil) + } + countries.removeAll() + } + .sheet(isPresented: $presentingInstanceForm) { + InstanceForm(savedInstanceID: $savedFormInstanceID) + } + #if os(tvOS) + .frame(maxWidth: 1000) + #endif + .navigationTitle("Locations") + } + + @ViewBuilder var settings: some View { + Section(header: SettingsHeader(text: "Locations Manifest".localized())) { + TextField("URL", text: $instancesManifest) + Button("Reload manifest", action: loadCountries) + .disabled(instancesManifest.isEmpty) + #if !os(macOS) + .keyboardType(.webSearch) + #endif + .disableAutocorrection(true) + } + .padding(.bottom, 4) + + if !InstancesManifest.shared.manifestURL.isNil { + Section(header: SettingsHeader(text: "Public Locations".localized()), footer: countryFooter) { + Picker("Country", selection: $countryOfPublicInstances) { + Text("Don't use public locations").tag(String?.none) + ForEach(countries, id: \.self) { country in + Text(country).tag(Optional(country)) + } + } + #if os(tvOS) + .pickerStyle(.inline) + #endif + .disabled(countries.isEmpty) + + Button { + InstancesManifest.shared.changePublicAccount(accounts, settings: model) + } label: { + if let account = accounts.current, account.isPublic { + Text("Switch to other public location") + } else { + Text("Switch to public locations") + } + } + .disabled(countryOfPublicInstances.isNil) + } + } + + Section(header: SettingsHeader(text: "Custom Locations".localized())) { + #if os(macOS) + InstancesSettings() + .environmentObject(model) + #else + ForEach(instances) { instance in + AccountsNavigationLink(instance: instance) + } + addInstanceButton + #endif + } + } + + @ViewBuilder var countryFooter: some View { + if let account = accounts.current { + let locationType = account.isPublic ? (account.country ?? "Unknown") : "Custom".localized() + let description = account.isPublic ? account.url : account.instance?.description ?? "unknown".localized() + + Text("Current: \(locationType)\n\(description)") + .foregroundColor(.secondary) + #if os(macOS) + .padding(.bottom, 10) + #endif + } + } + + func loadCountries() { + InstancesManifest.shared.configure() + InstancesManifest.shared.instancesList?.load() + .onSuccess { response in + if let instances: [ManifestedInstance] = response.typedContent() { + self.countries = instances.map(\.country).unique().sorted() + } + } + .onFailure { _ in + model.presentAlert(title: "Could not load locations manifest".localized()) + } + } + + private var addInstanceButton: some View { + Button { + presentingInstanceForm = true + } label: { + Label("Add Location...", systemImage: "plus") + } + } +} + +struct LocationsSettings_Previews: PreviewProvider { + static var previews: some View { + LocationsSettings() + .environmentObject(AccountsModel()) + .environmentObject(NavigationModel()) + .environmentObject(SettingsModel()) + } +} diff --git a/Shared/Settings/SettingsView.swift b/Shared/Settings/SettingsView.swift index c8c6ebb0..09e7040d 100644 --- a/Shared/Settings/SettingsView.swift +++ b/Shared/Settings/SettingsView.swift @@ -7,7 +7,7 @@ struct SettingsView: View { #if os(macOS) private enum Tabs: Hashable { - case browsing, player, quality, history, sponsorBlock, advanced, help + case browsing, player, quality, history, sponsorBlock, locations, advanced, help } @State private var selection: Tabs? @@ -75,6 +75,13 @@ struct SettingsView: View { } .tag(Optional(Tabs.sponsorBlock)) } + Form { + LocationsSettings() + } + .tabItem { + Label("Locations", systemImage: "globe") + } + .tag(Optional(Tabs.locations)) Group { AdvancedSettings() @@ -145,6 +152,12 @@ struct SettingsView: View { } } + NavigationLink { + LocationsSettings() + } label: { + Label("Locations", systemImage: "globe") + } + NavigationLink { AdvancedSettings() } label: { @@ -217,10 +230,12 @@ struct SettingsView: View { return 500 case .sponsorBlock: return 700 - case .advanced: - return 750 - case .help: + case .locations: return 600 + case .advanced: + return 250 + case .help: + return 580 } } #endif diff --git a/Yattee.xcodeproj/project.pbxproj b/Yattee.xcodeproj/project.pbxproj index 67c42fe5..95bb4e46 100644 --- a/Yattee.xcodeproj/project.pbxproj +++ b/Yattee.xcodeproj/project.pbxproj @@ -304,6 +304,9 @@ 37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; }; 37484C3226FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; }; 37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C3026FCB8F900287258 /* AccountValidator.swift */; }; + 374924DA2921050B0017D862 /* LocationsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374924D92921050B0017D862 /* LocationsSettings.swift */; }; + 374924DB2921050B0017D862 /* LocationsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374924D92921050B0017D862 /* LocationsSettings.swift */; }; + 374924DC2921050B0017D862 /* LocationsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374924D92921050B0017D862 /* LocationsSettings.swift */; }; 37494EA529200B14000DF176 /* DocumentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37494EA429200B14000DF176 /* DocumentsView.swift */; }; 37494EA729200E0B000DF176 /* DocumentsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37494EA629200E0B000DF176 /* DocumentsModel.swift */; }; 374AB3D728BCAF0000DF56FB /* SeekModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374AB3D628BCAF0000DF56FB /* SeekModel.swift */; }; @@ -1095,6 +1098,7 @@ 37484C2826FC83FF00287258 /* AccountForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountForm.swift; sourceTree = ""; }; 37484C2C26FC844700287258 /* InstanceSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceSettings.swift; sourceTree = ""; }; 37484C3026FCB8F900287258 /* AccountValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountValidator.swift; sourceTree = ""; }; + 374924D92921050B0017D862 /* LocationsSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationsSettings.swift; sourceTree = ""; }; 37494EA429200B14000DF176 /* DocumentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentsView.swift; sourceTree = ""; }; 37494EA629200E0B000DF176 /* DocumentsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentsModel.swift; sourceTree = ""; }; 3749BF6F27ADA135000480FF /* client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = client.h; sourceTree = ""; }; @@ -1814,6 +1818,7 @@ 37BC50A72778A84700510953 /* HistorySettings.swift */, 37484C2426FC83E000287258 /* InstanceForm.swift */, 37484C2C26FC844700287258 /* InstanceSettings.swift */, + 374924D92921050B0017D862 /* LocationsSettings.swift */, 37484C1826FC837400287258 /* PlayerSettings.swift */, 374C053427242D9F009BDDBE /* SponsorBlockSettings.swift */, 376BE50627347B57009AD608 /* SettingsHeader.swift */, @@ -2795,6 +2800,7 @@ 37BD07C82698B71C003EBB87 /* AppTabNavigation.swift in Sources */, 37599F38272B4D740087F250 /* FavoriteButton.swift in Sources */, 3754B01528B7F84D009717C8 /* Constants.swift in Sources */, + 374924DA2921050B0017D862 /* LocationsSettings.swift in Sources */, 378FFBC428660172009E3FBE /* URLParser.swift in Sources */, 3784B23D2728B85300B09468 /* ShareButton.swift in Sources */, 37EAD86B267B9C5600D9E01B /* SponsorBlockAPI.swift in Sources */, @@ -3057,6 +3063,7 @@ 3743CA4F270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */, 374C053C2724614F009BDDBE /* PlayerTVMenu.swift in Sources */, 377FC7DD267A081A00A6BBAF /* PopularView.swift in Sources */, + 374924DB2921050B0017D862 /* LocationsSettings.swift in Sources */, 37192D5828B179D60012EEDD /* ChaptersView.swift in Sources */, 3784CDE327772EE40055BBF2 /* Watch.swift in Sources */, 37E80F3D287B107F00561799 /* VideoDetailsOverlay.swift in Sources */, @@ -3368,6 +3375,7 @@ 37A5DBCA285E371400CA4DD1 /* ControlBackgroundModifier.swift in Sources */, 37E80F46287B7AEC00561799 /* PlayerQueueView.swift in Sources */, 37C0698427260B2100F7F6CB /* ThumbnailsModel.swift in Sources */, + 374924DC2921050B0017D862 /* LocationsSettings.swift in Sources */, 37D6025B28C17375009E8D98 /* PlaybackStatsView.swift in Sources */, 37666BAA27023AF000F869E5 /* AccountSelectionView.swift in Sources */, 3765788B2685471400D4EA09 /* Playlist.swift in Sources */,