diff --git a/Tusker/Preferences/Colors.swift b/Tusker/Preferences/Colors.swift index 9a13b07e..59709b52 100644 --- a/Tusker/Preferences/Colors.swift +++ b/Tusker/Preferences/Colors.swift @@ -81,13 +81,30 @@ extension Color { static let appFill = Color(uiColor: .appFill) } +@available(iOS, obsoleted: 17.0) private let traitsKey: String = ["Traits", "Defined", "client", "_"].reversed().joined() +@available(iOS, obsoleted: 17.0) private let key = "tusker_usePureBlackDarkMode" +@available(iOS 17.0, *) +private struct PureBlackDarkModeTrait: UITraitDefinition { + static let defaultValue = true + static let affectsColorAppearance = true +} + extension UITraitCollection { var pureBlackDarkMode: Bool { + if #available(iOS 17.0, *) { + return self[PureBlackDarkModeTrait.self] + } else { + return obsoletePureBlackDarkMode + } + } + + @available(iOS, obsoleted: 17.0) + var obsoletePureBlackDarkMode: Bool { get { - // default to true to mach OS behavior + // default to true to match OS behavior (value(forKey: traitsKey) as? [String: Any])?[key] as? Bool ?? true } set { @@ -98,7 +115,19 @@ extension UITraitCollection { } convenience init(pureBlackDarkMode: Bool) { - self.init() - self.pureBlackDarkMode = pureBlackDarkMode + if #available(iOS 17.0, *) { + self.init(PureBlackDarkModeTrait.self, value: pureBlackDarkMode) + } else { + self.init() + self.obsoletePureBlackDarkMode = pureBlackDarkMode + } + } +} + +@available(iOS 17.0, *) +extension UIMutableTraits { + var pureBlackDarkMode: Bool { + get { self[PureBlackDarkModeTrait.self] } + set { self[PureBlackDarkModeTrait.self] = newValue } } } diff --git a/Tusker/Scenes/TuskerSceneDelegate.swift b/Tusker/Scenes/TuskerSceneDelegate.swift index df53630b..25de0c44 100644 --- a/Tusker/Scenes/TuskerSceneDelegate.swift +++ b/Tusker/Scenes/TuskerSceneDelegate.swift @@ -32,14 +32,18 @@ extension TuskerSceneDelegate { guard let window else { return } window.overrideUserInterfaceStyle = Preferences.shared.theme window.tintColor = Preferences.shared.accentColor.color - let exception = catchNSException { - let key = ["Controller", "Presentation", "root", "_"].reversed().joined() - if let rootPresentationController = window.value(forKey: key) as? UIPresentationController { - rootPresentationController.overrideTraitCollection = UITraitCollection(pureBlackDarkMode: Preferences.shared.pureBlackDarkMode) + if #available(iOS 17.0, *) { + window.traitOverrides.pureBlackDarkMode = Preferences.shared.pureBlackDarkMode + } else { + let exception = catchNSException { + let key = ["Controller", "Presentation", "root", "_"].reversed().joined() + if let rootPresentationController = window.value(forKey: key) as? UIPresentationController { + rootPresentationController.overrideTraitCollection = UITraitCollection(pureBlackDarkMode: Preferences.shared.pureBlackDarkMode) + } + } + if let exception { + SentrySDK.capture(exception: exception) } - } - if let exception { - SentrySDK.capture(exception: exception) } } } diff --git a/Tusker/Screens/Report/ReportAddStatusView.swift b/Tusker/Screens/Report/ReportAddStatusView.swift index f2a6d372..05ceaaa7 100644 --- a/Tusker/Screens/Report/ReportAddStatusView.swift +++ b/Tusker/Screens/Report/ReportAddStatusView.swift @@ -76,8 +76,14 @@ private struct ScrollBackgroundModifier: ViewModifier { // otherwise the pureBlackDarkMode isn't propagated, for some reason? // even though it is for ReportSelectRulesView?? let traits: UITraitCollection = { - let t = UITraitCollection(userInterfaceStyle: colorScheme == .dark ? .dark : .light) - t.pureBlackDarkMode = true + var t = UITraitCollection(userInterfaceStyle: colorScheme == .dark ? .dark : .light) + if #available(iOS 17.0, *) { + t = t.modifyingTraits({ mutableTraits in + mutableTraits.pureBlackDarkMode = true + }) + } else { + t.obsoletePureBlackDarkMode = true + } return t }() Color(uiColor: .appGroupedBackground.resolvedColor(with: traits))