From 2efc7b87c435952e1e5cd53a686f799014512c23 Mon Sep 17 00:00:00 2001 From: Justin Mazzocchi <2831158+jzzocc@users.noreply.github.com> Date: Thu, 28 Jan 2021 21:45:15 -0800 Subject: [PATCH] Unnest preferences --- Localizations/Localizable.strings | 16 +- Metatext.xcodeproj/project.pbxproj | 12 -- .../MediaPreferencesViewModel.swift | 13 -- .../PostingReadingPreferencesViewModel.swift | 31 ---- .../View Models/PreferencesViewModel.swift | 21 ++- Views/MediaPreferencesView.swift | 96 ----------- Views/PostingReadingPreferencesView.swift | 60 ------- Views/PreferencesView.swift | 162 +++++++++++++++--- Views/StartupAndSyncingPreferencesView.swift | 52 ------ 9 files changed, 164 insertions(+), 299 deletions(-) delete mode 100644 ViewModels/Sources/ViewModels/View Models/MediaPreferencesViewModel.swift delete mode 100644 ViewModels/Sources/ViewModels/View Models/PostingReadingPreferencesViewModel.swift delete mode 100644 Views/MediaPreferencesView.swift delete mode 100644 Views/PostingReadingPreferencesView.swift delete mode 100644 Views/StartupAndSyncingPreferencesView.swift diff --git a/Localizations/Localizable.strings b/Localizations/Localizable.strings index 902088a..89574e3 100644 --- a/Localizations/Localizable.strings +++ b/Localizations/Localizable.strings @@ -121,8 +121,8 @@ "preferences.media.headers" = "Headers"; "preferences.media.headers.animate" = "Animate headers"; "preferences.media.autoplay" = "Autoplay"; -"preferences.media.autoplay.gifs" = "GIFs"; -"preferences.media.autoplay.videos" = "Videos"; +"preferences.media.autoplay.gifs" = "Autoplay GIFs"; +"preferences.media.autoplay.videos" = "Autoplay videos"; "preferences.media.autoplay.always" = "Always"; "preferences.media.autoplay.wifi" = "On Wi-Fi"; "preferences.media.autoplay.never" = "Never"; @@ -147,13 +147,11 @@ "preferences.notification-types.poll" = "Poll"; "preferences.notification-types.status" = "Status"; "preferences.muted-users" = "Muted Users"; -"preferences.startup-and-syncing" = "Startup and Syncing"; -"preferences.startup-and-syncing.home-timeline" = "Home timeline"; -"preferences.startup-and-syncing.notifications-tab" = "Notifications tab"; -"preferences.startup-and-syncing.position-on-startup" = "Position on startup"; -"preferences.startup-and-syncing.remember-position" = "Remember position"; -"preferences.startup-and-syncing.sync-position" = "Sync position with web and other devices"; -"preferences.startup-and-syncing.newest" = "Load newest"; +"preferences.home-timeline-position-on-startup" = "Home timeline position on startup"; +"preferences.notifications-position-on-startup" = "Notifications position on startup"; +"preferences.position.remember-position" = "Remember position"; +"preferences.position.sync-position" = "Sync position with web and other devices"; +"preferences.position.newest" = "Load newest"; "filters.active" = "Active"; "filters.expired" = "Expired"; "filter.add-new" = "Add New Filter"; diff --git a/Metatext.xcodeproj/project.pbxproj b/Metatext.xcodeproj/project.pbxproj index bbb06f3..e7b978b 100644 --- a/Metatext.xcodeproj/project.pbxproj +++ b/Metatext.xcodeproj/project.pbxproj @@ -44,9 +44,7 @@ D036EBB8259FE29800EC1CFC /* Status+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0849C7E25903C4900A5EBCC /* Status+Extensions.swift */; }; D036EBC2259FE2AD00EC1CFC /* UIVIewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E7AD3825870B13005F5E2D /* UIVIewController+Extensions.swift */; }; D036EBC7259FE2B700EC1CFC /* KingfisherOptionsInfo+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */; }; - D03B1B2A253818F3008F964B /* MediaPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B1B29253818F3008F964B /* MediaPreferencesView.swift */; }; D03D87F425C23C44004DCBB2 /* SecondaryNavigationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03D87F325C23C44004DCBB2 /* SecondaryNavigationTitleView.swift */; }; - D04226FD2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04226FC2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift */; }; D04F9E8E259E9C950081B0C9 /* ViewModels in Frameworks */ = {isa = PBXBuildFile; productRef = D04F9E8D259E9C950081B0C9 /* ViewModels */; }; D05936CF25A8D79800754FDF /* EditAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05936CE25A8D79800754FDF /* EditAttachmentViewController.swift */; }; D05936D025A8D79800754FDF /* EditAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05936CE25A8D79800754FDF /* EditAttachmentViewController.swift */; }; @@ -123,7 +121,6 @@ D0C7D49A24F7616A001EBDBB /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42524F76169001EBDBB /* TableView.swift */; }; D0C7D49B24F7616A001EBDBB /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42624F76169001EBDBB /* PreferencesView.swift */; }; D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42724F76169001EBDBB /* RootView.swift */; }; - D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42824F76169001EBDBB /* PostingReadingPreferencesView.swift */; }; D0C7D49E24F7616A001EBDBB /* SecondaryNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42924F76169001EBDBB /* SecondaryNavigationView.swift */; }; D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */; }; D0C7D4C224F7616A001EBDBB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D0C7D45224F76169001EBDBB /* Assets.xcassets */; }; @@ -239,9 +236,7 @@ D036AA06254B6118009094DF /* NotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = ""; }; D036AA0B254B612B009094DF /* NotificationContentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentConfiguration.swift; sourceTree = ""; }; D036AA16254CA823009094DF /* StatusBodyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBodyView.swift; sourceTree = ""; }; - D03B1B29253818F3008F964B /* MediaPreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreferencesView.swift; sourceTree = ""; }; D03D87F325C23C44004DCBB2 /* SecondaryNavigationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationTitleView.swift; sourceTree = ""; }; - D04226FC2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartupAndSyncingPreferencesView.swift; sourceTree = ""; }; D047FA8C24C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; }; D05936CE25A8D79800754FDF /* EditAttachmentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAttachmentViewController.swift; sourceTree = ""; }; D05936DD25A937EC00754FDF /* EditThumbnailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditThumbnailView.swift; sourceTree = ""; }; @@ -311,7 +306,6 @@ D0C7D42524F76169001EBDBB /* TableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableView.swift; sourceTree = ""; }; D0C7D42624F76169001EBDBB /* PreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = ""; }; D0C7D42724F76169001EBDBB /* RootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = ""; }; - D0C7D42824F76169001EBDBB /* PostingReadingPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostingReadingPreferencesView.swift; sourceTree = ""; }; D0C7D42924F76169001EBDBB /* SecondaryNavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationView.swift; sourceTree = ""; }; D0C7D42D24F76169001EBDBB /* NotificationTypesPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationTypesPreferencesView.swift; sourceTree = ""; }; D0C7D45224F76169001EBDBB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -550,7 +544,6 @@ D0E569DA2529319100FA1D72 /* LoadMoreView.swift */, D035F86E25B7F30E00DC75ED /* MainNavigationView.swift */, D05936FE25AA94EA00754FDF /* MarkAttachmentsSensitiveView.swift */, - D03B1B29253818F3008F964B /* MediaPreferencesView.swift */, D035F8A825B9155900DC75ED /* NewStatusButtonView.swift */, D036AA0B254B612B009094DF /* NotificationContentConfiguration.swift */, D036AA01254B6101009094DF /* NotificationListCell.swift */, @@ -560,7 +553,6 @@ D08B8D812544D80000B1EBEF /* PollOptionButton.swift */, D08B8D8C2544E6EC00B1EBEF /* PollResultView.swift */, D08B8D71254246E200B1EBEF /* PollView.swift */, - D0C7D42824F76169001EBDBB /* PostingReadingPreferencesView.swift */, D0C7D42624F76169001EBDBB /* PreferencesView.swift */, D0B32F4F250B373600311912 /* RegistrationView.swift */, D0DD50CA256B1F24004A04F7 /* ReportView.swift */, @@ -569,7 +561,6 @@ D035F8C625B96A4000DC75ED /* SecondaryNavigationButton.swift */, D03D87F325C23C44004DCBB2 /* SecondaryNavigationTitleView.swift */, D0C7D42924F76169001EBDBB /* SecondaryNavigationView.swift */, - D04226FC2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift */, D0625E55250F086B00502611 /* Status */, D0C7D42524F76169001EBDBB /* TableView.swift */, D0D2AC5225BCD2BA003D5DF2 /* TagContentConfiguration.swift */, @@ -872,7 +863,6 @@ D021A63625C38ADB008A0C0D /* AcknowledgmentsView.swift in Sources */, D07EC7CF25B13921006DF726 /* PickerEmoji+Extensions.swift in Sources */, D00702292555E51200F38136 /* ConversationListCell.swift in Sources */, - D03B1B2A253818F3008F964B /* MediaPreferencesView.swift in Sources */, D021A5F625C34538008A0C0D /* IdentitiesViewController.swift in Sources */, D07EC7DC25B13DBB006DF726 /* EmojiCollectionViewCell.swift in Sources */, D0C7D49C24F7616A001EBDBB /* RootView.swift in Sources */, @@ -910,7 +900,6 @@ D0625E59250F092900502611 /* StatusListCell.swift in Sources */, D0E569DB2529319100FA1D72 /* LoadMoreView.swift in Sources */, D05936FF25AA94EA00754FDF /* MarkAttachmentsSensitiveView.swift in Sources */, - D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */, D07EC7E325B13DD3006DF726 /* EmojiContentConfiguration.swift in Sources */, D0B5FE9B251583DB00478838 /* ProfileCollection+Extensions.swift in Sources */, D021A61A25C36C1A008A0C0D /* IdentityContentConfiguration.swift in Sources */, @@ -953,7 +942,6 @@ D05936E925AA3F3D00754FDF /* EditAttachmentView.swift in Sources */, D035F8C725B96A4000DC75ED /* SecondaryNavigationButton.swift in Sources */, D0EA59482522B8B600804347 /* ViewConstants.swift in Sources */, - D04226FD2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift in Sources */, D036AA0C254B612B009094DF /* NotificationContentConfiguration.swift in Sources */, D08B8D3D253F929E00B1EBEF /* ImageViewController.swift in Sources */, D035F86925B7F2ED00DC75ED /* MainNavigationViewController.swift in Sources */, diff --git a/ViewModels/Sources/ViewModels/View Models/MediaPreferencesViewModel.swift b/ViewModels/Sources/ViewModels/View Models/MediaPreferencesViewModel.swift deleted file mode 100644 index dce9df7..0000000 --- a/ViewModels/Sources/ViewModels/View Models/MediaPreferencesViewModel.swift +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright © 2020 Metabolist. All rights reserved. - -import Combine -import Foundation -import ServiceLayer - -public final class MediaPreferencesViewModel: ObservableObject { - public let identityContext: IdentityContext - - public init(identityContext: IdentityContext) { - self.identityContext = identityContext - } -} diff --git a/ViewModels/Sources/ViewModels/View Models/PostingReadingPreferencesViewModel.swift b/ViewModels/Sources/ViewModels/View Models/PostingReadingPreferencesViewModel.swift deleted file mode 100644 index cbc37bb..0000000 --- a/ViewModels/Sources/ViewModels/View Models/PostingReadingPreferencesViewModel.swift +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright © 2020 Metabolist. All rights reserved. - -import Combine -import Foundation -import ServiceLayer - -public final class PostingReadingPreferencesViewModel: ObservableObject { - @Published public var preferences: Identity.Preferences - @Published public var alertItem: AlertItem? - public let identityContext: IdentityContext - - private var cancellables = Set() - - public init(identityContext: IdentityContext) { - self.identityContext = identityContext - preferences = identityContext.identity.preferences - - identityContext.$identity - .map(\.preferences) - .dropFirst() - .removeDuplicates() - .assign(to: &$preferences) - - $preferences - .dropFirst() - .flatMap(identityContext.service.updatePreferences) - .assignErrorsToAlertItem(to: \.alertItem, on: self) - .sink { _ in } - .store(in: &cancellables) - } -} diff --git a/ViewModels/Sources/ViewModels/View Models/PreferencesViewModel.swift b/ViewModels/Sources/ViewModels/View Models/PreferencesViewModel.swift index 73bcc53..d9c1230 100644 --- a/ViewModels/Sources/ViewModels/View Models/PreferencesViewModel.swift +++ b/ViewModels/Sources/ViewModels/View Models/PreferencesViewModel.swift @@ -1,18 +1,35 @@ // Copyright © 2020 Metabolist. All rights reserved. +import Combine import Foundation import ServiceLayer public final class PreferencesViewModel: ObservableObject { - public let handle: String + @Published public var preferences: Identity.Preferences + @Published public var alertItem: AlertItem? public let shouldShowNotificationTypePreferences: Bool public let identityContext: IdentityContext + private var cancellables = Set() + public init(identityContext: IdentityContext) { self.identityContext = identityContext - handle = identityContext.identity.handle shouldShowNotificationTypePreferences = identityContext.identity.lastRegisteredDeviceToken != nil + preferences = identityContext.identity.preferences + + identityContext.$identity + .map(\.preferences) + .dropFirst() + .removeDuplicates() + .assign(to: &$preferences) + + $preferences + .dropFirst() + .flatMap(identityContext.service.updatePreferences) + .assignErrorsToAlertItem(to: \.alertItem, on: self) + .sink { _ in } + .store(in: &cancellables) } } diff --git a/Views/MediaPreferencesView.swift b/Views/MediaPreferencesView.swift deleted file mode 100644 index 2b28488..0000000 --- a/Views/MediaPreferencesView.swift +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright © 2020 Metabolist. All rights reserved. - -import SwiftUI -import ViewModels - -struct MediaPreferencesView: View { - @StateObject var viewModel: MediaPreferencesViewModel - @StateObject var identityContext: IdentityContext - @Environment(\.accessibilityReduceMotion) var accessibilityReduceMotion - - init(viewModel: MediaPreferencesViewModel) { - _viewModel = StateObject(wrappedValue: viewModel) - _identityContext = StateObject(wrappedValue: viewModel.identityContext) - } - - var body: some View { - Form { - if accessibilityReduceMotion { - Section { - Toggle("preferences.media.use-system-reduce-motion", - isOn: $identityContext.appPreferences.useSystemReduceMotionForMedia) - } - } - Section(header: Text("preferences.media.autoplay")) { - Picker("preferences.media.autoplay.gifs", - selection: reduceMotion ? .constant(.never) : $identityContext.appPreferences.autoplayGIFs) { - ForEach(AppPreferences.Autoplay.allCases) { option in - Text(option.localizedStringKey).tag(option) - } - } - Picker("preferences.media.autoplay.videos", - selection: reduceMotion ? .constant(.never) : $identityContext.appPreferences.autoplayVideos) { - ForEach(AppPreferences.Autoplay.allCases) { option in - Text(option.localizedStringKey).tag(option) - } - } - } - .disabled(reduceMotion) - Section(header: Text("preferences.media.avatars")) { - Picker("preferences.media.avatars.animate", - selection: reduceMotion ? .constant(.never) : $identityContext.appPreferences.animateAvatars) { - ForEach(AppPreferences.AnimateAvatars.allCases) { option in - Text(option.localizedStringKey).tag(option) - } - } - .disabled(reduceMotion) - } - Section(header: Text("preferences.media.headers")) { - Toggle("preferences.media.headers.animate", - isOn: reduceMotion ? .constant(false) : $identityContext.appPreferences.animateHeaders) - .disabled(reduceMotion) - } - } - .navigationTitle("preferences.media") - } -} - -private extension MediaPreferencesView { - var reduceMotion: Bool { - identityContext.appPreferences.shouldReduceMotion - } -} - -extension AppPreferences.AnimateAvatars { - var localizedStringKey: LocalizedStringKey { - switch self { - case .everywhere: - return "preferences.media.avatars.animate.everywhere" - case .profiles: - return "preferences.media.avatars.animate.profiles" - case .never: - return "preferences.media.avatars.animate.never" - } - } -} - -extension AppPreferences.Autoplay { - var localizedStringKey: LocalizedStringKey { - switch self { - case .always: - return "preferences.media.autoplay.always" - case .wifi: - return "preferences.media.autoplay.wifi" - case .never: - return "preferences.media.autoplay.never" - } - } -} - -#if DEBUG -struct MediaPreferencesView_Previews: PreviewProvider { - static var previews: some View { - MediaPreferencesView(viewModel: .init(identityContext: .preview)) - } -} -#endif diff --git a/Views/PostingReadingPreferencesView.swift b/Views/PostingReadingPreferencesView.swift deleted file mode 100644 index c35e70d..0000000 --- a/Views/PostingReadingPreferencesView.swift +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright © 2020 Metabolist. All rights reserved. - -import Mastodon -import SwiftUI -import ViewModels - -struct PostingReadingPreferencesView: View { - @StateObject var viewModel: PostingReadingPreferencesViewModel - - var body: some View { - Form { - Section { - Toggle("preferences.use-preferences-from-server", - isOn: $viewModel.preferences.useServerPostingReadingPreferences) - } - Section(header: Text("preferences.posting")) { - VStack(alignment: .leading) { - Text("preferences.posting-default-visiblility") - Picker("", selection: $viewModel.preferences.postingDefaultVisibility, - content: { - Text("status.visibility.public").tag(Status.Visibility.public) - Text("status.visibility.unlisted").tag(Status.Visibility.unlisted) - Text("status.visibility.private").tag(Status.Visibility.private) - }) - .pickerStyle(SegmentedPickerStyle()) - } - Toggle("preferences.posting-default-sensitive", - isOn: $viewModel.preferences.postingDefaultSensitive) - } - .disabled(viewModel.preferences.useServerPostingReadingPreferences) - Section(header: Text("preferences.reading")) { - VStack(alignment: .leading) { - Text("preferences.reading-expand-media") - Picker("", selection: $viewModel.preferences.readingExpandMedia, - content: { - Text("preferences.expand-media.default").tag(Preferences.ExpandMedia.default) - Text("preferences.expand-media.show-all").tag(Preferences.ExpandMedia.showAll) - Text("preferences.expand-media.hide-all").tag(Preferences.ExpandMedia.hideAll) - }) - .pickerStyle(SegmentedPickerStyle()) - } - Toggle("preferences.reading-expand-spoilers", - isOn: $viewModel.preferences.readingExpandSpoilers) - } - .disabled(viewModel.preferences.useServerPostingReadingPreferences) - } - .navigationTitle("preferences.posting-reading") - .alertItem($viewModel.alertItem) - } -} - -#if DEBUG -import PreviewViewModels - -struct PostingReadingPreferencesViewView_Previews: PreviewProvider { - static var previews: some View { - PostingReadingPreferencesView(viewModel: .init(identityContext: .preview)) - } -} -#endif diff --git a/Views/PreferencesView.swift b/Views/PreferencesView.swift index 960e7e9..ebc9c36 100644 --- a/Views/PreferencesView.swift +++ b/Views/PreferencesView.swift @@ -1,44 +1,158 @@ // Copyright © 2020 Metabolist. All rights reserved. +import Mastodon import SwiftUI import ViewModels struct PreferencesView: View { @StateObject var viewModel: PreferencesViewModel + @StateObject var identityContext: IdentityContext + @Environment(\.accessibilityReduceMotion) var accessibilityReduceMotion + + init(viewModel: PreferencesViewModel) { + _viewModel = StateObject(wrappedValue: viewModel) + _identityContext = StateObject(wrappedValue: viewModel.identityContext) + } var body: some View { Form { - Section(header: Text(viewModel.handle)) { - NavigationLink("preferences.posting-reading", - destination: PostingReadingPreferencesView( - viewModel: .init(identityContext: viewModel.identityContext))) - NavigationLink("preferences.filters", - destination: FiltersView( - viewModel: .init(identityContext: viewModel.identityContext))) - if viewModel.shouldShowNotificationTypePreferences { - NavigationLink("preferences.notification-types", - destination: NotificationTypesPreferencesView( + Section(header: Text(viewModel.identityContext.identity.handle)) { + if viewModel.identityContext.identity.authenticated + && !viewModel.identityContext.identity.pending { + NavigationLink("preferences.filters", + destination: FiltersView( viewModel: .init(identityContext: viewModel.identityContext))) + if viewModel.shouldShowNotificationTypePreferences { + NavigationLink("preferences.notification-types", + destination: NotificationTypesPreferencesView( + viewModel: .init(identityContext: viewModel.identityContext))) + } + NavigationLink("preferences.muted-users", + destination: TableView(viewModelClosure: viewModel.mutedUsersViewModel) + .navigationTitle(Text("preferences.muted-users"))) + NavigationLink("preferences.blocked-users", + destination: TableView(viewModelClosure: viewModel.blockedUsersViewModel) + .navigationTitle(Text("preferences.blocked-users"))) + NavigationLink("preferences.blocked-domains", + destination: DomainBlocksView(viewModel: viewModel.domainBlocksViewModel())) + Toggle("preferences.use-preferences-from-server", + isOn: $viewModel.preferences.useServerPostingReadingPreferences) + Group { + Picker("preferences.posting-default-visiblility", + selection: $viewModel.preferences.postingDefaultVisibility) { + Text("status.visibility.public").tag(Status.Visibility.public) + Text("status.visibility.unlisted").tag(Status.Visibility.unlisted) + Text("status.visibility.private").tag(Status.Visibility.private) + } + Toggle("preferences.posting-default-sensitive", + isOn: $viewModel.preferences.postingDefaultSensitive) + } + .disabled(viewModel.preferences.useServerPostingReadingPreferences) } - NavigationLink("preferences.muted-users", - destination: TableView(viewModelClosure: viewModel.mutedUsersViewModel) - .navigationTitle(Text("preferences.muted-users"))) - NavigationLink("preferences.blocked-users", - destination: TableView(viewModelClosure: viewModel.blockedUsersViewModel) - .navigationTitle(Text("preferences.blocked-users"))) - NavigationLink("preferences.blocked-domains", - destination: DomainBlocksView(viewModel: viewModel.domainBlocksViewModel())) + Group { + Picker("preferences.reading-expand-media", + selection: $viewModel.preferences.readingExpandMedia) { + Text("preferences.expand-media.default").tag(Preferences.ExpandMedia.default) + Text("preferences.expand-media.show-all").tag(Preferences.ExpandMedia.showAll) + Text("preferences.expand-media.hide-all").tag(Preferences.ExpandMedia.hideAll) + } + Toggle("preferences.reading-expand-spoilers", + isOn: $viewModel.preferences.readingExpandSpoilers) + } + .disabled(viewModel.preferences.useServerPostingReadingPreferences) } Section(header: Text("preferences.app")) { - NavigationLink("preferences.media", - destination: MediaPreferencesView( - viewModel: .init(identityContext: viewModel.identityContext))) - NavigationLink("preferences.startup-and-syncing", - destination: StartupAndSyncingPreferencesView( - identityContext: viewModel.identityContext)) + if accessibilityReduceMotion { + Toggle("preferences.media.use-system-reduce-motion", + isOn: $identityContext.appPreferences.useSystemReduceMotionForMedia) + } + Group { + Picker("preferences.media.autoplay.gifs", + selection: reduceMotion ? .constant(.never) : $identityContext.appPreferences.autoplayGIFs) { + ForEach(AppPreferences.Autoplay.allCases) { option in + Text(option.localizedStringKey).tag(option) + } + } + Picker("preferences.media.autoplay.videos", + selection: reduceMotion + ? .constant(.never) : $identityContext.appPreferences.autoplayVideos) { + ForEach(AppPreferences.Autoplay.allCases) { option in + Text(option.localizedStringKey).tag(option) + } + } + Picker("preferences.media.avatars.animate", + selection: reduceMotion + ? .constant(.never) : $identityContext.appPreferences.animateAvatars) { + ForEach(AppPreferences.AnimateAvatars.allCases) { option in + Text(option.localizedStringKey).tag(option) + } + } + Toggle("preferences.media.headers.animate", + isOn: reduceMotion ? .constant(false) : $identityContext.appPreferences.animateHeaders) + .disabled(reduceMotion) + } + .disabled(reduceMotion) + Picker("preferences.home-timeline-position-on-startup", + selection: $identityContext.appPreferences.homeTimelineBehavior) { + ForEach(AppPreferences.PositionBehavior.allCases) { option in + Text(option.localizedStringKey).tag(option) + } + } + Picker("preferences.notifications-position-on-startup", + selection: $identityContext.appPreferences.notificationsTabBehavior) { + ForEach(AppPreferences.PositionBehavior.allCases) { option in + Text(option.localizedStringKey).tag(option) + } + } } } .navigationTitle("preferences") + .alertItem($viewModel.alertItem) + } +} + +private extension PreferencesView { + var reduceMotion: Bool { + identityContext.appPreferences.shouldReduceMotion + } +} + +extension AppPreferences.AnimateAvatars { + var localizedStringKey: LocalizedStringKey { + switch self { + case .everywhere: + return "preferences.media.avatars.animate.everywhere" + case .profiles: + return "preferences.media.avatars.animate.profiles" + case .never: + return "preferences.media.avatars.animate.never" + } + } +} + +extension AppPreferences.Autoplay { + var localizedStringKey: LocalizedStringKey { + switch self { + case .always: + return "preferences.media.autoplay.always" + case .wifi: + return "preferences.media.autoplay.wifi" + case .never: + return "preferences.media.autoplay.never" + } + } +} + +extension AppPreferences.PositionBehavior { + var localizedStringKey: LocalizedStringKey { + switch self { + case .rememberPosition: + return "preferences.position.remember-position" + case .syncPosition: + return "preferences.position.sync-position" + case .newest: + return "preferences.position.newest" + } } } diff --git a/Views/StartupAndSyncingPreferencesView.swift b/Views/StartupAndSyncingPreferencesView.swift deleted file mode 100644 index dad7c82..0000000 --- a/Views/StartupAndSyncingPreferencesView.swift +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 Metabolist. All rights reserved. - -import SwiftUI -import ViewModels - -struct StartupAndSyncingPreferencesView: View { - @StateObject var identityContext: IdentityContext - - var body: some View { - Form { - Section(header: Text("preferences.startup-and-syncing.home-timeline")) { - Picker("preferences.startup-and-syncing.position-on-startup", - selection: $identityContext.appPreferences.homeTimelineBehavior) { - ForEach(AppPreferences.PositionBehavior.allCases) { option in - Text(option.localizedStringKey).tag(option) - } - } - } - Section(header: Text("preferences.startup-and-syncing.notifications-tab")) { - Picker("preferences.startup-and-syncing.position-on-startup", - selection: $identityContext.appPreferences.notificationsTabBehavior) { - ForEach(AppPreferences.PositionBehavior.allCases) { option in - Text(option.localizedStringKey).tag(option) - } - } - } - } - } -} - -extension AppPreferences.PositionBehavior { - var localizedStringKey: LocalizedStringKey { - switch self { - case .rememberPosition: - return "preferences.startup-and-syncing.remember-position" - case .syncPosition: - return "preferences.startup-and-syncing.sync-position" - case .newest: - return "preferences.startup-and-syncing.newest" - } - } -} - -#if DEBUG -import PreviewViewModels - -struct StartupAndSyncingPreferencesView_Previews: PreviewProvider { - static var previews: some View { - StartupAndSyncingPreferencesView(identityContext: .preview) - } -} -#endif