// Copyright © 2020 Metabolist. All rights reserved. import Combine import Mastodon import SwiftUI import ViewModels struct PreferencesView: View { @StateObject var viewModel: PreferencesViewModel @StateObject var identityContext: IdentityContext @EnvironmentObject var rootViewModel: RootViewModel @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.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))) } Button("preferences.muted-users") { rootViewModel.navigationViewModel?.navigateToMutedUsers() } .foregroundColor(.primary) Button("preferences.blocked-users") { rootViewModel.navigationViewModel?.navigateToBlockedUsers() } .foregroundColor(.primary) 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) } 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 && viewModel.identityContext.identity.authenticated) } Section(header: Text("preferences.app")) { Group { if UIApplication.shared.supportsAlternateIcons { NavigationLink(destination: AppIconPreferencesView(viewModel: viewModel)) { HStack { Text("preferences.app-icon") Spacer() if let appIcon = AppIcon.current { if let image = appIcon.image { image .resizable() .frame( width: UIFont.preferredFont(forTextStyle: .body).lineHeight, height: UIFont.preferredFont(forTextStyle: .body).lineHeight) .cornerRadius(.defaultCornerRadius / 2) } Text(appIcon.nameLocalizedStringKey) .foregroundColor(.secondary) } } } } Picker("preferences.app.color-scheme", selection: $identityContext.appPreferences.colorScheme) { ForEach(AppPreferences.ColorScheme.allCases) { option in Text(option.localizedStringKey).tag(option) } } NavigationLink("preferences.notifications", destination: NotificationPreferencesView(viewModel: viewModel)) Picker("preferences.status-word", selection: $identityContext.appPreferences.statusWord) { ForEach(AppPreferences.StatusWord.allCases) { option in Text(option.localizedStringKey).tag(option) } } Toggle("preferences.show-reblog-and-favorite-counts", isOn: $identityContext.appPreferences.showReblogAndFavoriteCounts) Toggle("preferences.require-double-tap-to-reblog", isOn: $identityContext.appPreferences.requireDoubleTapToReblog) Toggle("preferences.require-double-tap-to-favorite", isOn: $identityContext.appPreferences.requireDoubleTapToFavorite) Toggle("preferences.links.open-in-default-browser", isOn: $identityContext.appPreferences.openLinksInDefaultBrowser) if !identityContext.appPreferences.openLinksInDefaultBrowser { Toggle("preferences.links.use-universal-links", isOn: $identityContext.appPreferences.useUniversalLinks) } } Group { Picker("preferences.media.autoplay.gifs", selection: $identityContext.appPreferences.autoplayGIFs) { ForEach(AppPreferences.Autoplay.allCases) { option in Text(option.localizedStringKey).tag(option) } } Picker("preferences.media.autoplay.videos", selection: $identityContext.appPreferences.autoplayVideos) { ForEach(AppPreferences.Autoplay.allCases) { option in Text(option.localizedStringKey).tag(option) } } Picker("preferences.media.avatars.animate", selection: $identityContext.appPreferences.animateAvatars) { ForEach(AppPreferences.AnimateAvatars.allCases) { option in Text(option.localizedStringKey).tag(option) } } Toggle("preferences.media.custom-emojis.animate", isOn: $identityContext.appPreferences.animateCustomEmojis) Toggle("preferences.media.headers.animate", isOn: $identityContext.appPreferences.animateHeaders) } if viewModel.identityContext.identity.authenticated && !viewModel.identityContext.identity.pending { Picker("preferences.home-timeline-position-on-startup", selection: $identityContext.appPreferences.homeTimelineBehavior) { ForEach(AppPreferences.PositionBehavior.allCases) { option in Text(option.localizedStringKey).tag(option) } } } } } .navigationTitle("preferences") .alertItem($viewModel.alertItem) .onReceive(NotificationCenter.default.publisher( for: UIAccessibility.videoAutoplayStatusDidChangeNotification)) { _ in viewModel.objectWillChange.send() } } } extension AppPreferences.ColorScheme { var localizedStringKey: LocalizedStringKey { switch self { case .system: return "preferences.app.color-scheme.system" case .light: return "preferences.app.color-scheme.light" case .dark: return "preferences.app.color-scheme.dark" } } } extension AppPreferences.StatusWord { var localizedStringKey: LocalizedStringKey { switch self { case .toot: return "toot" case .post: return "post" } } } 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 .localRememberPosition: return "preferences.position.remember-position" case .newest: return "preferences.position.newest" } } } #if DEBUG import PreviewViewModels struct PreferencesView_Previews: PreviewProvider { static var previews: some View { PreferencesView(viewModel: .init(identityContext: .preview)) } } #endif