Add color scheme / appearance switcher

This commit is contained in:
vollkorntomate 2022-11-11 15:04:52 +01:00
parent 436cf0a045
commit 77a1c799f5
No known key found for this signature in database
GPG key ID: 87384A836B85D103
12 changed files with 121 additions and 15 deletions

View file

@ -201,6 +201,10 @@
"preferences" = "Einstellungen";
"preferences.app" = "App Einstellungen";
"preferences.app-icon" = "App Icon";
"preferences.app.color-scheme" = "Erscheinungsbild";
"preferences.app.color-scheme.dark" = "Dunkel";
"preferences.app.color-scheme.light" = "Hell";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "Gesperrte Domains";
"preferences.blocked-users" = "Gesperrte Nutzer";
"preferences.media" = "Medien";

View file

@ -201,6 +201,10 @@
"preferences" = "Preferences";
"preferences.app" = "App Preferences";
"preferences.app-icon" = "App Icon";
"preferences.app.color-scheme" = "Appearance";
"preferences.app.color-scheme.dark" = "Dark";
"preferences.app.color-scheme.light" = "Light";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "Blocked Domains";
"preferences.blocked-users" = "Blocked Users";
"preferences.media" = "Media";
@ -344,6 +348,7 @@
"status.visibility.unlisted.description" = "Visible for all, but not in public timelines";
"status.visibility.private.description" = "Visible for followers only";
"status.visibility.direct.description" = "Visible for mentioned users only";
"system" = "System";
"tag.accessibility-recent-uses-%ld" = "%ld recent uses";
"tag.accessibility-hint.post" = "View posts associated with trend";
"tag.accessibility-hint.toot" = "View toots associated with trend";

View file

@ -201,6 +201,10 @@
"preferences" = "Ajustes";
"preferences.app" = "Ajustes de la App";
"preferences.app-icon" = "Icono de la App";
"preferences.app.color-scheme" = "Appearance";
"preferences.app.color-scheme.dark" = "Dark";
"preferences.app.color-scheme.light" = "Light";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "Dominios bloqueados";
"preferences.blocked-users" = "Usuarios bloqueados";
"preferences.media" = "Multimedia";

View file

@ -201,6 +201,10 @@
"preferences" = "環境設定";
"preferences.app" = "アプリ環境設定";
"preferences.app-icon" = "アプリアイコン";
"preferences.app.color-scheme" = "Appearance";
"preferences.app.color-scheme.dark" = "Dark";
"preferences.app.color-scheme.light" = "Light";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "ブロックしたドメイン";
"preferences.blocked-users" = "ブロックしたユーザー";
"preferences.media" = "メディア";

View file

@ -201,6 +201,10 @@
"preferences" = "설정";
"preferences.app" = "앱 설정";
"preferences.app-icon" = "앱 아이콘";
"preferences.app.color-scheme" = "Appearance";
"preferences.app.color-scheme.dark" = "Dark";
"preferences.app.color-scheme.light" = "Light";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "차단된 도메인";
"preferences.blocked-users" = "차단된 사용자";
"preferences.media" = "미디어";

View file

@ -201,6 +201,10 @@
"preferences" = "Właściwości";
"preferences.app" = "Ustawienia aplikacji";
"preferences.app-icon" = "Ikona aplikacji";
"preferences.app.color-scheme" = "Appearance";
"preferences.app.color-scheme.dark" = "Dark";
"preferences.app.color-scheme.light" = "Light";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "Zablokowane domeny";
"preferences.blocked-users" = "Zablokowane profile";
"preferences.media" = "Media";

View file

@ -201,6 +201,10 @@
"preferences" = "Настройки";
"preferences.app" = "Настройки приложения";
"preferences.app-icon" = "Значок приложения";
"preferences.app.color-scheme" = "Appearance";
"preferences.app.color-scheme.dark" = "Dark";
"preferences.app.color-scheme.light" = "Light";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "Заблокированные домены";
"preferences.blocked-users" = "Заблокированные пользователи";
"preferences.media" = "Медиафайлы";

View file

