From fadd19d847d40f03a3cbbc7b508b280e11df505b Mon Sep 17 00:00:00 2001 From: Ghazi Tozri Date: Tue, 1 Sep 2026 11:15:28 +0200 Subject: [PATCH] Fix photo picker selection tint on iOS 26 On iOS 26 the picker's remote process samples the window's tint color when it connects, ignoring the view-level override, which left the selection badges white on grey in dark mode. Temporarily override the window tint while the picker is presented and restore it when picking finishes or the picker is dismantled. --- .../PhotoLibraryPicker.swift | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift b/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift index d414bd7a9..a10dd525f 100644 --- a/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift +++ b/ElementX/Sources/Screens/MediaPickerScreen/PhotoLibraryPicker.swift @@ -50,9 +50,19 @@ struct PhotoLibraryPicker: UIViewControllerRepresentable { } func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) { - // Override the app wide tint color (currently set to `.compound.texActionPrimary + // Override the app wide tint color (currently set to `.compound.texActionPrimary`) // as it's not legible enough in dark mode uiViewController.view.tintColor = .compound.textActionAccent + + // On iOS 26 the picker reads the window's tint instead so we need + // to make this workaround to override the window tint + DispatchQueue.main.async { [coordinator = context.coordinator] in + coordinator.overrideWindowTint(of: uiViewController) + } + } + + static func dismantleUIViewController(_ uiViewController: PHPickerViewController, coordinator: Coordinator) { + coordinator.restoreWindowTint() } func makeCoordinator() -> Coordinator { @@ -62,15 +72,32 @@ struct PhotoLibraryPicker: UIViewControllerRepresentable { final class Coordinator: NSObject, PHPickerViewControllerDelegate { private var photoLibraryPicker: PhotoLibraryPicker + private weak var overriddenWindow: UIWindow? + private var originalWindowTint: UIColor? + init(_ photoLibraryPicker: PhotoLibraryPicker) { self.photoLibraryPicker = photoLibraryPicker } + func overrideWindowTint(of pickerViewController: PHPickerViewController) { + guard overriddenWindow == nil, let window = pickerViewController.view.window else { return } + overriddenWindow = window + originalWindowTint = window.tintColor + window.tintColor = .compound.textActionAccent + } + + func restoreWindowTint() { + overriddenWindow?.tintColor = originalWindowTint + overriddenWindow = nil + } + // MARK: PHPickerViewControllerDelegate private static let loadingIndicatorIdentifier = "\(PhotoLibraryPicker.self)-Loading" func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { + restoreWindowTint() + guard !results.isEmpty else { photoLibraryPicker.callback(.cancel) return