Refactor verified alert to use edit menu
This commit is contained in:
parent
72873fbfc1
commit
197e180ccd
|
@ -51,10 +51,6 @@
|
|||
"clean_cache": {
|
||||
"title": "Clean Cache",
|
||||
"message": "Successfully cleaned %s cache."
|
||||
},
|
||||
"verified": {
|
||||
"title": "Verified",
|
||||
"message": "Ownership of this link was checked on %s"
|
||||
}
|
||||
},
|
||||
"controls": {
|
||||
|
@ -442,6 +438,10 @@
|
|||
"placeholder": {
|
||||
"label": "Label",
|
||||
"content": "Content"
|
||||
},
|
||||
"verified": {
|
||||
"short": "Verified at %s",
|
||||
"long": "Ownership of this link was checked on %s"
|
||||
}
|
||||
},
|
||||
"segmented_control": {
|
||||
|
|
|
@ -67,14 +67,17 @@ extension ProfileFieldSection {
|
|||
}
|
||||
cell.backgroundConfiguration = backgroundConfiguration
|
||||
|
||||
// set checkmark
|
||||
// set checkmark and edit menu label
|
||||
cell.checkmark.isHidden = true
|
||||
cell.checkmarkPopoverString = nil
|
||||
if let verifiedAt = field.verifiedAt.value {
|
||||
cell.checkmark.isHidden = false
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .short
|
||||
cell.checkmark.accessibilityLabel = L10n.Common.Alerts.Verified.message(formatter.string(from: verifiedAt))
|
||||
let dateString = formatter.string(from: verifiedAt)
|
||||
cell.checkmark.accessibilityLabel = L10n.Scene.Profile.Fields.Verified.long(dateString)
|
||||
cell.checkmarkPopoverString = L10n.Scene.Profile.Fields.Verified.short(dateString)
|
||||
}
|
||||
|
||||
cell.delegate = configuration.profileFieldCollectionViewCellDelegate
|
||||
|
|
|
@ -14,11 +14,6 @@ import MastodonLocalization
|
|||
|
||||
protocol ProfileFieldCollectionViewCellDelegate: AnyObject {
|
||||
func profileFieldCollectionViewCell(_ cell: ProfileFieldCollectionViewCell, metaLebel: MetaLabel, didSelectMeta meta: Meta)
|
||||
func profileFieldCollectionViewCell(_ cell: ProfileFieldCollectionViewCell, didTapAction: ProfileFieldCollectionViewCellAction)
|
||||
}
|
||||
|
||||
enum ProfileFieldCollectionViewCellAction {
|
||||
case Checkmark
|
||||
}
|
||||
|
||||
final class ProfileFieldCollectionViewCell: UICollectionViewCell {
|
||||
|
@ -32,7 +27,14 @@ final class ProfileFieldCollectionViewCell: UICollectionViewCell {
|
|||
let valueMetaLabel = MetaLabel(style: .profileFieldValue)
|
||||
|
||||
let checkmark = UIImageView(image: Asset.Editing.checkmark.image.withRenderingMode(.alwaysTemplate))
|
||||
var checkmarkPopoverString: String? = nil;
|
||||
let tapGesture = UITapGestureRecognizer();
|
||||
private var _editMenuInteraction: Any? = nil
|
||||
@available(iOS 16, *)
|
||||
fileprivate var editMenuInteraction: UIEditMenuInteraction {
|
||||
_editMenuInteraction = _editMenuInteraction ?? UIEditMenuInteraction(delegate: self)
|
||||
return _editMenuInteraction as! UIEditMenuInteraction
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
|
@ -62,6 +64,9 @@ extension ProfileFieldCollectionViewCell {
|
|||
tapGesture.addTarget(self, action: #selector(ProfileFieldCollectionViewCell.didTapCheckmark(_:)))
|
||||
checkmark.addGestureRecognizer(tapGesture)
|
||||
checkmark.isUserInteractionEnabled = true
|
||||
if #available(iOS 16, *) {
|
||||
checkmark.addInteraction(editMenuInteraction)
|
||||
}
|
||||
|
||||
// containerStackView: V - [ metaContainer | plainContainer ]
|
||||
let containerStackView = UIStackView()
|
||||
|
@ -99,10 +104,42 @@ extension ProfileFieldCollectionViewCell {
|
|||
valueMetaLabel.linkDelegate = self
|
||||
}
|
||||
|
||||
@objc public func didTapCheckmark(_: UITapGestureRecognizer) {
|
||||
delegate?.profileFieldCollectionViewCell(self, didTapAction: .Checkmark)
|
||||
@objc public func didTapCheckmark(_ recognizer: UITapGestureRecognizer) {
|
||||
if #available(iOS 16, *) {
|
||||
editMenuInteraction.presentEditMenu(with: UIEditMenuConfiguration(identifier: nil, sourcePoint: recognizer.location(in: checkmark)))
|
||||
} else {
|
||||
guard let editMenuLabel = checkmarkPopoverString else { return }
|
||||
|
||||
self.isUserInteractionEnabled = true
|
||||
self.becomeFirstResponder()
|
||||
|
||||
UIMenuController.shared.menuItems = [
|
||||
UIMenuItem(
|
||||
title: editMenuLabel,
|
||||
action: #selector(dismissVerifiedMenu)
|
||||
)
|
||||
]
|
||||
UIMenuController.shared.showMenu(from: checkmark, rect: checkmark.bounds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UIMenuController boilerplate
|
||||
@available(iOS, deprecated: 16, message: "Can be removed when target version is >=16 -- boilerplate to maintain compatibility with UIMenuController")
|
||||
extension ProfileFieldCollectionViewCell {
|
||||
override var canBecomeFirstResponder: Bool { true }
|
||||
|
||||
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
|
||||
if action == #selector(dismissVerifiedMenu) {
|
||||
return true
|
||||
}
|
||||
|
||||
return super.canPerformAction(action, withSender: sender)
|
||||
}
|
||||
|
||||
@objc public func dismissVerifiedMenu() {
|
||||
UIMenuController.shared.hideMenu()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MetaLabelDelegate
|
||||
|
@ -112,3 +149,16 @@ extension ProfileFieldCollectionViewCell: MetaLabelDelegate {
|
|||
delegate?.profileFieldCollectionViewCell(self, metaLebel: metaLabel, didSelectMeta: meta)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: UIEditMenuInteractionDelegate
|
||||
@available(iOS 16.0, *)
|
||||
extension ProfileFieldCollectionViewCell: UIEditMenuInteractionDelegate {
|
||||
func editMenuInteraction(_ interaction: UIEditMenuInteraction, menuFor configuration: UIEditMenuConfiguration, suggestedActions: [UIMenuElement]) -> UIMenu? {
|
||||
guard let editMenuLabel = checkmarkPopoverString else { return UIMenu(children: []) }
|
||||
return UIMenu(children: [UIAction(title: editMenuLabel) { _ in return }])
|
||||
}
|
||||
|
||||
func editMenuInteraction(_ interaction: UIEditMenuInteraction, targetRectFor configuration: UIEditMenuConfiguration) -> CGRect {
|
||||
return checkmark.frame
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import MastodonCore
|
|||
|
||||
protocol ProfileAboutViewControllerDelegate: AnyObject {
|
||||
func profileAboutViewController(_ viewController: ProfileAboutViewController, profileFieldCollectionViewCell: ProfileFieldCollectionViewCell, metaLabel: MetaLabel, didSelectMeta meta: Meta)
|
||||
func profileAboutViewController(_ viewController: ProfileAboutViewController, didTapCheckmarkFor field: ProfileFieldItem.FieldValue)
|
||||
}
|
||||
|
||||
final class ProfileAboutViewController: UIViewController {
|
||||
|
@ -153,21 +152,6 @@ extension ProfileAboutViewController: ProfileFieldCollectionViewCellDelegate {
|
|||
func profileFieldCollectionViewCell(_ cell: ProfileFieldCollectionViewCell, metaLebel: MetaLabel, didSelectMeta meta: Meta) {
|
||||
delegate?.profileAboutViewController(self, profileFieldCollectionViewCell: cell, metaLabel: metaLebel, didSelectMeta: meta)
|
||||
}
|
||||
|
||||
func profileFieldCollectionViewCell(_ cell: ProfileFieldCollectionViewCell, didTapAction action: ProfileFieldCollectionViewCellAction) {
|
||||
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||
guard let indexPath = collectionView.indexPath(for: cell) else { return }
|
||||
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
|
||||
|
||||
switch item {
|
||||
case .field(let field):
|
||||
delegate?.profileAboutViewController(self, didTapCheckmarkFor: field)
|
||||
case .addEntry: fallthrough
|
||||
case .editField: fallthrough
|
||||
case .noResult:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ProfileFieldEditCollectionViewCellDelegate
|
||||
|
|
|
@ -854,22 +854,6 @@ extension ProfileViewController: ProfileAboutViewControllerDelegate {
|
|||
) {
|
||||
handleMetaPress(meta)
|
||||
}
|
||||
|
||||
func profileAboutViewController(_ viewController: ProfileAboutViewController, didTapCheckmarkFor field: ProfileFieldItem.FieldValue) {
|
||||
guard let verifiedAt = field.verifiedAt.value else {
|
||||
return
|
||||
}
|
||||
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .short
|
||||
let alert = UIAlertController(title: L10n.Common.Alerts.Verified.title, message: L10n.Common.Alerts.Verified.message(formatter.string(from: verifiedAt)), preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default) { _ in
|
||||
alert.dismiss(animated: true)
|
||||
})
|
||||
|
||||
self.present(alert, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MastodonMenuDelegate
|
||||
|
|
|
@ -87,14 +87,6 @@ public enum L10n {
|
|||
/// Sign Up Failure
|
||||
public static let title = L10n.tr("Localizable", "Common.Alerts.SignUpFailure.Title")
|
||||
}
|
||||
public enum Verified {
|
||||
/// Ownership of this link was checked on %s
|
||||
public static func message(_ p1: UnsafePointer<CChar>) -> String {
|
||||
return L10n.tr("Localizable", "Common.Alerts.Verified.Message", p1)
|
||||
}
|
||||
/// Verified
|
||||
public static let title = L10n.tr("Localizable", "Common.Alerts.Verified.Title")
|
||||
}
|
||||
public enum VoteFailure {
|
||||
/// The poll has ended
|
||||
public static let pollEnded = L10n.tr("Localizable", "Common.Alerts.VoteFailure.PollEnded")
|
||||
|
@ -721,6 +713,16 @@ public enum L10n {
|
|||
/// Label
|
||||
public static let label = L10n.tr("Localizable", "Scene.Profile.Fields.Placeholder.Label")
|
||||
}
|
||||
public enum Verified {
|
||||
/// Ownership of this link was checked on %s
|
||||
public static func long(_ p1: UnsafePointer<CChar>) -> String {
|
||||
return L10n.tr("Localizable", "Scene.Profile.Fields.Verified.Long", p1)
|
||||
}
|
||||
/// Verified at %s
|
||||
public static func short(_ p1: UnsafePointer<CChar>) -> String {
|
||||
return L10n.tr("Localizable", "Scene.Profile.Fields.Verified.Short", p1)
|
||||
}
|
||||
}
|
||||
}
|
||||
public enum Header {
|
||||
/// Follows You
|
||||
|
|
|
@ -22,8 +22,6 @@ Please check your internet connection.";
|
|||
"Common.Alerts.SignOut.Message" = "Are you sure you want to sign out?";
|
||||
"Common.Alerts.SignOut.Title" = "Sign Out";
|
||||
"Common.Alerts.SignUpFailure.Title" = "Sign Up Failure";
|
||||
"Common.Alerts.Verified.Title" = "Verified";
|
||||
"Common.Alerts.Verified.Message" = "Ownership of this link was checked on %s";
|
||||
"Common.Alerts.VoteFailure.PollEnded" = "The poll has ended";
|
||||
"Common.Alerts.VoteFailure.Title" = "Vote Failure";
|
||||
"Common.Controls.Actions.Add" = "Add";
|
||||
|
@ -259,6 +257,8 @@ uploaded to Mastodon.";
|
|||
"Scene.Profile.Fields.AddRow" = "Add Row";
|
||||
"Scene.Profile.Fields.Placeholder.Content" = "Content";
|
||||
"Scene.Profile.Fields.Placeholder.Label" = "Label";
|
||||
"Scene.Profile.Fields.Verified.Short" = "Verified at %s";
|
||||
"Scene.Profile.Fields.Verified.Long" = "Ownership of this link was checked on %s";
|
||||
"Scene.Profile.Header.FollowsYou" = "Follows You";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@";
|
||||
"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account";
|
||||
|
|
Loading…
Reference in New Issue