mastodon-app-ufficiale-ipho.../MastodonSDK/Sources/MastodonUI/View/Menu/MastodonMenu.swift

240 lines
8.8 KiB
Swift

//
// MastodonMenu.swift
//
//
// Created by MainasuK on 2022-1-26.
//
import UIKit
import MastodonLocalization
public protocol MastodonMenuDelegate: AnyObject {
func menuAction(_ action: MastodonMenu.Action)
}
public enum MastodonMenu {
public static func setupMenu(
actions: [[Action]],
delegate: MastodonMenuDelegate
) -> UIMenu {
var children: [UIMenuElement] = []
for actionGroup in actions {
var submenuChildren: [UIMenuElement] = []
for action in actionGroup {
let element = action.build(delegate: delegate).menuElement
submenuChildren.append(element)
}
let submenu = UIMenu(options: .displayInline, children: submenuChildren)
children.append(submenu)
}
return UIMenu(children: children)
}
public static func setupAccessibilityActions(
actions: [[Action]],
delegate: MastodonMenuDelegate
) -> [UIAccessibilityCustomAction] {
var accessibilityActions: [UIAccessibilityCustomAction] = []
for action in actions.flatMap({ $0 }) {
let element = action.build(delegate: delegate)
accessibilityActions.append(element.accessibilityCustomAction)
}
return accessibilityActions
}
}
extension MastodonMenu {
public enum Action {
case translateStatus(TranslateStatusActionContext)
case muteUser(MuteUserActionContext)
case blockUser(BlockUserActionContext)
case reportUser(ReportUserActionContext)
case shareUser(ShareUserActionContext)
case bookmarkStatus(BookmarkStatusActionContext)
case hideReblogs(HideReblogsActionContext)
case shareStatus
case deleteStatus
case editStatus
func build(delegate: MastodonMenuDelegate) -> LabeledAction {
switch self {
case .hideReblogs(let context):
let title = context.showReblogs ? L10n.Common.Controls.Friendship.hideReblogs : L10n.Common.Controls.Friendship.showReblogs
let reblogAction = LabeledAction(title: title, image: UIImage(systemName: "arrow.2.squarepath")) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return reblogAction
case .muteUser(let context):
let title: String
let image: UIImage?
if context.isMuting {
title = L10n.Common.Controls.Friendship.unmuteUser(context.name)
image = UIImage(systemName: "speaker.wave.2")
} else {
title = L10n.Common.Controls.Friendship.muteUser(context.name)
image = UIImage(systemName: "speaker.slash")
}
let muteAction = LabeledAction(title: title, image: image) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return muteAction
case .blockUser(let context):
let title: String
let image: UIImage?
if context.isBlocking {
title = L10n.Common.Controls.Friendship.unblockUser(context.name)
image = UIImage(systemName: "hand.raised.slash")
} else {
title = L10n.Common.Controls.Friendship.blockUser(context.name)
image = UIImage(systemName: "hand.raised")
}
let blockAction = LabeledAction(title: title, image: image) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return blockAction
case .reportUser(let context):
let reportAction = LabeledAction(
title: L10n.Common.Controls.Actions.reportUser(context.name),
image: UIImage(systemName: "flag")
) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return reportAction
case .shareUser(let context):
let shareAction = LabeledAction(
title: L10n.Common.Controls.Actions.shareUser(context.name),
image: UIImage(systemName: "square.and.arrow.up")
) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return shareAction
case .bookmarkStatus(let context):
let title: String
let image: UIImage?
if context.isBookmarking {
title = L10n.Common.Controls.Actions.removeBookmark
image = UIImage(systemName: "bookmark.slash.fill")
} else {
title = L10n.Common.Controls.Actions.bookmark
image = UIImage(systemName: "bookmark")
}
let action = LabeledAction(title: title, image: image) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return action
case .shareStatus:
let action = LabeledAction(
title: L10n.Common.Controls.Actions.sharePost,
image: UIImage(systemName: "square.and.arrow.up")
) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return action
case .deleteStatus:
let deleteAction = LabeledAction(
title: L10n.Common.Controls.Actions.delete,
image: UIImage(systemName: "minus.circle"),
attributes: .destructive
) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return deleteAction
case let .translateStatus(context):
let language = Locale.current.localizedString(forIdentifier: context.language) ?? L10n.Common.Controls.Actions.TranslatePost.unknownLanguage
let translateAction = LabeledAction(
title: L10n.Common.Controls.Actions.TranslatePost.title(language),
image: UIImage(systemName: "character.book.closed")
) { [weak delegate] in
guard let delegate = delegate else { return }
delegate.menuAction(self)
}
return translateAction
case .editStatus:
let editStatusAction = LabeledAction(
title: L10n.Common.Controls.Actions.editPost,
image: UIImage(systemName: "pencil")
) {
[weak delegate] in
guard let delegate else { return }
delegate.menuAction(self)
}
return editStatusAction
} // end switch
} // end func build
} // end enum Action
}
extension MastodonMenu {
public struct MuteUserActionContext {
public let name: String
public let isMuting: Bool
public init(name: String, isMuting: Bool) {
self.name = name
self.isMuting = isMuting
}
}
public struct BlockUserActionContext {
public let name: String
public let isBlocking: Bool
public init(name: String, isBlocking: Bool) {
self.name = name
self.isBlocking = isBlocking
}
}
public struct BookmarkStatusActionContext {
public let isBookmarking: Bool
public init(isBookmarking: Bool) {
self.isBookmarking = isBookmarking
}
}
public struct ReportUserActionContext {
public let name: String
public init(name: String) {
self.name = name
}
}
public struct ShareUserActionContext {
public let name: String
public init(name: String) {
self.name = name
}
}
public struct HideReblogsActionContext {
public let showReblogs: Bool
public init(showReblogs: Bool) {
self.showReblogs = showReblogs
}
}
public struct TranslateStatusActionContext {
public let language: String
public init(language: String) {
self.language = language
}
}
}