command picker for drawing toolkit
This commit is contained in:
@@ -95,7 +95,7 @@ import Foundation
|
||||
|| gamepad.leftThumbstick.yAxis.value != 0)
|
||||
if navigationActionTriggeredPrivate { navigationActionTriggered = true}
|
||||
else {
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + 0.02) {
|
||||
DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) {
|
||||
if !navigationActionTriggeredPrivate {
|
||||
navigationActionTriggered = false
|
||||
}
|
||||
|
||||
@@ -836,6 +836,7 @@ import ObjectiveC.runtime
|
||||
]
|
||||
)
|
||||
label.attributedText = attr
|
||||
label.textAlignment = .center
|
||||
}
|
||||
|
||||
private func setupView() {
|
||||
|
||||
@@ -416,12 +416,34 @@ import UIKit
|
||||
doubleTapShorcuts[i] = shortcut
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
func widgetPickerViewController(_ controller: WidgetPickerViewController, didCreateWidget payload: NSDictionary) {
|
||||
let params = payload.mutableCopy() as? NSMutableDictionary ?? NSMutableDictionary()
|
||||
let pickerAction = ((params["pickerAction"] as? String) ?? "").lowercased()
|
||||
params.removeObject(forKey: "pickerAction")
|
||||
|
||||
if pickerAction == "create" {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@objc static public func enterDoubleTapShortcuts(in viewController: UIViewController){
|
||||
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||
selectedProfile = oscProfileMan.getSelectedProfile()
|
||||
guard let selectedProfile = selectedProfile else {return}
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
let pickerViewController = WidgetPickerViewController()
|
||||
pickerViewController.delegate = (viewController as! any WidgetPickerViewControllerDelegate)
|
||||
pickerViewController.keyboardPickerMode = .shortcutPicker
|
||||
pickerViewController.tabIdentifiers = ["keyboard"]
|
||||
pickerViewController.initialTabIdentifier = "keyboard"
|
||||
pickerViewController.shortcutIdentifier = "eraser"
|
||||
pickerViewController.shortcutPickerTipText = SwiftLocalizationHelper.localizedString(forKey: "Select eraser shortcut keys")
|
||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
||||
nav.modalPresentationStyle = .overFullScreen
|
||||
viewController.present(nav, animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
let alert = UIAlertController(title: SwiftLocalizationHelper.localizedString(forKey: "Eraser Shortcut"),
|
||||
message: SwiftLocalizationHelper.localizedString(forKey: "Enter eraser keyboard shortcut:"),
|
||||
preferredStyle: .alert)
|
||||
@@ -455,10 +477,24 @@ import UIKit
|
||||
viewController.present(alert, animated: true, completion: {
|
||||
})
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
@objc static public func enterBrushShortcut(in viewController: UIViewController){
|
||||
|
||||
let pickerViewController = WidgetPickerViewController()
|
||||
pickerViewController.delegate = (viewController as! any WidgetPickerViewControllerDelegate)
|
||||
pickerViewController.keyboardPickerMode = .shortcutPicker
|
||||
pickerViewController.tabIdentifiers = ["keyboard"]
|
||||
pickerViewController.initialTabIdentifier = "keyboard"
|
||||
pickerViewController.shortcutIdentifier = "brush"
|
||||
pickerViewController.shortcutPickerTipText = SwiftLocalizationHelper.localizedString(forKey: "Select brush shortcut keys")
|
||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
||||
nav.modalPresentationStyle = .overFullScreen
|
||||
viewController.present(nav, animated: true)
|
||||
return
|
||||
|
||||
/*
|
||||
let alert = UIAlertController(title: SwiftLocalizationHelper.localizedString(forKey: "Brush Shortcut"),
|
||||
message: SwiftLocalizationHelper.localizedString(forKey: "Enter brush keyboard shortcut:"),
|
||||
preferredStyle: .alert)
|
||||
@@ -500,13 +536,28 @@ import UIKit
|
||||
viewController.present(alert, animated: true, completion: {
|
||||
|
||||
})
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@objc static private(set) var squeezeStartShortcut:String = ""
|
||||
@objc static private(set) var squeezeEndShortcut:String = ""
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
@objc static public func enterSqueezeShortcuts(in viewController: UIViewController){
|
||||
|
||||
let pickerViewController = WidgetPickerViewController()
|
||||
pickerViewController.delegate = (viewController as! any WidgetPickerViewControllerDelegate)
|
||||
pickerViewController.keyboardPickerMode = .shortcutPicker
|
||||
pickerViewController.tabIdentifiers = ["keyboard"]
|
||||
pickerViewController.initialTabIdentifier = "keyboard"
|
||||
pickerViewController.shortcutIdentifier = "squeezePress"
|
||||
pickerViewController.shortcutPickerTipText = SwiftLocalizationHelper.localizedString(forKey: "squeezePressShortcutPickerTip")
|
||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
||||
nav.modalPresentationStyle = .overFullScreen
|
||||
viewController.present(nav, animated: true)
|
||||
return
|
||||
|
||||
/*
|
||||
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||
selectedProfile = oscProfileMan.getSelectedProfile()
|
||||
guard let selectedProfile = selectedProfile else {return}
|
||||
@@ -543,10 +594,24 @@ import UIKit
|
||||
|
||||
viewController.present(alert, animated: true, completion: {
|
||||
})
|
||||
*/
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
@objc static public func enterSqueezeEndShortcut(in viewController: UIViewController){
|
||||
|
||||
let pickerViewController = WidgetPickerViewController()
|
||||
pickerViewController.delegate = (viewController as! any WidgetPickerViewControllerDelegate)
|
||||
pickerViewController.keyboardPickerMode = .shortcutPicker
|
||||
pickerViewController.tabIdentifiers = ["keyboard"]
|
||||
pickerViewController.initialTabIdentifier = "keyboard"
|
||||
pickerViewController.shortcutIdentifier = "squeezeRelease"
|
||||
pickerViewController.shortcutPickerTipText = SwiftLocalizationHelper.localizedString(forKey: "squeezeReleaseShortcutPickerTip")
|
||||
let nav = UINavigationController(rootViewController: pickerViewController)
|
||||
nav.modalPresentationStyle = .overFullScreen
|
||||
viewController.present(nav, animated: true)
|
||||
return
|
||||
|
||||
/*
|
||||
let alert = UIAlertController(title: SwiftLocalizationHelper.localizedString(forKey: "Squeeze Shortcut"),
|
||||
message: SwiftLocalizationHelper.localizedString(forKey: "enterSqueezeReleaseShort"),
|
||||
preferredStyle: .alert)
|
||||
@@ -588,6 +653,7 @@ import UIKit
|
||||
viewController.present(alert, animated: true, completion: {
|
||||
|
||||
})
|
||||
*/
|
||||
}
|
||||
|
||||
private func attachHoverLeave(normalizedLocation:CGPoint){
|
||||
|
||||
@@ -2988,6 +2988,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Create shortcut" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "生成快捷键"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "生成快速鍵"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "生成快速鍵"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Create widget" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -4192,35 +4215,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"enterSqueezePressShort" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Enter shortcut on squeeze Press:"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "输入捏笔时发送的快捷键:"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "輸入捏筆時傳送的快速鍵:"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "輸入捏筆時傳送的快速鍵:"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enterSqueezeReleaseShort" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -9997,6 +9991,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Select brush shortcut keys" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "选择笔刷快捷键组合"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇筆刷快速鍵組合"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇筆刷快速鍵組合"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Select Control" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -10020,6 +10037,29 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Select eraser shortcut keys" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "选择橡皮擦快捷键组合"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇橡皮擦快速鍵組合"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇橡皮擦快速鍵組合"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Select Gyro Button" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -10700,6 +10740,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"squeezePressShortcutPickerTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Select shortcut keys on squeeze press"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "选择捏笔按压时发送的快捷键组合"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇捏筆按壓時發送的快捷鍵組合"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇捏筆按壓時發送的快捷鍵組合"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"squeezeReleaseShortcutPickerTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Select shortcut keys on squeeze release. To keep the previously selected keys pressed while squeezing, select “Null” on top right"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "选择捏笔松开时的快捷键组合, 若要在捏笔时保持之前选择的组合键按下, 选右上方”Null”"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇捏筆鬆開時的快速鍵組合,若要在捏筆時保持之前選擇的組合鍵按下,選右上方「Null」"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選擇捏筆鬆開時的快速鍵組合,若要在捏筆時保持之前選擇的組合鍵按下,選右上方「Null」"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"squeezeShortcutStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
|
||||
@class LayoutOnScreenControlsViewController;
|
||||
@class MicHandler;
|
||||
@protocol MicHandlerDelegate;
|
||||
@class WidgetPickerViewController;
|
||||
@protocol WidgetPickerViewControllerDelegate;
|
||||
|
||||
@interface SettingsViewController : UIViewController <RearNavigationBarMenuDelegate, MenuSectionDelegate, MicHandlerDelegate, UITextFieldDelegate>
|
||||
@interface SettingsViewController : UIViewController <RearNavigationBarMenuDelegate, MenuSectionDelegate, UITextFieldDelegate, WidgetPickerViewControllerDelegate>
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UINavigationBar *navigationBar;
|
||||
@property (strong, nonatomic) UIStackView *parentStack;
|
||||
|
||||
@@ -3614,6 +3614,33 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)widgetPickerViewController:(WidgetPickerViewController *)controller didCreateWidget:(NSDictionary *)payload API_AVAILABLE(ios(13.0)){
|
||||
OSCProfilesManager * profileMan = [OSCProfilesManager sharedManager:CGRectZero];
|
||||
OSCProfile* profile = [profileMan getSelectedProfile];
|
||||
NSString* shortcutIdentifier = [payload objectForKey:@"shortcutIdentifier"];
|
||||
|
||||
if([shortcutIdentifier isEqualToString:@"eraser"]) {
|
||||
profile.eraserShortcut = [payload objectForKey:@"cmdString"];
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.8 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
[PencilHandler enterBrushShortcutIn:self];
|
||||
});
|
||||
}
|
||||
if([shortcutIdentifier isEqualToString:@"brush"]) {
|
||||
profile.brushShortcut = [payload objectForKey:@"cmdString"];
|
||||
}
|
||||
if([shortcutIdentifier isEqualToString:@"squeezePress"]) {
|
||||
profile.squeezeStartShortcut = [payload objectForKey:@"cmdString"];
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.8 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
[PencilHandler enterSqueezeEndShortcutIn:self];
|
||||
});
|
||||
}
|
||||
if([shortcutIdentifier isEqualToString:@"squeezeRelease"]) {
|
||||
profile.squeezeEndShortcut = [payload objectForKey:@"cmdString"];
|
||||
}
|
||||
|
||||
[profileMan replaceSelectedProfileWith:profile overwriteDefault:true];
|
||||
}
|
||||
|
||||
/*
|
||||
- (void)autoHoverSwitchFlipped:(UISwitch* )sender{
|
||||
if(sender.isOn && !settingsViewJustLoaded){
|
||||
|
||||
@@ -59,9 +59,10 @@ enum KeyHighlightStyle {
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
enum VirtualKeyboardMode {
|
||||
public enum VirtualKeyboardMode {
|
||||
case picker
|
||||
case typing
|
||||
case shortcutPicker
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
@@ -179,12 +180,12 @@ struct VirtualKeyboardView: View {
|
||||
self.selectionSyncToken = selectionSyncToken
|
||||
self.externalDeselectionCommand = externalDeselectionCommand
|
||||
self.externalDeselectionToken = externalDeselectionToken
|
||||
_showsMouseWidgets = SwiftUI.State(initialValue: mode == .picker)
|
||||
_showsMouseWidgets = SwiftUI.State(initialValue: mode != .typing)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if mode == .picker {
|
||||
if usesPickerLayout {
|
||||
GeometryReader { proxy in
|
||||
let isPhone = UIDevice.current.userInterfaceIdiom == .phone
|
||||
let horizontalInset: CGFloat = isPhone ? 6 : 12
|
||||
@@ -298,7 +299,7 @@ struct VirtualKeyboardView: View {
|
||||
height: keyHeight,
|
||||
keyboardType: keyboardType,
|
||||
mode: mode,
|
||||
usesDirectionPadBaseStyle: mode == .picker,
|
||||
usesDirectionPadBaseStyle: usesDirectionPadBaseStyle,
|
||||
isActive:
|
||||
(key.role == .fn && fnMode)
|
||||
|| (key.role == .keyboardSwitch && keyboardType == .mac),
|
||||
@@ -325,7 +326,7 @@ struct VirtualKeyboardView: View {
|
||||
height: height ?? keyHeight,
|
||||
keyboardType: keyboardType,
|
||||
mode: mode,
|
||||
usesDirectionPadBaseStyle: mode == .picker,
|
||||
usesDirectionPadBaseStyle: usesDirectionPadBaseStyle,
|
||||
isActive: isActive,
|
||||
highlightStyle: highlightStyle(for: key),
|
||||
action: {
|
||||
@@ -345,9 +346,9 @@ struct VirtualKeyboardView: View {
|
||||
case .keyboardSwitch:
|
||||
keyboardType = keyboardType == .win ? .mac : .win
|
||||
case .normal:
|
||||
if mode == .picker, let family = selectionFamily(for: key) {
|
||||
if usesPickerSelectionBehavior, let family = selectionFamily(for: key) {
|
||||
handleDirectionKeyTap(key, family: family)
|
||||
} else if mode == .picker || isTypingToggleKey(key) {
|
||||
} else if usesPickerSelectionBehavior || isTypingToggleKey(key) {
|
||||
toggleRegularKeyHighlight(key)
|
||||
}
|
||||
}
|
||||
@@ -399,7 +400,9 @@ struct VirtualKeyboardView: View {
|
||||
if VirtualKeyboardView.selectedCmd == padCommand(for: family) {
|
||||
VirtualKeyboardView.selectedCmd = ""
|
||||
}
|
||||
return
|
||||
if mode != .shortcutPicker {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if directionSingleKeyLabels.contains(key.label) {
|
||||
@@ -413,6 +416,29 @@ struct VirtualKeyboardView: View {
|
||||
return
|
||||
}
|
||||
|
||||
if mode == .shortcutPicker {
|
||||
let command = key.cmdString(for: keyboardType) ?? key.label
|
||||
if canSelectCommand?(command) == false {
|
||||
return
|
||||
}
|
||||
let option = KeyboardWidgetOption(
|
||||
command: command,
|
||||
description: singleKeyDescription(for: key, family: family),
|
||||
highlightedLabels: [key.label],
|
||||
family: family,
|
||||
selectionState: .single(key.label)
|
||||
)
|
||||
applySelection(option)
|
||||
VirtualKeyboardView.tappedKeyLabels = [key.label]
|
||||
VirtualKeyboardView.selectedCmd = command
|
||||
VirtualKeyboardView.lastSelectionDisplayText = poolDisplayText(for: option)
|
||||
VirtualKeyboardView.lastSelectionUsesMacLayout = keyboardType == .mac
|
||||
VirtualKeyboardView.lastSelectionFromMouseWidgets = false
|
||||
VirtualKeyboardView.lastSelectionUsesFnCommandDisplay = false
|
||||
onCommandSelected?(command)
|
||||
return
|
||||
}
|
||||
|
||||
pendingSelectionFamily = family
|
||||
pendingKeyboardOptions = keyboardOptions(for: key, family: family)
|
||||
VirtualKeyboardView.tappedKeyLabels = [key.label]
|
||||
@@ -590,12 +616,12 @@ struct VirtualKeyboardView: View {
|
||||
}
|
||||
|
||||
private func highlightStyle(for key: Key) -> KeyHighlightStyle {
|
||||
if mode == .picker, let family = selectionFamily(for: key), padSelections.contains(family) {
|
||||
if usesPadSelectionHighlight, let family = selectionFamily(for: key), padSelections.contains(family) {
|
||||
return .pad
|
||||
}
|
||||
|
||||
if highlightedKeyIDs.contains(regularHighlightID(for: key))
|
||||
|| (mode == .picker && directionSingleKeyLabels.contains(key.label)) {
|
||||
|| (usesPickerSelectionBehavior && directionSingleKeyLabels.contains(key.label)) {
|
||||
return isPadLikeControl(key) ? .pad : .single
|
||||
}
|
||||
|
||||
@@ -770,7 +796,7 @@ struct VirtualKeyboardView: View {
|
||||
// MARK: - 小键盘 / 鼠标控件区
|
||||
var numpadBlock: some View {
|
||||
VStack(spacing: spacing) {
|
||||
if mode == .picker {
|
||||
if usesPickerLayout {
|
||||
HStack(spacing: spacing) {
|
||||
KeyView(
|
||||
key: Key(
|
||||
@@ -813,7 +839,7 @@ struct VirtualKeyboardView: View {
|
||||
}
|
||||
}
|
||||
|
||||
if mode == .picker {
|
||||
if usesPickerLayout {
|
||||
if showsMouseWidgets {
|
||||
mouseWidgetsBlock
|
||||
} else {
|
||||
@@ -980,65 +1006,93 @@ struct VirtualKeyboardView: View {
|
||||
)
|
||||
}
|
||||
|
||||
HStack(spacing: spacing) {
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Wheel\nUp"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELDOWN",
|
||||
macCmdString: "WHEELDOWN",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
if mode == .shortcutPicker {
|
||||
HStack(spacing: spacing) {
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Wheel\nUp"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELDOWN",
|
||||
macCmdString: "WHEELDOWN",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Wheel\nDown"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELUP",
|
||||
macCmdString: "WHEELUP",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Wheel\nDown"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELUP",
|
||||
macCmdString: "WHEELUP",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
HStack(spacing: spacing) {
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Wheel\nUp"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELDOWN",
|
||||
macCmdString: "WHEELDOWN",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "WheelPad"),
|
||||
width: unit * 2 + spacing,
|
||||
winCmdString: "WHEEL",
|
||||
macCmdString: "WHEEL",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Wheel\nDown"),
|
||||
width: unit,
|
||||
winCmdString: "WHEELUP",
|
||||
macCmdString: "WHEELUP",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "WheelPad"),
|
||||
width: unit * 2 + spacing,
|
||||
winCmdString: "WHEEL",
|
||||
macCmdString: "WHEEL",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
HStack(spacing: spacing) {
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "MousePad"),
|
||||
width: unit * 2 + spacing,
|
||||
winCmdString: "MOUSEPAD",
|
||||
macCmdString: "MOUSEPAD",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
),
|
||||
height: keyHeight * 2 + spacing
|
||||
)
|
||||
if mode != .shortcutPicker {
|
||||
HStack(spacing: spacing) {
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "MousePad"),
|
||||
width: unit * 2 + spacing,
|
||||
winCmdString: "MOUSEPAD",
|
||||
macCmdString: "MOUSEPAD",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
),
|
||||
height: keyHeight * 2 + spacing
|
||||
)
|
||||
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Trackball"),
|
||||
width: unit * 2 + spacing,
|
||||
winCmdString: "TRACKBALL",
|
||||
macCmdString: "TRACKBALL",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
),
|
||||
height: keyHeight * 2 + spacing
|
||||
)
|
||||
keyboardKeyView(
|
||||
Key(
|
||||
label: SwiftLocalizationHelper.localizedString(forKey: "Trackball"),
|
||||
width: unit * 2 + spacing,
|
||||
winCmdString: "TRACKBALL",
|
||||
macCmdString: "TRACKBALL",
|
||||
winKeyCode: 0xFF,
|
||||
macKeyCode: 0xFF
|
||||
),
|
||||
height: keyHeight * 2 + spacing
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1210,7 +1264,7 @@ struct VirtualKeyboardView: View {
|
||||
}
|
||||
|
||||
private var mouseWidgetKeys: [Key] {
|
||||
[
|
||||
var keys = [
|
||||
Key(label: SwiftLocalizationHelper.localizedString(forKey: "Left Button"), width: unit * 2 + spacing, winCmdString: "MLEFT", macCmdString: "MLEFT", winKeyCode: 0xFF, macKeyCode: 0xFF),
|
||||
Key(label: SwiftLocalizationHelper.localizedString(forKey: "Right Button"), width: unit * 2 + spacing, winCmdString: "MRIGHT", macCmdString: "MRIGHT", winKeyCode: 0xFF, macKeyCode: 0xFF),
|
||||
Key(label: SwiftLocalizationHelper.localizedString(forKey: "Middle Button"), width: unit * 2 + spacing, winCmdString: "MMIDDLE", macCmdString: "MMIDDLE", winKeyCode: 0xFF, macKeyCode: 0xFF),
|
||||
@@ -1222,6 +1276,29 @@ struct VirtualKeyboardView: View {
|
||||
Key(label: SwiftLocalizationHelper.localizedString(forKey: "MousePad"), width: unit * 2 + spacing, winCmdString: "MOUSEPAD", macCmdString: "MOUSEPAD", winKeyCode: 0xFF, macKeyCode: 0xFF),
|
||||
Key(label: SwiftLocalizationHelper.localizedString(forKey: "Trackball"), width: unit * 2 + spacing, winCmdString: "TRACKBALL", macCmdString: "TRACKBALL", winKeyCode: 0xFF, macKeyCode: 0xFF)
|
||||
]
|
||||
if mode == .shortcutPicker {
|
||||
keys.removeAll { key in
|
||||
let command = key.cmdString(for: keyboardType) ?? ""
|
||||
return command == "WHEEL" || command == "MOUSEPAD" || command == "TRACKBALL"
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
private var usesPickerLayout: Bool {
|
||||
mode != .typing
|
||||
}
|
||||
|
||||
private var usesPickerSelectionBehavior: Bool {
|
||||
mode == .picker || mode == .shortcutPicker
|
||||
}
|
||||
|
||||
private var usesPadSelectionHighlight: Bool {
|
||||
mode == .picker
|
||||
}
|
||||
|
||||
private var usesDirectionPadBaseStyle: Bool {
|
||||
mode == .picker
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1528,6 +1605,10 @@ struct VirtualKeyboardView_Previews: PreviewProvider {
|
||||
VirtualKeyboardView(mode: .picker)
|
||||
.frame(height: 320)
|
||||
.previewDisplayName("Picker")
|
||||
|
||||
VirtualKeyboardView(mode: .shortcutPicker)
|
||||
.frame(height: 320)
|
||||
.previewDisplayName("Shortcut Picker")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +283,9 @@ struct WidgetPickerView: View {
|
||||
private let initialShape: String?
|
||||
private let availableTabs: [WidgetPickerTab]
|
||||
private let preferredInitialTab: WidgetPickerTab?
|
||||
private let keyboardPickerMode: VirtualKeyboardMode
|
||||
private let shortcutPickerTipText: String?
|
||||
private let shortcutIdentifier: String?
|
||||
var onWidgetCreated: (([String: String]) -> Void)? = nil
|
||||
var onCloseRequested: (() -> Void)? = nil
|
||||
|
||||
@@ -291,7 +294,7 @@ struct WidgetPickerView: View {
|
||||
@SwiftUI.State private var selectedCmds: [String] = []
|
||||
@SwiftUI.State private var poolItems: [WidgetPoolItem] = []
|
||||
@SwiftUI.State private var resetToken: Int = 0
|
||||
@SwiftUI.State private var tipMessage: String = SwiftLocalizationHelper.localizedString(forKey: "Tap any control to add it")
|
||||
@SwiftUI.State private var tipMessage: String
|
||||
@SwiftUI.State private var tipMessageType: PoolTipMessageType = .normal
|
||||
@SwiftUI.State private var keyboardDeselectionCommand: String = ""
|
||||
@SwiftUI.State private var keyboardDeselectionToken: Int = 0
|
||||
@@ -316,6 +319,9 @@ struct WidgetPickerView: View {
|
||||
initialShape: String? = nil,
|
||||
availableTabs: [WidgetPickerTab] = WidgetPickerTab.allCases,
|
||||
preferredInitialTab: WidgetPickerTab? = nil,
|
||||
keyboardPickerMode: VirtualKeyboardMode = .picker,
|
||||
shortcutPickerTipText: String? = nil,
|
||||
shortcutIdentififier: String? = nil,
|
||||
onWidgetCreated: (([String: String]) -> Void)? = nil,
|
||||
onCloseRequested: (() -> Void)? = nil
|
||||
) {
|
||||
@@ -327,9 +333,17 @@ struct WidgetPickerView: View {
|
||||
self.initialShape = initialShape
|
||||
self.availableTabs = normalizedTabs
|
||||
self.preferredInitialTab = resolvedInitialTab
|
||||
self.keyboardPickerMode = keyboardPickerMode
|
||||
self.shortcutPickerTipText = shortcutPickerTipText
|
||||
self.shortcutIdentifier = shortcutIdentififier
|
||||
self.onWidgetCreated = onWidgetCreated
|
||||
self.onCloseRequested = onCloseRequested
|
||||
_selectedTab = SwiftUI.State(initialValue: resolvedInitialTab ?? (normalizedTabs.contains(.keyboard) ? .keyboard : normalizedTabs[0]))
|
||||
_tipMessage = SwiftUI.State(
|
||||
initialValue: (keyboardPickerMode == .shortcutPicker && !(shortcutPickerTipText ?? "").isEmpty)
|
||||
? (shortcutPickerTipText ?? "")
|
||||
: SwiftLocalizationHelper.localizedString(forKey: "Tap any control to add it")
|
||||
)
|
||||
}
|
||||
|
||||
private let functionalButtonOptions: [FunctionalButtonOption] = [
|
||||
@@ -487,7 +501,10 @@ struct WidgetPickerView: View {
|
||||
]
|
||||
|
||||
private var defaultTipMessage: String {
|
||||
SwiftLocalizationHelper.localizedString(forKey: "Tap any control to add it")
|
||||
if isShortcutPickerMode, let shortcutPickerTipText, !shortcutPickerTipText.isEmpty {
|
||||
return shortcutPickerTipText
|
||||
}
|
||||
return SwiftLocalizationHelper.localizedString(forKey: "Tap any control to add it")
|
||||
}
|
||||
|
||||
private var tipMessageColor: Color {
|
||||
@@ -500,6 +517,11 @@ struct WidgetPickerView: View {
|
||||
}
|
||||
|
||||
private func setTipMessage(_ message: String, type: PoolTipMessageType = .normal) {
|
||||
if isShortcutPickerMode, let shortcutPickerTipText, !shortcutPickerTipText.isEmpty {
|
||||
tipMessage = shortcutPickerTipText
|
||||
tipMessageType = .normal
|
||||
return
|
||||
}
|
||||
tipMessage = message
|
||||
tipMessageType = type
|
||||
}
|
||||
@@ -678,7 +700,7 @@ struct WidgetPickerView: View {
|
||||
.padding(.vertical, pickerInsetGamepadVertical)
|
||||
case .keyboard:
|
||||
VirtualKeyboardView(
|
||||
mode: .picker,
|
||||
mode: keyboardPickerMode,
|
||||
canSelectCommand: { canSelectCommand($0, source: .keyboard) },
|
||||
isCommandSelected: { selectedCmds.contains($0) },
|
||||
onCommandSelected: { appendCommand($0, source: .keyboard) },
|
||||
@@ -852,44 +874,48 @@ struct WidgetPickerView: View {
|
||||
.frame(maxWidth: poolGridWidth ?? .infinity, alignment: .center)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
|
||||
if keyboardPickerMode != .shortcutPicker {
|
||||
PoolActionChip(
|
||||
title: SwiftLocalizationHelper.localizedString(forKey: "Gyro switch button"),
|
||||
isPrimary: false,
|
||||
height: poolChipHeight,
|
||||
fontSize: poolChipFontSize,
|
||||
cornerRadius: metrics.chipCornerRadius
|
||||
) {
|
||||
handleGyroButtonTap()
|
||||
}
|
||||
.overlay(
|
||||
Group {
|
||||
if selectedGyroCommand != nil {
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.stroke(Color.orange.opacity(0.75), lineWidth: 1.4)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 1.00, green: 0.96, blue: 0.74).opacity(0.34),
|
||||
Color(red: 0.95, green: 0.78, blue: 0.32).opacity(0.22)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
title: SwiftLocalizationHelper.localizedString(forKey: "Gyro switch button"),
|
||||
isPrimary: false,
|
||||
height: poolChipHeight,
|
||||
fontSize: poolChipFontSize,
|
||||
cornerRadius: metrics.chipCornerRadius
|
||||
) {
|
||||
handleGyroButtonTap()
|
||||
}
|
||||
)
|
||||
.overlay(
|
||||
Group {
|
||||
if selectedGyroCommand != nil {
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.stroke(Color.orange.opacity(0.75), lineWidth: 1.4)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(
|
||||
LinearGradient(
|
||||
gradient: Gradient(colors: [
|
||||
Color(red: 1.00, green: 0.96, blue: 0.74).opacity(0.34),
|
||||
Color(red: 0.95, green: 0.78, blue: 0.32).opacity(0.22)
|
||||
]),
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottomTrailing
|
||||
)
|
||||
)
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
HStack(spacing: metrics.isPhone ? 8 : 12) {
|
||||
PoolActionChip(
|
||||
title: isEditMode
|
||||
? WidgetPickerSubmissionAction.create.poolActionTitle
|
||||
: SwiftLocalizationHelper.localizedString(forKey: "Create widget"),
|
||||
title: isShortcutPickerMode
|
||||
? SwiftLocalizationHelper.localizedString(forKey: "Create shortcut")
|
||||
: (isEditMode
|
||||
? WidgetPickerSubmissionAction.create.poolActionTitle
|
||||
: SwiftLocalizationHelper.localizedString(forKey: "Create widget")),
|
||||
isPrimary: true,
|
||||
height: poolChipHeight,
|
||||
fontSize: poolChipFontSize,
|
||||
@@ -1662,7 +1688,15 @@ struct WidgetPickerView: View {
|
||||
return "{\n \"cmdString\": \"\(payload["cmdString"] ?? "")\",\n \"buttonLabel\": \"\(payload["buttonLabel"] ?? "")\",\n \"shape\": \"\(payload["shape"] ?? "")\"\n}"
|
||||
}
|
||||
|
||||
private var isShortcutPickerMode: Bool {
|
||||
keyboardPickerMode == .shortcutPicker
|
||||
}
|
||||
|
||||
private var shouldBypassCreateWidgetSheet: Bool {
|
||||
if isShortcutPickerMode {
|
||||
return true
|
||||
}
|
||||
|
||||
guard !poolItems.isEmpty else { return false }
|
||||
|
||||
let hasVisibleConfigurationSection =
|
||||
@@ -1724,7 +1758,7 @@ struct WidgetPickerView: View {
|
||||
}
|
||||
|
||||
private func presentCreateWidgetSheet(for submissionAction: WidgetPickerSubmissionAction) {
|
||||
guard !poolItems.isEmpty else {
|
||||
guard isShortcutPickerMode || !poolItems.isEmpty else {
|
||||
setTipMessage(SwiftLocalizationHelper.localizedString(forKey: "Select at least one command before creating a widget"), type: .error)
|
||||
return
|
||||
}
|
||||
@@ -1740,7 +1774,7 @@ struct WidgetPickerView: View {
|
||||
}
|
||||
|
||||
private func submitWidgetPayload() {
|
||||
let payload = makeWidgetPayload()
|
||||
var payload = makeWidgetPayload()
|
||||
lastCreatedWidgetPayload = payload
|
||||
setTipMessage(SwiftLocalizationHelper.localizedString(forKey: "Widget config generated"))
|
||||
onWidgetCreated?(payload)
|
||||
@@ -1753,11 +1787,16 @@ struct WidgetPickerView: View {
|
||||
"cmdString": buildCmdString(),
|
||||
"buttonLabel": targetWidgetKind == .button ? widgetButtonLabel : "",
|
||||
"shape": targetWidgetKind == .button ? widgetShape.rawValue : "",
|
||||
"pickerAction": pendingSubmissionAction.payloadValue
|
||||
"pickerAction": pendingSubmissionAction.payloadValue,
|
||||
"shortcutIdentifier": shortcutIdentifier ?? ""
|
||||
]
|
||||
}
|
||||
|
||||
private func buildCmdString() -> String {
|
||||
if isShortcutPickerMode {
|
||||
return selectedCmds.joined(separator: "+")
|
||||
}
|
||||
|
||||
let joiner = effectiveWidgetComboMode == .shortcut && showsComboModeControl ? "+" : "-"
|
||||
var cmdString = selectedCmds.joined(separator: joiner)
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ public final class WidgetPickerViewController: UIViewController {
|
||||
public var initialShape: String?
|
||||
public var tabIdentifiers: [String] = []
|
||||
public var initialTabIdentifier: String?
|
||||
public var keyboardPickerMode: VirtualKeyboardMode = .picker
|
||||
public var shortcutPickerTipText: String?
|
||||
@objc public var shortcutIdentifier: String?
|
||||
|
||||
private var hostingViewController: UIHostingController<WidgetPickerView>?
|
||||
|
||||
@@ -32,6 +35,9 @@ public final class WidgetPickerViewController: UIViewController {
|
||||
initialShape: initialShape,
|
||||
availableTabs: resolvedTabs(),
|
||||
preferredInitialTab: resolvedInitialTab(),
|
||||
keyboardPickerMode: keyboardPickerMode,
|
||||
shortcutPickerTipText: shortcutPickerTipText,
|
||||
shortcutIdentififier: shortcutIdentifier,
|
||||
onWidgetCreated: { [weak self] payload in
|
||||
guard let self else { return }
|
||||
self.delegate?.widgetPickerViewController(self, didCreateWidget: payload as NSDictionary)
|
||||
|
||||
Reference in New Issue
Block a user