feat: make copy action works in media preview scene
This commit is contained in:
parent
66de0593df
commit
4baaf3368b
|
@ -202,14 +202,10 @@ extension StatusTableViewCellDelegate where Self: StatusProvider {
|
|||
return self.context.photoLibraryService.copyImage(url: url)
|
||||
}
|
||||
.switchToLatest()
|
||||
.sink(receiveCompletion: { [weak self] completion in
|
||||
guard let self = self else { return }
|
||||
.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .failure(let error):
|
||||
guard let error = error as? PhotoLibraryService.PhotoLibraryError,
|
||||
case .noPermission = error else { return }
|
||||
let alertController = SettingService.openSettingsAlertController(title: L10n.Common.Alerts.SavePhotoFailure.title, message: L10n.Common.Alerts.SavePhotoFailure.message)
|
||||
self.coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil))
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: copy photo fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||
case .finished:
|
||||
break
|
||||
}
|
||||
|
|
|
@ -226,6 +226,24 @@ extension MediaPreviewViewController: MediaPreviewImageViewControllerDelegate {
|
|||
case .local(let meta):
|
||||
context.photoLibraryService.save(image: meta.image, withNotificationFeedback: true)
|
||||
}
|
||||
case .copyPhoto:
|
||||
switch viewController.viewModel.item {
|
||||
case .status(let meta):
|
||||
context.photoLibraryService.copyImage(url: meta.url)
|
||||
.sink { completion in
|
||||
switch completion {
|
||||
case .failure(let error):
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: copy photo fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||
case .finished:
|
||||
break
|
||||
}
|
||||
} receiveValue: { _ in
|
||||
// do nothing
|
||||
}
|
||||
.store(in: &context.disposeBag)
|
||||
case .local(let meta):
|
||||
context.photoLibraryService.copy(image: meta.image, withNotificationFeedback: true)
|
||||
}
|
||||
case .share:
|
||||
let applicationActivities: [UIActivity] = [
|
||||
SafariActivity(sceneCoordinator: self.coordinator)
|
||||
|
@ -236,6 +254,7 @@ extension MediaPreviewViewController: MediaPreviewImageViewControllerDelegate {
|
|||
)
|
||||
activityViewController.popoverPresentationController?.sourceView = viewController.previewImageView.imageView
|
||||
self.present(activityViewController, animated: true, completion: nil)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,14 @@ extension MediaPreviewImageViewController: UIContextMenuInteractionDelegate {
|
|||
guard let self = self else { return }
|
||||
self.delegate?.mediaPreviewImageViewController(self, contextMenuActionPerform: .savePhoto)
|
||||
}
|
||||
|
||||
let copyAction = UIAction(
|
||||
title: L10n.Common.Controls.Actions.copyPhoto, image: UIImage(systemName: "doc.on.doc")!, identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off
|
||||
) { [weak self] _ in
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: copy photo", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
guard let self = self else { return }
|
||||
self.delegate?.mediaPreviewImageViewController(self, contextMenuActionPerform: .copyPhoto)
|
||||
}
|
||||
|
||||
let shareAction = UIAction(
|
||||
title: L10n.Common.Controls.Actions.share, image: UIImage(systemName: "square.and.arrow.up")!, identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off
|
||||
|
@ -145,6 +153,7 @@ extension MediaPreviewImageViewController: UIContextMenuInteractionDelegate {
|
|||
let actionProvider: UIContextMenuActionProvider = { elements -> UIMenu? in
|
||||
return UIMenu(title: "", image: nil, identifier: nil, options: [], children: [
|
||||
saveAction,
|
||||
copyAction,
|
||||
shareAction
|
||||
])
|
||||
}
|
||||
|
@ -162,6 +171,7 @@ extension MediaPreviewImageViewController: UIContextMenuInteractionDelegate {
|
|||
extension MediaPreviewImageViewController {
|
||||
enum ContextMenuAction {
|
||||
case savePhoto
|
||||
case copyPhoto
|
||||
case share
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@ extension PhotoLibraryService {
|
|||
extension PhotoLibraryService {
|
||||
|
||||
func saveImage(url: URL) -> AnyPublisher<UIImage, Error> {
|
||||
guard PHPhotoLibrary.authorizationStatus(for: .addOnly) != .denied else {
|
||||
return Fail(error: PhotoLibraryError.noPermission).eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
return processImage(url: url)
|
||||
.handleEvents(receiveOutput: { image in
|
||||
self.save(image: image)
|
||||
|
@ -45,10 +49,6 @@ extension PhotoLibraryService {
|
|||
let impactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)
|
||||
let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
|
||||
|
||||
guard PHPhotoLibrary.authorizationStatus(for: .addOnly) != .denied else {
|
||||
return Fail(error: PhotoLibraryError.noPermission).eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
return ImagePipeline.shared.imagePublisher(with: url)
|
||||
.handleEvents(receiveSubscription: { _ in
|
||||
impactFeedbackGenerator.impactOccurred()
|
||||
|
@ -87,6 +87,16 @@ extension PhotoLibraryService {
|
|||
notificationFeedbackGenerator.notificationOccurred(.success)
|
||||
}
|
||||
}
|
||||
|
||||
func copy(image: UIImage, withNotificationFeedback: Bool = false) {
|
||||
UIPasteboard.general.image = image
|
||||
|
||||
// assert no error
|
||||
if withNotificationFeedback {
|
||||
let notificationFeedbackGenerator = UINotificationFeedbackGenerator()
|
||||
notificationFeedbackGenerator.notificationOccurred(.success)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
|
||||
// TODO: notify banner
|
||||
|
|
Loading…
Reference in New Issue