2023-01-08 18:49:49 +00:00
|
|
|
import SwiftUI
|
|
|
|
#if canImport(UIKit)
|
2023-01-17 10:36:01 +00:00
|
|
|
import UIKit
|
2023-01-08 18:49:49 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
public extension View {
|
2023-01-17 10:36:01 +00:00
|
|
|
func applyTheme(_ theme: Theme) -> some View {
|
|
|
|
modifier(ThemeApplier(theme: theme))
|
|
|
|
}
|
2023-01-08 18:49:49 +00:00
|
|
|
}
|
|
|
|
|
2023-09-18 19:03:52 +00:00
|
|
|
@MainActor
|
2023-01-08 18:49:49 +00:00
|
|
|
struct ThemeApplier: ViewModifier {
|
2023-01-20 20:58:57 +00:00
|
|
|
@Environment(\EnvironmentValues.colorScheme) var colorScheme
|
2023-01-22 05:38:30 +00:00
|
|
|
|
2023-09-18 19:03:52 +00:00
|
|
|
var theme: Theme
|
2023-01-22 05:38:30 +00:00
|
|
|
|
2023-01-20 20:58:57 +00:00
|
|
|
var actualColorScheme: SwiftUI.ColorScheme? {
|
|
|
|
if theme.followSystemColorScheme {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return theme.selectedScheme == ColorScheme.dark ? .dark : .light
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
|
|
|
func body(content: Content) -> some View {
|
|
|
|
content
|
|
|
|
.tint(theme.tintColor)
|
2023-01-20 20:58:57 +00:00
|
|
|
.preferredColorScheme(actualColorScheme)
|
2023-01-08 18:49:49 +00:00
|
|
|
#if canImport(UIKit)
|
2023-01-17 10:36:01 +00:00
|
|
|
.onAppear {
|
2023-01-20 20:58:57 +00:00
|
|
|
// If theme is never set before set the default store. This should only execute once after install.
|
|
|
|
if !theme.isThemePreviouslySet {
|
2023-09-20 06:20:01 +00:00
|
|
|
theme.applySet(set: colorScheme == .dark ? .iceCubeDark : .iceCubeLight)
|
2023-01-20 20:58:57 +00:00
|
|
|
theme.isThemePreviouslySet = true
|
2023-01-22 05:38:30 +00:00
|
|
|
} else if theme.followSystemColorScheme, theme.isThemePreviouslySet,
|
2023-01-21 14:54:15 +00:00
|
|
|
let sets = availableColorsSets
|
2023-01-22 05:38:30 +00:00
|
|
|
.first(where: { $0.light.name == theme.selectedSet || $0.dark.name == theme.selectedSet })
|
|
|
|
{
|
2023-09-20 06:20:01 +00:00
|
|
|
theme.applySet(set: colorScheme == .dark ? sets.dark.name : sets.light.name)
|
2023-01-20 20:58:57 +00:00
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
setWindowTint(theme.tintColor)
|
2023-01-29 12:24:51 +00:00
|
|
|
setWindowUserInterfaceStyle(from: theme.selectedScheme)
|
2023-01-17 10:36:01 +00:00
|
|
|
setBarsColor(theme.primaryBackgroundColor)
|
|
|
|
}
|
2023-09-18 05:01:23 +00:00
|
|
|
.onChange(of: theme.tintColor) { _, newValue in
|
2023-01-17 10:36:01 +00:00
|
|
|
setWindowTint(newValue)
|
|
|
|
}
|
2023-09-18 05:01:23 +00:00
|
|
|
.onChange(of: theme.primaryBackgroundColor) { _, newValue in
|
2023-01-17 10:36:01 +00:00
|
|
|
setBarsColor(newValue)
|
|
|
|
}
|
2023-09-18 05:01:23 +00:00
|
|
|
.onChange(of: theme.selectedScheme) { _, newValue in
|
2023-01-30 06:27:06 +00:00
|
|
|
setWindowUserInterfaceStyle(from: newValue)
|
2023-01-29 12:24:51 +00:00
|
|
|
}
|
2023-09-18 05:01:23 +00:00
|
|
|
.onChange(of: colorScheme) { _, newColorScheme in
|
2023-01-20 20:58:57 +00:00
|
|
|
if theme.followSystemColorScheme,
|
|
|
|
let sets = availableColorsSets
|
2023-01-22 05:38:30 +00:00
|
|
|
.first(where: { $0.light.name == theme.selectedSet || $0.dark.name == theme.selectedSet })
|
|
|
|
{
|
2023-09-20 06:20:01 +00:00
|
|
|
theme.applySet(set: newColorScheme == .dark ? sets.dark.name : sets.light.name)
|
2023-01-20 20:58:57 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if canImport(UIKit)
|
2023-01-29 12:24:51 +00:00
|
|
|
private func setWindowUserInterfaceStyle(from colorScheme: ColorScheme) {
|
|
|
|
guard !theme.followSystemColorScheme else {
|
2023-01-30 06:27:06 +00:00
|
|
|
setWindowUserInterfaceStyle(.unspecified)
|
|
|
|
return
|
2023-01-29 12:24:51 +00:00
|
|
|
}
|
|
|
|
switch colorScheme {
|
|
|
|
case .dark:
|
|
|
|
setWindowUserInterfaceStyle(.dark)
|
|
|
|
case .light:
|
|
|
|
setWindowUserInterfaceStyle(.light)
|
|
|
|
}
|
|
|
|
}
|
2023-01-30 06:27:06 +00:00
|
|
|
|
2023-01-29 12:24:51 +00:00
|
|
|
private func setWindowUserInterfaceStyle(_ userInterfaceStyle: UIUserInterfaceStyle) {
|
2024-02-14 11:48:14 +00:00
|
|
|
for window in allWindows() {
|
|
|
|
window.overrideUserInterfaceStyle = userInterfaceStyle
|
|
|
|
}
|
2023-01-29 12:24:51 +00:00
|
|
|
}
|
2023-01-30 06:27:06 +00:00
|
|
|
|
2023-01-08 18:49:49 +00:00
|
|
|
private func setWindowTint(_ color: Color) {
|
2024-02-14 11:48:14 +00:00
|
|
|
for window in allWindows() {
|
|
|
|
window.tintColor = UIColor(color)
|
|
|
|
}
|
2023-01-08 18:49:49 +00:00
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-08 18:49:49 +00:00
|
|
|
private func setBarsColor(_ color: Color) {
|
2023-01-17 10:36:01 +00:00
|
|
|
UINavigationBar.appearance().isTranslucent = true
|
|
|
|
UINavigationBar.appearance().barTintColor = UIColor(color)
|
2023-01-08 18:49:49 +00:00
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
|
2023-01-08 18:49:49 +00:00
|
|
|
private func allWindows() -> [UIWindow] {
|
2023-01-17 10:36:01 +00:00
|
|
|
UIApplication.shared.connectedScenes
|
|
|
|
.compactMap { $0 as? UIWindowScene }
|
2023-09-16 12:15:03 +00:00
|
|
|
.flatMap(\.windows)
|
2023-01-08 18:49:49 +00:00
|
|
|
}
|
2023-01-17 10:36:01 +00:00
|
|
|
#endif
|
2023-01-08 18:49:49 +00:00
|
|
|
}
|