diff --git a/SignalUI/UIKitExtensions/UIButton+SignalUI.swift b/SignalUI/UIKitExtensions/UIButton+SignalUI.swift index c941f0657d..a46af6a235 100644 --- a/SignalUI/UIKitExtensions/UIButton+SignalUI.swift +++ b/SignalUI/UIKitExtensions/UIButton+SignalUI.swift @@ -206,41 +206,16 @@ public extension UIButton.Configuration { return configuration } - /// Round button that has glass material background on iOS 26+ and no background on older iOS versions. - static func round(image: UIImage) -> Self { - var configuration: UIButton.Configuration - if #available(iOS 26, *) { - configuration = .glass() - } else { - configuration = .plain() - } - configuration.image = image - configuration.baseForegroundColor = .Signal.label - configuration.cornerStyle = .capsule - configuration.contentInsets = .init(margin: 10) // 44 dp wide and tall if icon is a standard 24x24 - return configuration - } - - /// Round button that has glass material background on iOS 26+ and no background on older iOS versions. static func round(themeIcon: ThemeIcon) -> Self { - round(image: Theme.iconImage(themeIcon)) - } - - /// Round button that has glass material background on iOS 26+ and "system chrome" blur on older iOS versions. - static func roundMaterial(image: UIImage) -> Self { var configuration: UIButton.Configuration if #available(iOS 26, *) { configuration = .glass() + configuration.cornerStyle = .capsule } else { configuration = .plain() - - var backgroundConfiguration = UIBackgroundConfiguration.clear() - backgroundConfiguration.customView = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial)) - configuration.background = backgroundConfiguration } - configuration.image = image + configuration.image = Theme.iconImage(themeIcon) configuration.baseForegroundColor = .Signal.label - configuration.cornerStyle = .capsule configuration.contentInsets = .init(margin: 10) // 44 dp wide and tall if icon is a standard 24x24 return configuration } diff --git a/SignalUI/ViewControllers/ScanQRCodeViewController.swift b/SignalUI/ViewControllers/ScanQRCodeViewController.swift index f9e38ed294..48139705d3 100644 --- a/SignalUI/ViewControllers/ScanQRCodeViewController.swift +++ b/SignalUI/ViewControllers/ScanQRCodeViewController.swift @@ -185,7 +185,7 @@ public class QRCodeScanViewController: OWSViewController { fileprivate var backgroundColor: UIColor { switch self { case .framed: - return .Signal.background + return .ows_black case .unadorned: return .clear } @@ -219,26 +219,39 @@ public class QRCodeScanViewController: OWSViewController { return true } - private lazy var uploadPhotoButton = UIButton( - configuration: .roundMaterial(image: Theme.iconImage(.buttonPhotoLibrary)), - primaryAction: UIAction { [weak self] _ in + private lazy var uploadPhotoButton: UIButton = { + let button = OWSRoundedButton { [weak self] in guard let self else { return } self.delegate?.didTapUploadPhotoButton(self) - }, - ) + } + + button.ows_contentEdgeInsets = UIEdgeInsets(margin: 14) + + // Always use dark theming since it sits over the scan mask. + button.setTemplateImageName( + Theme.iconName(.buttonPhotoLibrary), + tintColor: .ows_white, + ) + button.backgroundColor = .ows_whiteAlpha20 + + return button + }() // MARK: - View Lifecycle override public func viewDidLoad() { + AssertIsOnMainThread() + super.viewDidLoad() - overrideUserInterfaceStyle = .dark view.backgroundColor = appearance.backgroundColor addObservers() } override public func viewDidAppear(_ animated: Bool) { + AssertIsOnMainThread() + super.viewDidAppear(animated) tryToStartScanning() @@ -253,6 +266,8 @@ public class QRCodeScanViewController: OWSViewController { } override public func viewDidDisappear(_ animated: Bool) { + AssertIsOnMainThread() + super.viewDidDisappear(animated) stopScanning() @@ -261,6 +276,8 @@ public class QRCodeScanViewController: OWSViewController { // MARK: - Notifications private func addObservers() { + AssertIsOnMainThread() + NotificationCenter.default.addObserver( self, selector: #selector(didEnterBackground), @@ -289,11 +306,15 @@ public class QRCodeScanViewController: OWSViewController { @objc private func didEnterBackground() { + AssertIsOnMainThread() + stopScanning() } @objc private func didBecomeActive() { + AssertIsOnMainThread() + if self.view.window != nil { tryToStartScanning() } @@ -333,6 +354,8 @@ public class QRCodeScanViewController: OWSViewController { @objc public func tryToStartScanning() { + AssertIsOnMainThread() + guard nil == scanner else { Logger.info("Early return because scanner is not nil") return @@ -380,6 +403,8 @@ public class QRCodeScanViewController: OWSViewController { } private func startScanning() { + AssertIsOnMainThread() + guard scanner == nil else { owsFailDebug("already scanning") return @@ -803,6 +828,8 @@ private class QRCodeScanner { } func startVideoCapture(initialOrientation: UIInterfaceOrientation) -> Promise { + AssertIsOnMainThread() + guard !Platform.isSimulator else { // Trying to actually set up the capture session will fail on a simulator // since we don't have actual capture devices. But it's useful to be able