diff --git a/Linphone/Utils/Extensions/ColorExtension.swift b/Linphone/Utils/Extensions/ColorExtension.swift index 111472603..61bb47671 100644 --- a/Linphone/Utils/Extensions/ColorExtension.swift +++ b/Linphone/Utils/Extensions/ColorExtension.swift @@ -22,15 +22,17 @@ import SwiftUI extension Color { + private static var theme: Theme { ColorProvider.shared.theme } + static let transparentColor = Color(hex: "#00000000") static let black = Color(hex: "#000000") static let white = Color(hex: "#FFFFFF") - static let orangeMain700 = ThemeManager.shared.currentTheme.main700 - static let orangeMain500 = ThemeManager.shared.currentTheme.main500 - static let orangeMain300 = ThemeManager.shared.currentTheme.main300 - static let orangeMain100 = ThemeManager.shared.currentTheme.main100 - static let orangeMain100Alpha50 = ThemeManager.shared.currentTheme.main100Alpha50 + static var orangeMain700: Color { theme.main700 } + static var orangeMain500: Color { theme.main500 } + static var orangeMain300: Color { theme.main300 } + static var orangeMain100: Color { theme.main100 } + static var orangeMain100Alpha50: Color { theme.main100Alpha50 } static let grayMain2c800 = Color(hex: "#22334D") static let grayMain2c800Alpha65 = Color(hex: "#A622334D") diff --git a/Linphone/Utils/ThemeManager.swift b/Linphone/Utils/ThemeManager.swift index cc8a892fc..7c51f17cf 100644 --- a/Linphone/Utils/ThemeManager.swift +++ b/Linphone/Utils/ThemeManager.swift @@ -18,9 +18,11 @@ */ import SwiftUI +import Combine +// MARK: - Theme definition -struct Theme { +struct Theme: Equatable { let name: String let main100: Color let main100Alpha50: Color @@ -29,26 +31,28 @@ struct Theme { let main700: Color } -class ThemeManager { - +// MARK: - Theme Manager + +final class ThemeManager: ObservableObject { static let shared = ThemeManager() private let themeKey = "selectedTheme" - var currentTheme: Theme - init () { + @Published var currentTheme: Theme = ThemeManager.orange + + private init() { let storedName = UserDefaults.standard.string(forKey: themeKey) currentTheme = themes[storedName ?? ""] ?? ThemeManager.orange } func applyTheme(named name: String) { - guard let theme = themes[name] else { - return + guard let theme = themes[name] else { return } + withAnimation(.easeInOut(duration: 0.3)) { + self.currentTheme = theme } - self.currentTheme = theme - UserDefaults.standard.setValue(name, forKey: self.themeKey) + UserDefaults.standard.setValue(name, forKey: themeKey) } - // MARK: - Theme Instances + // MARK: - Theme Presets let themes: [String: Theme] = [ orange.name: orange, @@ -122,5 +126,25 @@ class ThemeManager { main500: Color(hex: "#800080"), main700: Color(hex: "#520052") ) - +} + +// MARK: - Color Provider (reactive bridge for SwiftUI) + +final class ColorProvider: ObservableObject { + static let shared = ColorProvider() + + @Published private(set) var theme: Theme + private var cancellable: AnyCancellable? + + private init() { + let manager = ThemeManager.shared + self.theme = manager.currentTheme + + cancellable = manager.$currentTheme + .sink { [weak self] theme in + withAnimation(.easeInOut(duration: 0.3)) { + self?.theme = theme + } + } + } }