diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard
index 2d94ccce..ac316243 100644
--- a/VoidLink/Base.lproj/iPad.storyboard
+++ b/VoidLink/Base.lproj/iPad.storyboard
@@ -1359,6 +1359,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1400,7 +1420,6 @@
-
@@ -1450,6 +1469,8 @@
+
+
@@ -2024,8 +2045,8 @@
-
-
+
+
@@ -2195,6 +2216,7 @@
+
@@ -2207,7 +2229,7 @@
-
+
@@ -2216,13 +2238,13 @@
-
+
-
+
-
+
diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard
index af94c953..aa5aa306 100644
--- a/VoidLink/Base.lproj/iPhone.storyboard
+++ b/VoidLink/Base.lproj/iPhone.storyboard
@@ -621,8 +621,8 @@
-
-
+
+
@@ -1703,6 +1703,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2019,7 +2039,7 @@
-
+
@@ -2039,7 +2059,7 @@
-
+
@@ -2061,7 +2081,7 @@
-
+
@@ -2181,6 +2201,8 @@
+
+
@@ -2223,6 +2245,7 @@
+
@@ -2234,19 +2257,19 @@
-
+
-
+
-
+
-
+
diff --git a/VoidLink/Database/DataManager.h b/VoidLink/Database/DataManager.h
index 792b9eef..d0ee1291 100644
--- a/VoidLink/Database/DataManager.h
+++ b/VoidLink/Database/DataManager.h
@@ -110,6 +110,7 @@ typedef NS_ENUM(NSInteger, WidgetSizeTransition) {
framePacingMode:(NSInteger)framePacingMode
sendDummyEvent:(BOOL)sendDummyEvent
rememberFoldState:(BOOL)rememberFoldState
+ singleTapSensitivy:(CGFloat)singleTapSensitivy
backgroundSessionTimer:(NSInteger)backgroundSessionTimer;
- (NSArray*) getHosts;
diff --git a/VoidLink/Database/DataManager.m b/VoidLink/Database/DataManager.m
index efd68206..461a1ab7 100644
--- a/VoidLink/Database/DataManager.m
+++ b/VoidLink/Database/DataManager.m
@@ -105,6 +105,7 @@
framePacingMode:(NSInteger)framePacingMode
sendDummyEvent:(BOOL)sendDummyEvent
rememberFoldState:(BOOL)rememberFoldState
+ singleTapSensitivy:(CGFloat)singleTapSensitivy
backgroundSessionTimer:(NSInteger)backgroundSessionTimer{
[_managedObjectContext performBlockAndWait:^{
@@ -160,6 +161,7 @@
settingsToSave.renderingBackend = [NSNumber numberWithInteger:renderingBackend];
settingsToSave.framePacingMode = [NSNumber numberWithInteger:framePacingMode];
settingsToSave.sendDummyEvent = sendDummyEvent;
+ settingsToSave.singleTapSensitivity = [NSNumber numberWithDouble:singleTapSensitivy];
settingsToSave.rememberFoldState = rememberFoldState;
[self saveData];
}];
diff --git a/VoidLink/Database/TemporarySettings.h b/VoidLink/Database/TemporarySettings.h
index 15f36b8a..7fedcfc7 100644
--- a/VoidLink/Database/TemporarySettings.h
+++ b/VoidLink/Database/TemporarySettings.h
@@ -78,6 +78,7 @@
@property (nonatomic, retain) NSNumber * renderingBackend;
@property (nonatomic) BOOL sendDummyEvent;
@property (nonatomic) BOOL rememberFoldState;
+@property (nonatomic, retain) NSNumber * singleTapSensitivity;
@property (nonatomic, retain) NSNumber * framePacingMode;
- (id) initFromSettings:(Settings*)settings;
diff --git a/VoidLink/Database/TemporarySettings.m b/VoidLink/Database/TemporarySettings.m
index ffe11d4a..a0218eb7 100644
--- a/VoidLink/Database/TemporarySettings.m
+++ b/VoidLink/Database/TemporarySettings.m
@@ -133,6 +133,7 @@
self.gyroBiasX = settings.gyroBiasX;
self.gyroBiasY = settings.gyroBiasY;
self.gyroBiasZ = settings.gyroBiasZ;
+ self.singleTapSensitivity = settings.singleTapSensitivity;
self.backgroundSessionTimer = settings.backroundSessionTimer;
#endif
self.uniqueId = settings.uniqueId;
diff --git a/VoidLink/Input/CommandManager.swift b/VoidLink/Input/CommandManager.swift
index 14384f87..76bdcf6b 100644
--- a/VoidLink/Input/CommandManager.swift
+++ b/VoidLink/Input/CommandManager.swift
@@ -115,11 +115,14 @@ import UIKit
"OSCBACK"
]
- @objc public static let touchPadCmds: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD", "DS4TOUCH", "MOUSEPAD", "MOUSEWHEEL", "WHEEL", "DPAD", "TRACKBALL", "WASDPAD", "ARROWPAD"]
+ @objc public static let touchPadCmds: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD","LTPAD", "RTPAD", "DS4TOUCH", "MOUSEPAD", "MOUSEWHEEL", "WHEEL", "DPAD", "TRACKBALL", "WASDPAD", "ARROWPAD"]
@objc public static let directionPads: [String] = ["DPAD", "WASDPAD", "ARROWPAD"]
@objc public static let stickTouchPads: [String] = ["LSVPAD", "RSVPAD", "LSPAD", "RSPAD"]
@objc public static let nonVectorStickPads: [String] = ["LSPAD", "RSPAD"]
- @objc public static let functionalButtonCmds: [String] = ["SETTINGS","GYRO","ACCEL","MOTION"]
+ @objc public static let verticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL"]
+ @objc public static let bidirectionalVerticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL"]
+ @objc public static let functionalButtonCmds: [String] = ["SETTINGS"]
+ @objc public static let motionControlButtonCmds: [String] = ["GYRO","ACCEL","MOTION"]
// @objc public static let specialGameWidgets: [String] = ["YSRSV", "YSLT", "YSRT", "YSRB", "YSB", "YSRT2", "YSRB2", "YSB2", "YSEM", "YSML", "YSMR", "YSWASD"]
@@ -464,6 +467,7 @@ import UIKit
CommandManager.oscButtonMappings.keys.map { $0 as String },
CommandManager.mouseButtonMappings.keys.map { $0 as String },
CommandManager.functionalButtonCmds.map { $0 as String },
+ CommandManager.motionControlButtonCmds.map { $0 as String },
CommandManager.touchPadCmds.map { $0 as String }
]
.lazy
diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift
index 4a1d067b..e84e6bc2 100644
--- a/VoidLink/Input/OnScreenWidgetView.swift
+++ b/VoidLink/Input/OnScreenWidgetView.swift
@@ -63,6 +63,7 @@ import UIKit
@objc public var identifier: String = ""
private var buttonString: String = ""
private var functionalButtonString: String = ""
+ private var motionControlButtonString: String = ""
private var touchPadString: String = ""
// super combo key string set
@objc public var comboButtonStrings: [String] = []
@@ -104,8 +105,18 @@ import UIKit
// for all touchPad or buttons hybrid with touchPads
@objc public var hasStickIndicator: Bool = false
- @objc public var hasSensitivityTweak: Bool = false
-
+ @objc public var hasSensitivityX: Bool = false
+ @objc public var sensitivityXMin: CGFloat = 0
+ @objc public var sensitivityXMAX: CGFloat = 8
+ @objc public var hasSensitivityY: Bool = false
+ @objc public var sensitivityYMin: CGFloat = 0
+ @objc public var sensitivityYMAX: CGFloat = 8
+ @objc public var hasAutoTap: Bool = false
+ @objc public var isMousePad: Bool = false
+ @objc public var hasTrackBall: Bool = false
+ @objc public var isFuncationalButton: Bool = false
+ @objc public var hasHapticFeedback: Bool = false
+
// for all stick pads
@objc public var minStickOffset: CGFloat = 0
public let stickMaxOffset: CGFloat = 0x7FFE
@@ -200,7 +211,7 @@ import UIKit
@objc init(cmdString: String, buttonLabel: String, shape:String) {
-
+
self.cmdString = cmdString
self.touchPadString = ""
@@ -223,19 +234,13 @@ import UIKit
else {self.widgetType = WidgetTypeEnum.button}
let touchPadString = Set(comboStrings).intersection(Set(CommandManager.touchPadCmds)).first ?? ""
+
self.comboButtonStrings = comboStrings.filter{$0 != touchPadString}
self.touchPadString = touchPadString
self.buttonString = self.comboButtonStrings.first ?? ""
self.functionalButtonString = Set(self.comboButtonStrings).intersection(Set(CommandManager.functionalButtonCmds)).first ?? ""
-
- // let stickAndMouseTouchpads = ["LSPAD", "RSPAD", "LSVPAD", "RSVPAD", "MOUSEPAD"]
- let nonVectorStickPads = ["LSPAD", "RSPAD"]
- // if CommandManager.touchPadCmds.contains(self.touchPadString) {self.hasSensitivityTweak = true}
- self.hasSensitivityTweak = CommandManager.touchPadCmds.contains(self.touchPadString)
-
- // if nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad {self.hasStickIndicator = true}
- self.hasStickIndicator = nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad
-
+ self.motionControlButtonString = Set(self.comboButtonStrings).intersection(Set(CommandManager.motionControlButtonCmds)).first ?? ""
+
switch self.cmdString {
case "LSPAD", "LSVPAD":
self.comboButtonStrings = ["OSCL3"]
@@ -251,8 +256,7 @@ import UIKit
else {
self.widgetType = WidgetTypeEnum.button // legacy combo button connected by "+"
}
-
-
+
print("widgetType: \(self.widgetType)")
print("touchPadString: \(self.touchPadString)")
for comboButtonString in comboButtonStrings {
@@ -296,6 +300,9 @@ import UIKit
self.oscProfile = oscProfileMan.getSelectedProfile()
super.init(frame: .zero)
+ // helps widget panel to hide/show stacks
+ self.accessWidgetAttributes()
+
upIndicator = createLrudDirectionLayer()
upIndicator.anchorPoint = CGPoint(x: 0.5, y: 1)
downIndicator = createLrudDirectionLayer()
@@ -310,12 +317,11 @@ import UIKit
self.mouseButtonAction = MouseButtonAction.noClick
self.buttonMode = ButtonMode.regular.rawValue
}
+ if !self.motionControlButtonString.isEmpty {
+ self.buttonMode = ButtonMode.tapToToggle.rawValue
+ }
if !self.functionalButtonString.isEmpty {
self.buttonMode = ButtonMode.movable.rawValue
- if (self.functionalButtonString == "GYRO" ||
- self.functionalButtonString == "ACCEL" ||
- self.functionalButtonString == "MOTION")
- {self.buttonMode = ButtonMode.tapToToggle.rawValue}
}
}
@@ -327,6 +333,20 @@ import UIKit
fatalError("init(coder:) has not been implemented")
}
+ @objc public func accessWidgetAttributes(){
+ self.hasStickIndicator = CommandManager.nonVectorStickPads.contains(self.touchPadString) && widgetType == WidgetTypeEnum.touchPad
+ self.hasSensitivityX = CommandManager.touchPadCmds.contains(self.touchPadString) && !CommandManager.verticalTouchPads.contains(self.touchPadString)
+ self.hasSensitivityY = CommandManager.touchPadCmds.contains(self.touchPadString)
+ if CommandManager.bidirectionalVerticalTouchPads.contains(self.touchPadString){
+ self.sensitivityYMin = -4
+ self.sensitivityYMAX = 4
+ }
+ self.hasAutoTap = self.widgetType == WidgetTypeEnum.button && self.functionalButtonString != ""
+ self.isMousePad = self.touchPadString == "MOUSEPAD" && widgetType == WidgetTypeEnum.touchPad
+ self.hasTrackBall = self.touchPadString == "TRACKBALL"
+ self.isFuncationalButton = self.functionalButtonString != ""
+ self.hasHapticFeedback = !self.comboButtonStrings.isEmpty
+ }
// ======================================================================================================
@objc public func setupAutoTapTimer() {
@@ -1095,8 +1115,8 @@ import UIKit
private func handleButtonDown() {
if !OnScreenWidgetView.editMode {self.sendComboButtonsDownEvent(comboStrings: self.comboButtonStrings)}
- if !OnScreenWidgetView.editMode, !self.functionalButtonString.isEmpty {self.handleFunctionalButtonDown()}
-
+ if !OnScreenWidgetView.editMode, !self.motionControlButtonString.isEmpty {self.handleMotionControlButtonDown()}
+
// sadflkasdfl;
if OnScreenWidgetView.buttonVisualFeedbackEnabled {
@@ -1118,6 +1138,10 @@ import UIKit
private func handleButtonUp() {
if !OnScreenWidgetView.editMode {self.sendComboButtonsUpEvent(comboStrings: self.comboButtonStrings)}
+ if !OnScreenWidgetView.editMode && !self.motionControlButtonString.isEmpty{
+ self.handleMotionControlButtonUp()
+ }
+
if !OnScreenWidgetView.editMode && !self.functionalButtonString.isEmpty{
self.handleFunctionalButtonUp()
}
@@ -1171,7 +1195,7 @@ import UIKit
//==========================================================================================================
- //=========================================send on screen controller stick events
+ //=========================================send on screen controller stick/trigger events
private func touchInputToStickInput(input: CGFloat) -> CGFloat{
let target = stickMaxOffset * input / stickInputScale
return fmax(fmin(target, stickMaxOffset),-stickMaxOffset)
@@ -1216,6 +1240,15 @@ import UIKit
}
self.mixInputDelegate?.mixLeftStickAndGyroInput(x: targetX, y: targetY)
}
+
+ private func sendLeftTriggerTouchPadEvent(inputY: CGFloat){
+ self.onScreenControls.updateLeftTrigger(UInt8(max(min(inputY,255),0)))
+ }
+
+ private func sendRightTriggerTouchPadEvent(inputY: CGFloat){
+ self.onScreenControls.updateRightTrigger(UInt8(max(min(inputY,255),0)))
+ }
+
//==========================================================================================================
private func sendOscButtonDownEvent(oscString: String){
@@ -1627,6 +1660,17 @@ import UIKit
self.updateTouchLocation(touch: touches.first!)
self.sendRightStickTouchPadEvent(inputX: self.deltaX*1.5167*self.sensitivityFactorX, inputY: self.deltaY*1.5167*self.sensitivityFactorY)
}
+ case "LTPAD":
+ DispatchQueue.global(qos: .userInteractive).async {
+ self.updateTouchLocation(touch: touches.first!)
+ self.sendLeftTriggerTouchPadEvent(inputY: (-self.offSetY*4.5*self.sensitivityFactorY))
+ }
+ case "RTPAD":
+ DispatchQueue.global(qos: .userInteractive).async {
+ self.updateTouchLocation(touch: touches.first!)
+ self.sendRightTriggerTouchPadEvent(inputY: (-self.offSetY*4.5*self.sensitivityFactorY))
+ }
+ break
case "DPAD", "WASDPAD", "ARROWPAD":
self.updateTouchLocation(touch: touches.first!)
handleLrudTouchMove()
@@ -1642,8 +1686,8 @@ import UIKit
}
}
- private func handleFunctionalButtonDown(){
- switch self.functionalButtonString {
+ private func handleMotionControlButtonDown(){
+ switch self.motionControlButtonString {
case "GYRO":
self.functionalButtonDelegate?.startGyroUpdate()
case "ACCEL":
@@ -1656,12 +1700,9 @@ import UIKit
}
}
- private func handleFunctionalButtonUp(){
+ private func handleMotionControlButtonUp(){
let longPressed = CACurrentMediaTime() - self.touchTapTimeStamp > 0.3
- switch self.functionalButtonString {
- case "SETTINGS":
- if longPressed, buttonMode == ButtonMode.movable.rawValue {break}
- NotificationCenter.default.post(name: Notification.Name("SettingsOverlayButtonPressedNotification"), object:nil) // inform layout tool controller to fetch button size factors. self will be passed as the object of the notification
+ switch self.motionControlButtonString {
case "GYRO":
self.functionalButtonDelegate?.stopGyroUpdate(interruption: false)
case "ACCEL":
@@ -1674,6 +1715,18 @@ import UIKit
}
}
+ private func handleFunctionalButtonUp(){
+ let longPressed = CACurrentMediaTime() - self.touchTapTimeStamp > 0.3
+ switch self.functionalButtonString {
+ case "SETTINGS":
+ if longPressed, buttonMode == ButtonMode.movable.rawValue {break}
+ NotificationCenter.default.post(name: Notification.Name("SettingsOverlayButtonPressedNotification"), object:nil) // inform layout tool controller to fetch button size factors. self will be passed as the object of the notification
+ default:
+ break
+ }
+ }
+
+
private func clearRightStickTouchPadFlag(){
let mixRightStickInputToGyro = (oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick
&& oscProfile.yawPitchToRightStick)
@@ -1764,6 +1817,10 @@ import UIKit
self.clearLeftStickTouchPadFlag()
case "RSVPAD":
self.clearRightStickTouchPadFlag()
+ case "LTPAD":
+ self.onScreenControls.updateLeftTrigger(0x00)
+ case "RTPAD":
+ self.onScreenControls.updateRightTrigger(0x00)
case "WASDPAD":
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["W"]!,Int8(KEY_ACTION_UP), 0)
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings["A"]!,Int8(KEY_ACTION_UP), 0)
diff --git a/VoidLink/Input/RelativeTouchHandler.m b/VoidLink/Input/RelativeTouchHandler.m
index 275b29e4..4a6f2585 100644
--- a/VoidLink/Input/RelativeTouchHandler.m
+++ b/VoidLink/Input/RelativeTouchHandler.m
@@ -33,6 +33,8 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
UITouch* touchLockedForMouseMove;
+ CADisplayLink *displayLink;
+
#if TARGET_OS_TV
UIGestureRecognizer* remotePressRecognizer;
UIGestureRecognizer* remoteLongPressRecognizer;
@@ -65,6 +67,9 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
screenWidthWithThreshold = CGRectGetWidth([[UIScreen mainScreen] bounds]) - EDGE_TOLERANCE;
self->touchPointSpawnedAtUpperScreenEdge = false;
+ // self->displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkCallback:)];
+ // [self->displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+
#if TARGET_OS_TV
remotePressRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(remoteButtonPressed:)];
remotePressRecognizer.allowedPressTypes = @[@(UIPressTypeSelect)];
@@ -132,8 +137,13 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
return hypotf(originalPoint.x - currentPoint.x, originalPoint.y - currentPoint.y) <= 300;
}
+- (BOOL)isAdjacentPoints:(CGPoint)currentPoint from:(CGPoint)originalPoint {
+ bool isAdjacent = hypotf(originalPoint.x - currentPoint.x, originalPoint.y - currentPoint.y) <= hypot(currentSettings.singleTapSensitivity.doubleValue, currentSettings.singleTapSensitivity.doubleValue);
+ return isAdjacent;
+}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ firstTouchMoved = false;
//check if touch point is spawned on the left or right upper half screen edges, this is the highest priority
CGPoint initialPoint = [[touches anyObject] locationInView:streamView];
@@ -142,7 +152,6 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
return;
}
- firstTouchMoved = false;
touchPointSpawnedAtUpperScreenEdge = false; // reset this flag immediately if we get a touch event passing the check above, this fixes irresponsive touch after closing the command tool menu.
if([[event allTouches] count] == 2 && ![self isOnScreenWidgetViewBeingPressed] && ![self isOnScreenControllerBeingPressed:[event allTouches]]){
@@ -206,7 +215,9 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
// NSLog(@"%f touchesMoved callback, locked touch: %llu", CACurrentMediaTime(), (uintptr_t)touchLockedForMouseMove);
if([touches containsObject:touchLockedForMouseMove]){
- mousePointerMoved = true;
+ if(!mousePointerMoved && ![self isAdjacentPoints:initialMousePointerLocation from:[touchLockedForMouseMove locationInView:streamView]]){
+ mousePointerMoved = true;
+ }
[self sendMouseMoveEvent:touchLockedForMouseMove];
}
}
@@ -242,10 +253,18 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
touchPointSpawnedAtUpperScreenEdge = false;
}
+- (void)displayLinkCallback:(CADisplayLink *)link {
+ dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
+ if(self->touchLockedForMouseMove && !self->mousePointerMoved){
+ CGPoint testpoint = [self->touchLockedForMouseMove locationInView:self->streamView];
+ NSLog(@"displayLinkCallback %f: %f, %f", CACurrentMediaTime(), testpoint.x, testpoint.y);
+ //[self sendMouseMoveEvent:touchLockedForMouseMove];
+ }
+ });
+}
- (void)sendMouseMoveEvent:(UITouch* )touch{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
- if(self->touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC.
CGPoint currentLocation = [touch locationInView:self->streamView];
@@ -261,8 +280,9 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
int deltaY = (currentLocation.y - self->latestMousePointerLocation.y) * 1.35 * self->currentSettings.mousePointerVelocityFactor.floatValue;
if (deltaX != 0 || deltaY != 0) {
- LiSendMouseMoveEvent(deltaX, deltaY);
self->latestMousePointerLocation = currentLocation;
+ if(self->touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC.
+ LiSendMouseMoveEvent(deltaX, deltaY);
}
}
});
diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
index a156178f..1d9dce47 100644
--- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
+++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
@@ -66,6 +66,7 @@
+
diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings
index 7fed9c97..39e1fb1b 100644
--- a/VoidLink/Localization/Localizable.xcstrings
+++ b/VoidLink/Localization/Localizable.xcstrings
@@ -162,25 +162,48 @@
}
}
},
- " Profile: %@ Widget: %@" : {
+ " Profile: %@ Alias: %@ Command: %@" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
- "value" : " 当前布局: %@ 当前组件: %@"
+ "value" : " 当前布局: %@ 别名: %@ 命令: %@"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
- "value" : " 版面配置:%@ 小工具:%@"
+ "value" : " 版面配置: %@ 别名: %@ 命令: %@"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
- "value" : " 版面配置:%@ 小工具:%@"
+ "value" : " 版面配置: %@ 别名: %@ 命令: %@"
+ }
+ }
+ }
+ },
+ " Profile: %@ Widget: %@" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : " 当前布局: %@ 控件: %@"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : " 版面配置: %@ 小工具: %@"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : " 版面配置: %@ 小工具: %@"
}
}
}
diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
index 1609a629..eb0f67e8 100644
--- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
+++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
@@ -612,7 +612,8 @@
bool noValidTouchPadString = ![CommandManager.touchPadCmds containsObject:cmdString];
bool noValidOscButtonString = ![CommandManager.oscButtonMappings.allKeys containsObject:cmdString];
bool noValidFunctionalButtonString = ![CommandManager.functionalButtonCmds containsObject:cmdString];
- bool paramInvalid = noValidKeyboardString && noValidMouseButtonString && noValidTouchPadString && noValidOscButtonString && noValidFunctionalButtonString && noValidSuperComboButtonString;
+ bool noValidMotionControlButtonString = ![CommandManager.motionControlButtonCmds containsObject:cmdString];
+ bool paramInvalid = noValidKeyboardString && noValidMouseButtonString && noValidTouchPadString && noValidOscButtonString && noValidFunctionalButtonString && noValidSuperComboButtonString && noValidMotionControlButtonString;
if([buttonLabel isEqualToString:@""]) widgetInitParams[@"buttonLabel"] = [[cmdString lowercaseString] capitalizedString];
@@ -761,51 +762,37 @@
[self autoFitLabel:self.currentProfileLabel];
self.currentProfileLabel.textAlignment = NSTextAlignmentLeft;
[self.currentProfileLabel setText:
- [LocalizationHelper localizedStringForKey:@" Profile: %@ Widget: %@",
+ [LocalizationHelper localizedStringForKey:@" Profile: %@ Alias: %@ Command: %@",
[profilesManager getSelectedProfile].name,
- selectedWidgetView.widgetLabel]];
+ selectedWidgetView.widgetLabel, selectedWidgetView.cmdString]];
self.undoButton.alpha = selectedWidgetView.layoutChanges.count>1 ? 1.0 : 0.3;
[self.layoutOSC updateGuidelinesForOnScreenWidget:self->selectedWidgetView]; // shows guideline immediately when widget is tapped
-
-
- // hide irrelevant stacks
- self.autoTapStack.hidden = selectedWidgetView.widgetType != WidgetTypeEnumButton;
- self.buttonModeStack.hidden = selectedWidgetView.widgetType != WidgetTypeEnumButton;
-
- bool showSensitivityFactorStack = selectedWidgetView.hasSensitivityTweak;
- bool showStickIndicatorOffsetStack = selectedWidgetView.hasStickIndicator;
- self.sensitivityXStack.hidden = !showSensitivityFactorStack || [selectedWidgetView.cmdString containsString:@"MOUSEWHEEL"] || [selectedWidgetView.cmdString containsString:@"WHEEL"];
- self.sensitivityYStack.hidden = !showSensitivityFactorStack;
- if(showSensitivityFactorStack){
- if([selectedWidgetView.cmdString containsString:@"MOUSEWHEEL"] || [selectedWidgetView.cmdString containsString:@"WHEEL"]){
- [self.sensitivityYSlider setMinimumValue:-4];
- [self.sensitivityYSlider setMaximumValue:4];
- }
- else{
- [self.sensitivityYSlider setMinimumValue:0];
- [self.sensitivityYSlider setMaximumValue:8];
- }
- }
+ // stack & values
+ [selectedWidgetView accessWidgetAttributes];
- self.stickIndicatorOffsetStack.hidden = !showStickIndicatorOffsetStack;
- self.mouseDownButtonStack.hidden = !([selectedWidgetView.cmdString containsString:@"MOUSEPAD"] && selectedWidgetView.widgetType == WidgetTypeEnumTouchPad);
- self.decelerationRateStack.hidden = !([selectedWidgetView.cmdString containsString:@"TRACKBALL"] && selectedWidgetView.widgetType == WidgetTypeEnumTouchPad);
-
- // setup values
-
-
- if(showSensitivityFactorStack){
+ self.sensitivityXStack.hidden = !selectedWidgetView.hasSensitivityX;
+ if(selectedWidgetView.hasSensitivityX){
+ [self.sensitivityXSlider setMinimumValue:selectedWidgetView.sensitivityXMin];
+ [self.sensitivityXSlider setMaximumValue:selectedWidgetView.sensitivityXMAX];
[self.sensitivityXSlider setValue:self->selectedWidgetView.sensitivityFactorX];
[self autoFitLabel:self.sensitivityXLabel];
+ }
+
+ self.sensitivityYStack.hidden = !selectedWidgetView.hasSensitivityY;
+ if(selectedWidgetView.hasSensitivityY){
+ [self.sensitivityYSlider setMinimumValue:selectedWidgetView.sensitivityYMin];
+ [self.sensitivityYSlider setMaximumValue:selectedWidgetView.sensitivityYMAX];
[self.sensitivityXLabel setText:[LocalizationHelper localizedStringForKey:@"SensitivityX: %.2f", self->selectedWidgetView.sensitivityFactorX]];
[self autoFitLabel:self.sensitivityYLabel];
[self.sensitivityYSlider setValue:self->selectedWidgetView.sensitivityFactorY];
[self.sensitivityYLabel setText:[LocalizationHelper localizedStringForKey:@"SensitivityY: %.2f", self->selectedWidgetView.sensitivityFactorY]];
}
- if(showStickIndicatorOffsetStack){
+
+ self.stickIndicatorOffsetStack.hidden = !selectedWidgetView.hasStickIndicator;
+ if(selectedWidgetView.hasStickIndicator){
// illustrating the indicator offset,
[self hideStickIndicators];
selectedWidgetView.touchBeganLocation = CGPointMake(CGRectGetWidth(selectedWidgetView.frame)/2, CGRectGetHeight(selectedWidgetView.frame)/4);
@@ -833,30 +820,28 @@
[self autoFitLabel:self.widgetBorderWidthLabel];
[self widgetBorderWidthSliderMoved:self.widgetBorderWidthSlider];
+ self.autoTapStack.hidden = !selectedWidgetView.hasAutoTap;
[self.autoTapSlider setValue:self->selectedWidgetView.autoTapInterval];
[self autoFitLabel:self.autoTapLabel];
[self autoTapSliderMoved:self.autoTapSlider];
+ self.decelerationRateStack.hidden = !selectedWidgetView.hasTrackBall;
[self.decelerationRateSlider setValue:selectedWidgetView.trackballDecelerationRate];
[self autoFitLabel:self.decelerationRateLabel];
[self decelerationRateSliderMoved:self.decelerationRateSlider];
+ self.mouseDownButtonStack.hidden = !selectedWidgetView.isMousePad;
self.mouseButtonDownSelector.selectedSegmentIndex = selectedWidgetView.mouseButtonAction;
- NSSet *specialCmds = [NSSet setWithArray:CommandManager.functionalButtonCmds];
- NSSet *comboButtonStrings = [NSSet setWithArray:widgetView.comboButtonStrings];
- bool isFuncationalButton = [specialCmds intersectsSet:comboButtonStrings];
- [self.buttonModeSelector setEnabled:!isFuncationalButton forSegmentAtIndex:0];
- [self.buttonModeSelector setEnabled:!isFuncationalButton forSegmentAtIndex:1];
- if(isFuncationalButton) [self.autoTapStack setHidden:YES];
+ self.buttonModeStack.hidden = selectedWidgetView.widgetType != WidgetTypeEnumButton;
+ [self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:0];
+ [self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:1];
[self.buttonModeSelector setSelectedSegmentIndex:selectedWidgetView.buttonMode];
[self autoFitStack:self.widgetPanelStack];
if([self isIPhone]){
- self.vibrationStyleStack.hidden =
- [widgetView.cmdString containsString:@"MOUSEPAD"] ||
- [widgetView.cmdString containsString:@"TRACKBALL"];
+ self.vibrationStyleStack.hidden = !selectedWidgetView.hasHapticFeedback;
[self autoFitStack:self.widgetPanelStack];
self.vibrationStyleSelector.selectedSegmentIndex = self->selectedWidgetView.vibrationStyle;
}
@@ -884,7 +869,7 @@
[self autoFitLabel:self.currentProfileLabel];
self.currentProfileLabel.textAlignment = NSTextAlignmentLeft;
[self.currentProfileLabel setText:
- [LocalizationHelper localizedStringForKey:@" Profile: %@ Widget: %@",
+ [LocalizationHelper localizedStringForKey:@" Profile: %@ Widget: %@",
[profilesManager getSelectedProfile].name,
selectedControllerLayer.name]];
diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h
index 07abf8e2..595e1014 100644
--- a/VoidLink/ViewControllers/SettingsViewController.h
+++ b/VoidLink/ViewControllers/SettingsViewController.h
@@ -166,6 +166,9 @@
@property (strong, nonatomic) IBOutlet UIStackView *gyroToStickMinOffsetStack;
@property (strong, nonatomic) IBOutlet UISlider *gyroToStickMinOffsetSlider;
+@property (strong, nonatomic) IBOutlet UIStackView *singleTapSensitivityStack;
+@property (strong, nonatomic) IBOutlet UISlider *singleTapSensitivitySlider;
+
@property (strong, nonatomic) IBOutlet UIStackView *testStack;
@property (nonatomic, strong) MicHandler *micHandler;
diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m
index 1240548e..ce939afb 100644
--- a/VoidLink/ViewControllers/SettingsViewController.m
+++ b/VoidLink/ViewControllers/SettingsViewController.m
@@ -696,6 +696,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.pointerVelocityDividerStack ofId:@"pointerVelocityDividerStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection];
[self addSetting:self.pointerVelocityFactorStack ofId:@"pointerVelocityFactorStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection];
[self addSetting:self.mousePointerVelocityStack ofId:@"mousePointerVelocityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection];
+ [self addSetting:self.singleTapSensitivityStack ofId:@"singleTapSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection];
[self addSetting:self.onScreenWidgetStack ofId:@"onScreenWidgetStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection];
[self addSetting:self.buttonVisualFeedbackStack ofId:@"buttonVisualFeedbackStack" withInfoTag:NO withDynamicLabel:NO to:touchAndControlSection];
[self addSetting:self.swapAbxyStack ofId:@"swapAbaxyStack" withInfoTag:NO withDynamicLabel:NO to:touchAndControlSection];
@@ -1649,7 +1650,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self.buttonVisualFeedbackSwitch setOn:self->tempSettings.buttonVisualFeedback];
[self.gyroModeSelector setSelectedSegmentIndex:self->tempSettings.gyroMode.intValue];
- [self.gyroSensitivitySlider setValue: (uint16_t)(self->tempSettings.gyroSensitivity.floatValue * 100) animated:YES]; // Load old setting.
+ [self.gyroSensitivitySlider setValue: (uint16_t)(self->tempSettings.gyroSensitivity.floatValue * 100) animated:NO]; // Load old setting.
[self.gyroSensitivitySlider addTarget:self action:@selector(gyroSensitivitySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self gyroSensitivitySliderMoved:self.gyroSensitivitySlider];
@@ -1690,7 +1691,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self.bitrateSlider setMinimumValue:0];
[self.bitrateSlider setMaximumValue:(sizeof(bitrateTable) / sizeof(*bitrateTable)) - 1];
- [self.bitrateSlider setValue:[self getSliderValueForBitrate:self->_bitrate] animated:YES];
+ [self.bitrateSlider setValue:[self getSliderValueForBitrate:self->_bitrate] animated:NO];
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
[self updateBitrateText];
[self updateResolutionDisplayLabel];
@@ -1763,12 +1764,12 @@ BOOL isCustomResolution(int resolutionSelected) {
//TouchMode & OSC Related Settings:
// pointer veloc setting, will be enable/disabled by touchMode
- [self.pointerVelocityModeDividerSlider setValue: (uint8_t)(self->tempSettings.pointerVelocityModeDivider.floatValue * 100) animated:YES]; // Load old setting.
+ [self.pointerVelocityModeDividerSlider setValue: (uint8_t)(self->tempSettings.pointerVelocityModeDivider.floatValue * 100) animated:NO]; // Load old setting.
[self.pointerVelocityModeDividerSlider addTarget:self action:@selector(pointerVelocityModeDividerSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self pointerVelocityModeDividerSliderMoved:self.pointerVelocityModeDividerSlider];
// init pointer veloc setting, will be enable/disabled by touchMode
- [self.touchPointerVelocityFactorSlider setValue: [self map_SliderValue_fromVelocFactor: self->tempSettings.touchPointerVelocityFactor.floatValue] animated:YES]; // Load old setting.
+ [self.touchPointerVelocityFactorSlider setValue: [self map_SliderValue_fromVelocFactor: self->tempSettings.touchPointerVelocityFactor.floatValue] animated:NO]; // Load old setting.
[self.touchPointerVelocityFactorSlider addTarget:self action:@selector(touchPointerVelocityFactorSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self touchPointerVelocityFactorSliderMoved:self.touchPointerVelocityFactorSlider];
@@ -1777,10 +1778,13 @@ BOOL isCustomResolution(int resolutionSelected) {
// [self.asyncNativeTouchPrioritySelector addTarget:self action:@selector(asyncNativeTouchPriorityChanged) forControlEvents:UIControlEventValueChanged];
// init relative touch mouse pointer veloc setting, will be enable/disabled by touchMode
- [self.mousePointerVelocityFactorSlider setValue:[self map_SliderValue_fromVelocFactor: self->tempSettings.mousePointerVelocityFactor.floatValue] animated:YES]; // Load old setting.
+ [self.mousePointerVelocityFactorSlider setValue:[self map_SliderValue_fromVelocFactor: self->tempSettings.mousePointerVelocityFactor.floatValue] animated:NO]; // Load old setting.
[self.mousePointerVelocityFactorSlider addTarget:self action:@selector(mousePointerVelocityFactorSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self mousePointerVelocityFactorSliderMoved:self.mousePointerVelocityFactorSlider];
-
+
+ [self.singleTapSensitivitySlider setValue:self->tempSettings.singleTapSensitivity.doubleValue animated:NO];
+ [self.singleTapSensitivitySlider addTarget:self action:@selector(singleTapSensitivitySliderMoved:) forControlEvents:(UIControlEventValueChanged)];
+ [self singleTapSensitivitySliderMoved:self.singleTapSensitivitySlider];
// these settings will be affected by onscreenControl & touchMode, must be loaded before them.
// NSLog(@"osc tool fingers setting test: %d", currentSettings.oscLayoutToolFingers.intValue);
@@ -1798,7 +1802,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self onScreenWidgetChanged];
// touch move event interval for native-touch.
- [self.touchMoveEventIntervalSlider setValue:self->tempSettings.touchMoveEventInterval.intValue animated:YES]; // Load old setting.
+ [self.touchMoveEventIntervalSlider setValue:self->tempSettings.touchMoveEventInterval.intValue animated:NO]; // Load old setting.
[self.touchMoveEventIntervalSlider addTarget:self action:@selector(touchMoveEventIntervalSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self touchMoveEventIntervalSliderMoved:self.touchMoveEventIntervalSlider];
@@ -1895,7 +1899,7 @@ BOOL isCustomResolution(int resolutionSelected) {
if (!self->_mainFrameViewController.settingsExpandedInStreamView) {
[self invokeOscLayout]; // Don't open osc layout tool immediately during streaming
}
-
+
[self findDynamicLabelFromStack:self.onScreenWidgetStack].text = [self isCustomOswEnabled] ? [LocalizationHelper localizedStringForKey:@"%d finger tap", self->oswLayoutFingers] : @"";
[self handleOswGestureChange];}];
@@ -2195,6 +2199,11 @@ BOOL isCustomResolution(int resolutionSelected) {
[self findDynamicLabelFromStack:_mousePointerVelocityStack].text = [NSString stringWithFormat:@" %d%% ",(uint16_t)[self map_velocFactorDisplay_fromSliderValue:sender.value]];
}
+- (void) singleTapSensitivitySliderMoved:(UISlider* )sender {
+ [self findDynamicLabelFromStack:_singleTapSensitivityStack].text = [NSString stringWithFormat:@" %.1f ",sender.value];
+}
+
+
- (uint32_t) getScreenEdgeFromSelector {
switch (self.slideToSettingsScreenEdgeSelector.selectedSegmentIndex) {
case 0: return UIRectEdgeLeft;
@@ -2254,6 +2263,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self setHidden:!isNativeTouch forStack:self.pointerVelocityFactorStack];
[self setHidden:!(sender.selectedSegmentIndex == RelativeTouch) forStack:self.mousePointerVelocityStack];
+ [self setHidden:!(sender.selectedSegmentIndex == RelativeTouch) forStack:self.singleTapSensitivityStack];
[self setHidden:![self isNotNativeTouchOnly] forStack:self.onScreenWidgetStack];
[self setHidden:![self isNotNativeTouchOnly] forStack:self.buttonVisualFeedbackStack];
[self handleOswGestureChange];
@@ -2401,7 +2411,7 @@ BOOL isCustomResolution(int resolutionSelected) {
defaultBitrate = round(resolutionFactor * frameRateFactor) * 1000;
_bitrate = MIN(defaultBitrate, 100000);
- [self.bitrateSlider setValue:[self getSliderValueForBitrate:_bitrate] animated:YES];
+ [self.bitrateSlider setValue:[self getSliderValueForBitrate:_bitrate] animated:NO];
[self updateBitrateText];
}
@@ -2781,6 +2791,7 @@ BOOL isCustomResolution(int resolutionSelected) {
NSInteger localMousePointerMode = [self.localMousePointerModeSelector selectedSegmentIndex];
BOOL sendDummyEvent = self.sendDummyEventSwitch.isOn;
BOOL rememberFoldState = self.rememberFoldStateSwitch.isOn;
+ CGFloat singleTapSensitivity = self.singleTapSensitivitySlider.value;
NSInteger backgroundSessionTimer = self.backgroundSessionTimerSlider.value == self.backgroundSessionTimerSlider.maximumValue ? (uint32_t) INT16_MAX : (uint32_t)self.backgroundSessionTimerSlider.value;
[dataMan saveSettingsWithBitrate:_bitrate
@@ -2832,6 +2843,7 @@ BOOL isCustomResolution(int resolutionSelected) {
framePacingMode:framePacingMode
sendDummyEvent:sendDummyEvent
rememberFoldState:rememberFoldState
+ singleTapSensitivy:singleTapSensitivity
backgroundSessionTimer:backgroundSessionTimer];
}
diff --git a/VoidLink/mul.lproj/iPad.xcstrings b/VoidLink/mul.lproj/iPad.xcstrings
index 2022de41..5f7bc9e1 100644
--- a/VoidLink/mul.lproj/iPad.xcstrings
+++ b/VoidLink/mul.lproj/iPad.xcstrings
@@ -1394,13 +1394,13 @@
}
},
"cKS-fy-Zpg.segmentTitles[0]" : {
- "comment" : "Class = \"UISegmentedControl\"; cKS-fy-Zpg.segmentTitles[0] = \"slide to toggle\"; ObjectID = \"cKS-fy-Zpg\";",
+ "comment" : "Class = \"UISegmentedControl\"; cKS-fy-Zpg.segmentTitles[0] = \"slide-toggle\"; ObjectID = \"cKS-fy-Zpg\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
- "value" : "slide to toggle"
+ "value" : "slide-toggle"
}
},
"zh-Hans" : {
@@ -1424,30 +1424,30 @@
}
},
"cKS-fy-Zpg.segmentTitles[1]" : {
- "comment" : "Class = \"UISegmentedControl\"; cKS-fy-Zpg.segmentTitles[1] = \"slide & hold\"; ObjectID = \"cKS-fy-Zpg\";",
+ "comment" : "Class = \"UISegmentedControl\"; cKS-fy-Zpg.segmentTitles[1] = \"slide-hold\"; ObjectID = \"cKS-fy-Zpg\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
- "value" : "slide & hold"
+ "value" : "slide-hold"
}
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑动时按下"
}
},
"zh-Hant" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑動時按下"
}
},
"zh-HK" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑動時按下"
}
}
@@ -3865,6 +3865,36 @@
}
}
},
+ "SuN-S2-8hj.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Single Tap Sensitivity\"; ObjectID = \"SuN-S2-8hj\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Single Tap Sensitivity"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "单击灵敏度"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "單擊靈敏度"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "單擊靈敏度"
+ }
+ }
+ }
+ },
"t7a-18-5wz.text" : {
"comment" : "Class = \"UILabel\"; text = \"Performance Graphs \"; ObjectID = \"t7a-18-5wz\";",
"extractionState" : "extracted_with_value",
diff --git a/VoidLink/mul.lproj/iPhone.xcstrings b/VoidLink/mul.lproj/iPhone.xcstrings
index 71229c12..c0f5c5ed 100644
--- a/VoidLink/mul.lproj/iPhone.xcstrings
+++ b/VoidLink/mul.lproj/iPhone.xcstrings
@@ -2672,60 +2672,60 @@
}
},
"ojp-aS-m8w.segmentTitles[0]" : {
- "comment" : "Class = \"UISegmentedControl\"; ojp-aS-m8w.segmentTitles[0] = \"slide to toggle\"; ObjectID = \"ojp-aS-m8w\";",
+ "comment" : "Class = \"UISegmentedControl\"; ojp-aS-m8w.segmentTitles[0] = \"slide-toggle\"; ObjectID = \"ojp-aS-m8w\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
- "value" : "slide to toggle"
+ "value" : "slide-toggle"
}
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑出时松开"
}
},
"zh-Hant" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑出時鬆開"
}
},
"zh-HK" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑出時鬆開"
}
}
}
},
"ojp-aS-m8w.segmentTitles[1]" : {
- "comment" : "Class = \"UISegmentedControl\"; ojp-aS-m8w.segmentTitles[1] = \"slide & hold\"; ObjectID = \"ojp-aS-m8w\";",
+ "comment" : "Class = \"UISegmentedControl\"; ojp-aS-m8w.segmentTitles[1] = \"slide-hold\"; ObjectID = \"ojp-aS-m8w\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
- "value" : "slide & hold"
+ "value" : "slide-hold"
}
},
"zh-Hans" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑动时按下"
}
},
"zh-Hant" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑動時按下"
}
},
"zh-HK" : {
"stringUnit" : {
- "state" : "translated",
+ "state" : "needs_review",
"value" : "滑動時按下"
}
}
@@ -4171,6 +4171,36 @@
}
}
},
+ "WzD-wo-Wum.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Single Tap Sensitivity\"; ObjectID = \"WzD-wo-Wum\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Single Tap Sensitivity"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "单击灵敏度"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "單擊靈敏度"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "單擊靈敏度"
+ }
+ }
+ }
+ },
"XtQ-YN-4jb.text" : {
"comment" : "Class = \"UILabel\"; text = \"Touch Move Event Interval\"; ObjectID = \"XtQ-YN-4jb\";",
"extractionState" : "extracted_with_value",