Files
Termind/TFI/Platform/MobileHistoryMenuConfiguration.swift

63 lines
2.4 KiB
Swift

// SPDX-FileCopyrightText: 2026 Kaede Akino
// SPDX-License-Identifier: GPL-3.0-only
import UIKit
/// Configure native History menus after SwiftUI has supplied their commands and images.
@MainActor
enum MobileHistoryMenuConfiguration {
private static let recordImageIdentifier = "termind.history.connection"
static func recordImage(systemName: String) -> UIImage {
let image = (UIImage(systemName: systemName) ?? UIImage()).withRenderingMode(.alwaysTemplate)
image.accessibilityIdentifier = recordImageIdentifier
return image
}
static func apply(to builder: any UIMenuBuilder) {
guard #available(iOS 27.0, *), builder.system === UIMenuSystem.main,
let root = builder.menu(for: .root)
else { return }
for menu in root.children.compactMap({ $0 as? UIMenu }) where containsHistoryShortcut(menu) {
builder.replace(menu: menu.identifier, with: configured(menu))
}
}
// Identify the command independently of the app language and SwiftUI-generated menu identifiers.
private static func containsHistoryShortcut(_ menu: UIMenu) -> Bool {
menu.children.contains { element in
if isShowHistory(element) { return true }
return (element as? UIMenu).map(containsHistoryShortcut) ?? false
}
}
private static func isShowHistory(_ element: UIMenuElement) -> Bool {
guard let command = element as? UIKeyCommand else { return false }
return command.input?.lowercased() == "y" && command.modifierFlags == .command
}
private static func configured(_ menu: UIMenu) -> UIMenu {
guard #available(iOS 27.0, *) else { return menu }
let children = menu.children.map { element -> UIMenuElement in
if let submenu = element as? UIMenu {
return configured(submenu)
}
if element.image != nil,
isShowHistory(element) || isConnectionRecord(element)
{
element.preferredImageVisibility = .visible
}
return element
}
let result = menu.replacingChildren(children)
if isConnectionRecord(result) {
result.preferredImageVisibility = .visible
}
return result
}
private static func isConnectionRecord(_ element: UIMenuElement) -> Bool {
element.image?.accessibilityIdentifier == recordImageIdentifier
}
}