feat: restore keyboard shortcut for compose scene
This commit is contained in:
parent
af0dc45d1b
commit
591acb4c2c
|
@ -324,130 +324,137 @@ extension ComposeViewController: UIAdaptivePresentationControllerDelegate {
|
|||
|
||||
}
|
||||
|
||||
//extension ComposeViewController {
|
||||
// override var keyCommands: [UIKeyCommand]? {
|
||||
// composeKeyCommands
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//extension ComposeViewController {
|
||||
//
|
||||
// enum ComposeKeyCommand: String, CaseIterable {
|
||||
// case discardPost
|
||||
// case publishPost
|
||||
// case mediaBrowse
|
||||
// case mediaPhotoLibrary
|
||||
// case mediaCamera
|
||||
// case togglePoll
|
||||
// case toggleContentWarning
|
||||
// case selectVisibilityPublic
|
||||
// // TODO: remove selectVisibilityUnlisted from codebase
|
||||
// // case selectVisibilityUnlisted
|
||||
// case selectVisibilityPrivate
|
||||
// case selectVisibilityDirect
|
||||
//
|
||||
// var title: String {
|
||||
// switch self {
|
||||
// case .discardPost: return L10n.Scene.Compose.Keyboard.discardPost
|
||||
// case .publishPost: return L10n.Scene.Compose.Keyboard.publishPost
|
||||
// case .mediaBrowse: return L10n.Scene.Compose.Keyboard.appendAttachmentEntry(L10n.Scene.Compose.MediaSelection.browse)
|
||||
// case .mediaPhotoLibrary: return L10n.Scene.Compose.Keyboard.appendAttachmentEntry(L10n.Scene.Compose.MediaSelection.photoLibrary)
|
||||
// case .mediaCamera: return L10n.Scene.Compose.Keyboard.appendAttachmentEntry(L10n.Scene.Compose.MediaSelection.camera)
|
||||
// case .togglePoll: return L10n.Scene.Compose.Keyboard.togglePoll
|
||||
// case .toggleContentWarning: return L10n.Scene.Compose.Keyboard.toggleContentWarning
|
||||
// case .selectVisibilityPublic: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.public)
|
||||
// // case .selectVisibilityUnlisted: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.unlisted)
|
||||
// case .selectVisibilityPrivate: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.private)
|
||||
// case .selectVisibilityDirect: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.direct)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // UIKeyCommand input
|
||||
// var input: String {
|
||||
// switch self {
|
||||
// case .discardPost: return "w" // + command
|
||||
// case .publishPost: return "\r" // (enter) + command
|
||||
// case .mediaBrowse: return "b" // + option + command
|
||||
// case .mediaPhotoLibrary: return "p" // + option + command
|
||||
// case .mediaCamera: return "c" // + option + command
|
||||
// case .togglePoll: return "p" // + shift + command
|
||||
// case .toggleContentWarning: return "c" // + shift + command
|
||||
// case .selectVisibilityPublic: return "1" // + command
|
||||
// // case .selectVisibilityUnlisted: return "2" // + command
|
||||
// case .selectVisibilityPrivate: return "2" // + command
|
||||
// case .selectVisibilityDirect: return "3" // + command
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var modifierFlags: UIKeyModifierFlags {
|
||||
// switch self {
|
||||
// case .discardPost: return [.command]
|
||||
// case .publishPost: return [.command]
|
||||
// case .mediaBrowse: return [.alternate, .command]
|
||||
// case .mediaPhotoLibrary: return [.alternate, .command]
|
||||
// case .mediaCamera: return [.alternate, .command]
|
||||
// case .togglePoll: return [.shift, .command]
|
||||
// case .toggleContentWarning: return [.shift, .command]
|
||||
// case .selectVisibilityPublic: return [.command]
|
||||
// // case .selectVisibilityUnlisted: return [.command]
|
||||
// case .selectVisibilityPrivate: return [.command]
|
||||
// case .selectVisibilityDirect: return [.command]
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var propertyList: Any {
|
||||
// return rawValue
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var composeKeyCommands: [UIKeyCommand]? {
|
||||
// ComposeKeyCommand.allCases.map { command in
|
||||
// UIKeyCommand(
|
||||
// title: command.title,
|
||||
// image: nil,
|
||||
// action: #selector(Self.composeKeyCommandHandler(_:)),
|
||||
// input: command.input,
|
||||
// modifierFlags: command.modifierFlags,
|
||||
// propertyList: command.propertyList,
|
||||
// alternates: [],
|
||||
// discoverabilityTitle: nil,
|
||||
// attributes: [],
|
||||
// state: .off
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @objc private func composeKeyCommandHandler(_ sender: UIKeyCommand) {
|
||||
// guard let rawValue = sender.propertyList as? String,
|
||||
// let command = ComposeKeyCommand(rawValue: rawValue) else { return }
|
||||
//
|
||||
// switch command {
|
||||
// case .discardPost:
|
||||
// cancelBarButtonItemPressed(cancelBarButtonItem)
|
||||
// case .publishPost:
|
||||
// publishBarButtonItemPressed(publishBarButtonItem)
|
||||
// case .mediaBrowse:
|
||||
// present(documentPickerController, animated: true, completion: nil)
|
||||
// case .mediaPhotoLibrary:
|
||||
// present(photoLibraryPicker, animated: true, completion: nil)
|
||||
// case .mediaCamera:
|
||||
// guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
|
||||
// return
|
||||
// }
|
||||
// present(imagePickerController, animated: true, completion: nil)
|
||||
// case .togglePoll:
|
||||
// composeToolbarView.pollButton.sendActions(for: .touchUpInside)
|
||||
// case .toggleContentWarning:
|
||||
// composeToolbarView.contentWarningButton.sendActions(for: .touchUpInside)
|
||||
// case .selectVisibilityPublic:
|
||||
// viewModel.selectedStatusVisibility = .public
|
||||
// // case .selectVisibilityUnlisted:
|
||||
// // viewModel.selectedStatusVisibility.value = .unlisted
|
||||
// case .selectVisibilityPrivate:
|
||||
// viewModel.selectedStatusVisibility = .private
|
||||
// case .selectVisibilityDirect:
|
||||
// viewModel.selectedStatusVisibility = .direct
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
extension ComposeViewController {
|
||||
override var keyCommands: [UIKeyCommand]? {
|
||||
composeKeyCommands
|
||||
}
|
||||
}
|
||||
|
||||
extension ComposeViewController {
|
||||
|
||||
enum ComposeKeyCommand: String, CaseIterable {
|
||||
case discardPost
|
||||
case publishPost
|
||||
case mediaBrowse
|
||||
case mediaPhotoLibrary
|
||||
case mediaCamera
|
||||
case togglePoll
|
||||
case toggleContentWarning
|
||||
case selectVisibilityPublic
|
||||
// TODO: remove selectVisibilityUnlisted from codebase
|
||||
// case selectVisibilityUnlisted
|
||||
case selectVisibilityPrivate
|
||||
case selectVisibilityDirect
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .discardPost: return L10n.Scene.Compose.Keyboard.discardPost
|
||||
case .publishPost: return L10n.Scene.Compose.Keyboard.publishPost
|
||||
case .mediaBrowse: return L10n.Scene.Compose.Keyboard.appendAttachmentEntry(L10n.Scene.Compose.MediaSelection.browse)
|
||||
case .mediaPhotoLibrary: return L10n.Scene.Compose.Keyboard.appendAttachmentEntry(L10n.Scene.Compose.MediaSelection.photoLibrary)
|
||||
case .mediaCamera: return L10n.Scene.Compose.Keyboard.appendAttachmentEntry(L10n.Scene.Compose.MediaSelection.camera)
|
||||
case .togglePoll: return L10n.Scene.Compose.Keyboard.togglePoll
|
||||
case .toggleContentWarning: return L10n.Scene.Compose.Keyboard.toggleContentWarning
|
||||
case .selectVisibilityPublic: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.public)
|
||||
// case .selectVisibilityUnlisted: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.unlisted)
|
||||
case .selectVisibilityPrivate: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.private)
|
||||
case .selectVisibilityDirect: return L10n.Scene.Compose.Keyboard.selectVisibilityEntry(L10n.Scene.Compose.Visibility.direct)
|
||||
}
|
||||
}
|
||||
|
||||
// UIKeyCommand input
|
||||
var input: String {
|
||||
switch self {
|
||||
case .discardPost: return "w" // + command
|
||||
case .publishPost: return "\r" // (enter) + command
|
||||
case .mediaBrowse: return "b" // + option + command
|
||||
case .mediaPhotoLibrary: return "p" // + option + command
|
||||
case .mediaCamera: return "c" // + option + command
|
||||
case .togglePoll: return "p" // + shift + command
|
||||
case .toggleContentWarning: return "c" // + shift + command
|
||||
case .selectVisibilityPublic: return "1" // + command
|
||||
// case .selectVisibilityUnlisted: return "2" // + command
|
||||
case .selectVisibilityPrivate: return "2" // + command
|
||||
case .selectVisibilityDirect: return "3" // + command
|
||||
}
|
||||
}
|
||||
|
||||
var modifierFlags: UIKeyModifierFlags {
|
||||
switch self {
|
||||
case .discardPost: return [.command]
|
||||
case .publishPost: return [.command]
|
||||
case .mediaBrowse: return [.alternate, .command]
|
||||
case .mediaPhotoLibrary: return [.alternate, .command]
|
||||
case .mediaCamera: return [.alternate, .command]
|
||||
case .togglePoll: return [.shift, .command]
|
||||
case .toggleContentWarning: return [.shift, .command]
|
||||
case .selectVisibilityPublic: return [.command]
|
||||
// case .selectVisibilityUnlisted: return [.command]
|
||||
case .selectVisibilityPrivate: return [.command]
|
||||
case .selectVisibilityDirect: return [.command]
|
||||
}
|
||||
}
|
||||
|
||||
var propertyList: Any {
|
||||
return rawValue
|
||||
}
|
||||
}
|
||||
|
||||
var composeKeyCommands: [UIKeyCommand]? {
|
||||
ComposeKeyCommand.allCases.map { command in
|
||||
UIKeyCommand(
|
||||
title: command.title,
|
||||
image: nil,
|
||||
action: #selector(Self.composeKeyCommandHandler(_:)),
|
||||
input: command.input,
|
||||
modifierFlags: command.modifierFlags,
|
||||
propertyList: command.propertyList,
|
||||
alternates: [],
|
||||
discoverabilityTitle: nil,
|
||||
attributes: [],
|
||||
state: .off
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func composeKeyCommandHandler(_ sender: UIKeyCommand) {
|
||||
guard let rawValue = sender.propertyList as? String,
|
||||
let command = ComposeKeyCommand(rawValue: rawValue) else { return }
|
||||
|
||||
switch command {
|
||||
case .discardPost:
|
||||
cancelBarButtonItemPressed(cancelBarButtonItem)
|
||||
case .publishPost:
|
||||
publishBarButtonItemPressed(publishBarButtonItem)
|
||||
case .mediaBrowse:
|
||||
guard !isViewControllerIsAlreadyModal(composeContentViewController.documentPickerController) else { return }
|
||||
present(composeContentViewController.documentPickerController, animated: true, completion: nil)
|
||||
case .mediaPhotoLibrary:
|
||||
guard !isViewControllerIsAlreadyModal(composeContentViewController.photoLibraryPicker) else { return }
|
||||
present(composeContentViewController.photoLibraryPicker, animated: true, completion: nil)
|
||||
case .mediaCamera:
|
||||
guard UIImagePickerController.isSourceTypeAvailable(.camera) else {
|
||||
return
|
||||
}
|
||||
guard !isViewControllerIsAlreadyModal(composeContentViewController.imagePickerController) else { return }
|
||||
present(composeContentViewController.imagePickerController, animated: true, completion: nil)
|
||||
case .togglePoll:
|
||||
composeContentViewModel.isPollActive.toggle()
|
||||
case .toggleContentWarning:
|
||||
composeContentViewModel.isContentWarningActive.toggle()
|
||||
case .selectVisibilityPublic:
|
||||
composeContentViewModel.visibility = .public
|
||||
// case .selectVisibilityUnlisted:
|
||||
// viewModel.selectedStatusVisibility.value = .unlisted
|
||||
case .selectVisibilityPrivate:
|
||||
composeContentViewModel.visibility = .private
|
||||
case .selectVisibilityDirect:
|
||||
composeContentViewModel.visibility = .direct
|
||||
}
|
||||
}
|
||||
|
||||
private func isViewControllerIsAlreadyModal(_ viewController: UIViewController) -> Bool {
|
||||
return viewController.presentingViewController != nil
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,20 +55,20 @@ public final class ComposeContentViewController: UIViewController {
|
|||
return configuration
|
||||
}
|
||||
|
||||
private(set) lazy var photoLibraryPicker: PHPickerViewController = {
|
||||
public private(set) lazy var photoLibraryPicker: PHPickerViewController = {
|
||||
let imagePicker = PHPickerViewController(configuration: ComposeContentViewController.createPhotoLibraryPickerConfiguration())
|
||||
imagePicker.delegate = self
|
||||
return imagePicker
|
||||
}()
|
||||
|
||||
private(set) lazy var imagePickerController: UIImagePickerController = {
|
||||
public private(set) lazy var imagePickerController: UIImagePickerController = {
|
||||
let imagePickerController = UIImagePickerController()
|
||||
imagePickerController.sourceType = .camera
|
||||
imagePickerController.delegate = self
|
||||
return imagePickerController
|
||||
}()
|
||||
|
||||
private(set) lazy var documentPickerController: UIDocumentPickerViewController = {
|
||||
public private(set) lazy var documentPickerController: UIDocumentPickerViewController = {
|
||||
let documentPickerController = UIDocumentPickerViewController(forOpeningContentTypes: [.image, .movie])
|
||||
documentPickerController.delegate = self
|
||||
return documentPickerController
|
||||
|
@ -342,6 +342,7 @@ extension ComposeContentViewController {
|
|||
// bind back to source due to visibility not update via delegate
|
||||
composeContentToolbarViewModel.$visibility
|
||||
.dropFirst()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] visibility in
|
||||
guard let self = self else { return }
|
||||
if self.viewModel.visibility != visibility {
|
||||
|
|
|
@ -91,7 +91,7 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
|||
// @Published public internal(set) var isMediaValid = true
|
||||
|
||||
// poll
|
||||
@Published var isPollActive = false
|
||||
@Published public var isPollActive = false
|
||||
@Published public var pollOptions: [PollComposeItem.Option] = {
|
||||
// initial with 2 options
|
||||
var options: [PollComposeItem.Option] = []
|
||||
|
@ -111,7 +111,7 @@ public final class ComposeContentViewModel: NSObject, ObservableObject {
|
|||
@Published var isLoadingCustomEmoji = false
|
||||
|
||||
// visibility
|
||||
@Published var visibility: Mastodon.Entity.Status.Visibility
|
||||
@Published public var visibility: Mastodon.Entity.Status.Visibility
|
||||
|
||||
// UI & UX
|
||||
@Published var replyToCellFrame: CGRect = .zero
|
||||
|
|
Loading…
Reference in New Issue