Add a follow system colors option close #128

This commit is contained in:
Thomas Ricouard 2023-01-20 21:58:57 +01:00
parent cd05a75ab9
commit 5321b2b8d8
12 changed files with 82 additions and 47 deletions

View file

@ -622,7 +622,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.3;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.thomasricouard.IceCubesApp.IceCubesNotifications;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@ -652,7 +652,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.3;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.thomasricouard.IceCubesApp.IceCubesNotifications;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@ -683,7 +683,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.3;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.thomasricouard.IceCubesApp.IceCubesShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@ -713,7 +713,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.3;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.thomasricouard.IceCubesApp.IceCubesShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
@ -877,7 +877,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0.3;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.thomasricouard.IceCubesApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
@ -929,7 +929,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0.3;
MARKETING_VERSION = 1.0.4;
PRODUCT_BUNDLE_IDENTIFIER = com.thomasricouard.IceCubesApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;

View file

@ -14,6 +14,7 @@ struct IceCubesApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
@Environment(\.scenePhase) private var scenePhase
@StateObject private var appAccountsManager = AppAccountsManager.shared
@StateObject private var currentInstance = CurrentInstance.shared
@StateObject private var currentAccount = CurrentAccount.shared
@ -197,6 +198,8 @@ struct IceCubesApp: App {
}
class AppDelegate: NSObject, UIApplicationDelegate {
let themeObserver = ThemeObserverViewController(nibName: nil, bundle: nil)
func application(_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool
{
@ -219,3 +222,11 @@ class AppDelegate: NSObject, UIApplicationDelegate {
func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError _: Error) {}
}
class ThemeObserverViewController: UIViewController {
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
print(traitCollection.userInterfaceStyle.rawValue)
}
}

View file

@ -13,10 +13,20 @@ struct DisplaySettingsView: View {
var body: some View {
Form {
Section("settings.display.section.theme") {
Toggle("settings.display.theme.systemColor", isOn: $theme.followSystemColorScheme)
themeSelectorButton
ColorPicker("settings.display.theme.tint", selection: $theme.tintColor)
.onChange(of: theme.tintColor) { newValue in
theme.followSystemColorScheme = false
}
ColorPicker("settings.display.theme.background", selection: $theme.primaryBackgroundColor)
.onChange(of: theme.primaryBackgroundColor) { newValue in
theme.followSystemColorScheme = false
}
ColorPicker("settings.display.theme.secondary-background", selection: $theme.secondaryBackgroundColor)
.onChange(of: theme.primaryBackgroundColor) { newValue in
theme.followSystemColorScheme = false
}
}
.listRowBackground(theme.primaryBackgroundColor)

View file

@ -7,7 +7,7 @@ import Network
import SwiftUI
import Timeline
struct TimelineTab: View {
struct TimelineTab: View {
@EnvironmentObject private var theme: Theme
@EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var preferences: UserPreferences

View file

@ -61,6 +61,7 @@
"settings.display.theme.background" = "Hintergrundfarbe";
"settings.display.theme.secondary-background" = "Sekundäre Hintergrundfarbe";
"settings.display.theme.tint" = "Akzentfarbe";
"settings.display.theme.systemColor" = "Match-System";
"settings.general.browser" = "Browser";
"settings.general.browser.in-app" = "In-App Browser";
"settings.general.browser.system" = "System Browser";

View file

@ -61,6 +61,7 @@
"settings.display.theme.background" = "Background color";
"settings.display.theme.secondary-background" = "Secondary Background color";
"settings.display.theme.tint" = "Tint color";
"settings.display.theme.systemColor" = "Match System";
"settings.general.browser" = "Browser";
"settings.general.browser.in-app" = "In-App Browser";
"settings.general.browser.system" = "System Browser";

View file

@ -61,6 +61,7 @@
"settings.display.theme.background" = "Color de fondo";
"settings.display.theme.secondary-background" = "Color de fondo secundario";
"settings.display.theme.tint" = "Color";
"settings.display.theme.systemColor" = "Sistema de coincidencia";
"settings.general.browser" = "Navegador";
"settings.general.browser.in-app" = "Interno";
"settings.general.browser.system" = "Sistema";

View file

@ -61,6 +61,7 @@
"settings.display.theme.background" = "Achtergrondkleur";
"settings.display.theme.secondary-background" = "Secundaire Achtergrondkleur";
"settings.display.theme.tint" = "Kleurtint";
"settings.display.theme.systemColor" = "Match systeem";
"settings.general.browser" = "Browser";
"settings.general.browser.in-app" = "In-App Browser";
"settings.general.browser.system" = "Systeem Browser";

View file

@ -1,4 +1,11 @@
import SwiftUI
public let availableColorsSets: [ColorSetCouple] =
[.init(light: IceCubeLight(), dark: IceCubeDark()),
.init(light: DesertLight(), dark: DesertDark()),
.init(light: NemesisLight(), dark: NemesisDark()),
.init(light: MediumLight(), dark: MediumDark())]
public protocol ColorSet {
var name: ColorSetName { get }
var scheme: ColorScheme { get }
@ -23,6 +30,15 @@ public enum ColorSetName: String {
case mediumDark = "Medium - Dark"
}
public struct ColorSetCouple: Identifiable {
public var id: String {
dark.name.rawValue + light.name.rawValue
}
public let light: ColorSet
public let dark: ColorSet
}
public struct IceCubeDark: ColorSet {
public var name: ColorSetName = .iceCubeDark
public var scheme: ColorScheme = .dark

View file

@ -6,6 +6,7 @@ public class Theme: ObservableObject {
case colorScheme, tint, label, primaryBackground, secondaryBackground
case avatarPosition, avatarShape, statusActionsDisplay, statusDisplayStyle
case selectedSet, selectedScheme
case followSystemColorSchme
}
public enum AvatarPosition: String, CaseIterable {
@ -62,7 +63,7 @@ public class Theme: ObservableObject {
}
}
@AppStorage("is_previously_set") private var isSet: Bool = false
@AppStorage("is_previously_set") public var isThemePreviouslySet: Bool = false
@AppStorage(ThemeKey.selectedScheme.rawValue) public var selectedScheme: ColorScheme = .dark
@AppStorage(ThemeKey.tint.rawValue) public var tintColor: Color = .black
@AppStorage(ThemeKey.primaryBackground.rawValue) public var primaryBackgroundColor: Color = .white
@ -73,6 +74,7 @@ public class Theme: ObservableObject {
@AppStorage(ThemeKey.selectedSet.rawValue) var storedSet: ColorSetName = .iceCubeDark
@AppStorage(ThemeKey.statusActionsDisplay.rawValue) public var statusActionsDisplay: StatusActionsDisplay = .full
@AppStorage(ThemeKey.statusDisplayStyle.rawValue) public var statusDisplayStyle: StatusDisplayStyle = .large
@AppStorage(ThemeKey.followSystemColorSchme.rawValue) public var followSystemColorScheme: Bool = true
@Published public var avatarPosition: AvatarPosition = .top
@Published public var avatarShape: AvatarShape = .rounded
@ -85,13 +87,6 @@ public class Theme: ObservableObject {
private init() {
selectedSet = storedSet
// If theme is never set before set the default store. This should only execute once after install.
if !isSet {
setColor(withName: .iceCubeDark)
isSet = true
}
avatarPosition = AvatarPosition(rawValue: rawAvatarPosition) ?? .top
avatarShape = AvatarShape(rawValue: rawAvatarShape) ?? .rounded

View file

@ -10,43 +10,48 @@ public extension View {
}
struct ThemeApplier: ViewModifier {
@Environment(\EnvironmentValues.colorScheme) var colorScheme
@ObservedObject var theme: Theme
var actualColorScheme: SwiftUI.ColorScheme? {
if theme.followSystemColorScheme {
return nil
}
return theme.selectedScheme == ColorScheme.dark ? .dark : .light
}
func body(content: Content) -> some View {
content
.tint(theme.tintColor)
.preferredColorScheme(theme.selectedScheme == ColorScheme.dark ? .dark : .light)
.preferredColorScheme(actualColorScheme)
#if canImport(UIKit)
.onAppear {
// If theme is never set before set the default store. This should only execute once after install.
if !theme.isThemePreviouslySet {
theme.selectedSet = colorScheme == .dark ? .iceCubeDark : .iceCubeLight
theme.isThemePreviouslySet = true
}
setWindowTint(theme.tintColor)
setWindowUserInterfaceStyle(theme.selectedScheme)
setBarsColor(theme.primaryBackgroundColor)
}
.onChange(of: theme.tintColor) { newValue in
setWindowTint(newValue)
}
.onChange(of: theme.selectedScheme) { newValue in
setWindowUserInterfaceStyle(newValue)
}
.onChange(of: theme.primaryBackgroundColor) { newValue in
setBarsColor(newValue)
}
.onChange(of: colorScheme) { newColorScheme in
if theme.followSystemColorScheme,
let sets = availableColorsSets
.first(where: { $0.light.name == theme.selectedSet || $0.dark.name == theme.selectedSet }) {
theme.selectedSet = newColorScheme == .dark ? sets.dark.name : sets.light.name
}
}
#endif
}
#if canImport(UIKit)
private func setWindowUserInterfaceStyle(_ colorScheme: ColorScheme) {
allWindows()
.forEach {
switch colorScheme {
case .dark:
$0.overrideUserInterfaceStyle = .dark
case .light:
$0.overrideUserInterfaceStyle = .light
}
}
}
private func setWindowTint(_ color: Color) {
allWindows()
.forEach {

View file

@ -10,21 +10,11 @@ public struct ThemePreviewView: View {
public var body: some View {
ScrollView {
HStack(spacing: gutterSpace) {
ThemeBoxView(color: IceCubeDark())
ThemeBoxView(color: IceCubeLight())
}
HStack(spacing: gutterSpace) {
ThemeBoxView(color: DesertDark())
ThemeBoxView(color: DesertLight())
}
HStack(spacing: gutterSpace) {
ThemeBoxView(color: NemesisDark())
ThemeBoxView(color: NemesisLight())
}
HStack(spacing: gutterSpace) {
ThemeBoxView(color: MediumDark())
ThemeBoxView(color: MediumLight())
ForEach(availableColorsSets) { couple in
HStack(spacing: gutterSpace) {
ThemeBoxView(color: couple.light)
ThemeBoxView(color: couple.dark)
}
}
}
.padding(4)
@ -94,6 +84,10 @@ struct ThemeBoxView: View {
isSelected = newValue.rawValue == color.name.rawValue
}
.onTapGesture {
let currentScheme = theme.selectedScheme
if color.scheme != currentScheme {
theme.followSystemColorScheme = false
}
theme.selectedSet = color.name
}
}