@ -201,6 +201,10 @@
"preferences" = "偏好设置";
"preferences.app" = "应用偏好设置";
"preferences.app-icon" = "应用图标";
"preferences.app.color-scheme" = "Appearance";
"preferences.app.color-scheme.dark" = "Dark";
"preferences.app.color-scheme.light" = "Light";
"preferences.app.color-scheme.system" = "System";
"preferences.blocked-domains" = "已屏蔽的域名";
"preferences.blocked-users" = "已屏蔽的用户";
"preferences.media" = "媒体";

View file

@ -17,6 +17,14 @@ public struct AppPreferences {
}
public extension AppPreferences {
enum ColorScheme: String, CaseIterable, Identifiable {
case system
case light
case dark
public var id: String { rawValue }
}
enum StatusWord: String, CaseIterable, Identifiable {
case toot
case post
@ -47,6 +55,18 @@ public extension AppPreferences {
public var id: String { rawValue }
}
var colorScheme: ColorScheme {
get {
if let rawValue = self[.colorScheme] as String?,
let value = ColorScheme(rawValue: rawValue) {
return value
}
return .system
}
set { self[.colorScheme] = newValue.rawValue }
}
var statusWord: StatusWord {
get {
if let rawValue = self[.statusWord] as String?,
@ -185,6 +205,7 @@ public extension AppPreferences {
private extension AppPreferences {
enum Item: String {
case colorScheme
case statusWord
case requireDoubleTapToReblog
case requireDoubleTapToFavorite

View file

@ -6,7 +6,7 @@ import Mastodon
import ServiceLayer
public final class NavigationViewModel: ObservableObject {
public let identityContext: IdentityContext
@Published public private(set) var identityContext: IdentityContext
public let navigations: AnyPublisher<Navigation, Never>
@Published public private(set) var recentIdentities = [Identity]()

View file

@ -88,6 +88,11 @@ struct PreferencesView: View {
}
}
}
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",
@ -153,6 +158,19 @@ struct PreferencesView: View {
}
}
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 {

View file

@ -1,29 +1,63 @@
// Copyright © 2020 Metabolist. All rights reserved.
import SwiftUI
import UIKit
import ViewModels
struct RootView: View {
@StateObject var viewModel: RootViewModel
@State private var previousColorScheme: AppPreferences.ColorScheme = .system
var appPreferencesPublisher: AnyPublisher<AppPreferences, Never> {
viewModel.navigationViewModel?.identityContext.$appPreferences.eraseToAnyPublisher()
?? Empty<AppPreferences, Never>().eraseToAnyPublisher()
}
var body: some View {
if let navigationViewModel = viewModel.navigationViewModel {
MainNavigationView { navigationViewModel }
.id(navigationViewModel.identityContext.identity.id)
.environmentObject(viewModel)
.transition(.opacity)
.edgesIgnoringSafeArea(.all)
} else {
NavigationView {
AddIdentityView(
viewModelClosure: { viewModel.addIdentityViewModel() },
displayWelcome: true)
Group {
if let navigationViewModel = viewModel.navigationViewModel {
MainNavigationView { navigationViewModel }
.id(navigationViewModel.identityContext.identity.id)
.environmentObject(viewModel)
.transition(.opacity)
.edgesIgnoringSafeArea(.all)
} else {
NavigationView {
AddIdentityView(
viewModelClosure: { viewModel.addIdentityViewModel() },
displayWelcome: true)
.navigationBarTitleDisplayMode(.inline)
.navigationBarHidden(true)
}
.environmentObject(viewModel)
.navigationViewStyle(StackNavigationViewStyle())
.transition(.opacity)
}
.environmentObject(viewModel)
.navigationViewStyle(StackNavigationViewStyle())
.transition(.opacity)
}
.onReceive(appPreferencesPublisher) { preferences in
if preferences.colorScheme != previousColorScheme {
self.previousColorScheme = preferences.colorScheme
setColorScheme(preferences.colorScheme)
}
}
}
private func setColorScheme(_ colorScheme: AppPreferences.ColorScheme) {
let scenes = UIApplication.shared.connectedScenes
let windowScenes = scenes.first as? UIWindowScene
let window = windowScenes?.windows.first
window?.overrideUserInterfaceStyle = colorScheme.uiKit
}
}
extension AppPreferences.ColorScheme {
var uiKit: UIUserInterfaceStyle {
switch self {
case .system:
return .unspecified
case .light:
return .light
case .dark:
return .dark
}
}
}