From c974e79d101fad1d55d2595478a6d4801a9c4ecd Mon Sep 17 00:00:00 2001 From: stakeswky Date: Sun, 22 Feb 2026 21:38:22 +0800 Subject: [PATCH] Fix: add Cancel button to photo picker on macOS when Photos library is empty When the Photos library is empty on macOS (Catalyst), PHPickerViewController renders no close/cancel button and ignores Esc/Cmd+Q, leaving the user unable to dismiss the picker without force-quitting the app (issue #507). Fix: after presenting the picker, inject a UIBarButtonItem(.cancel) into its navigationItem.leftBarButtonItem under #if targetEnvironment(macCatalyst). Tapping it dismisses the picker and calls the completion handler with nil, matching the existing behaviour for a cancelled pick. Fixes #507 --- .../photo-picker/GalleryPhotoPicker.swift | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/KeePassium/util/photo-picker/GalleryPhotoPicker.swift b/KeePassium/util/photo-picker/GalleryPhotoPicker.swift index 89ed8be33..7454f5f91 100644 --- a/KeePassium/util/photo-picker/GalleryPhotoPicker.swift +++ b/KeePassium/util/photo-picker/GalleryPhotoPicker.swift @@ -27,8 +27,29 @@ final class GalleryPhotoPicker: PhotoPicker { } override internal func _pickImageInternal() { - _presenter?.present(picker, animated: true, completion: nil) + _presenter?.present(picker, animated: true) { [weak self] in + #if targetEnvironment(macCatalyst) + // On macOS, PHPickerViewController shows no close button when the Photos library is + // empty, leaving the user with no way to dismiss it (issue #507). + // Inject a Cancel button into the navigation bar as a reliable escape hatch. + guard let self else { return } + let cancelButton = UIBarButtonItem( + barButtonSystemItem: .cancel, + target: self, + action: #selector(self.cancelPicker) + ) + self.picker.navigationItem.leftBarButtonItem = cancelButton + #endif + } + } + + #if targetEnvironment(macCatalyst) + @objc private func cancelPicker() { + _presenter?.dismiss(animated: true) { [weak self] in + self?._completion?(.success(nil)) + } } + #endif override class func isAllowed() -> Bool { #if INTUNE