mac desktop experience fixes & tips
This commit is contained in:
@@ -8,6 +8,13 @@
|
||||
import UIKit
|
||||
|
||||
@objc class AlertControllerUtil: NSObject {
|
||||
private static func makeCountdownMessage(baseMessage: String?, remainingSeconds: Int) -> String {
|
||||
let countdownText = "\(remainingSeconds)"
|
||||
guard let baseMessage, !baseMessage.isEmpty else {
|
||||
return countdownText
|
||||
}
|
||||
return "\(baseMessage)\n\n\(countdownText)"
|
||||
}
|
||||
|
||||
/// 类方法,直接在任何 UIViewController 上显示倒计时弹窗
|
||||
/// - Parameters:
|
||||
@@ -34,16 +41,24 @@ import UIKit
|
||||
completion: (() -> Void)? = nil
|
||||
) {
|
||||
var remainingSeconds = countdown
|
||||
let originalMessage = message
|
||||
var isAlertDismissed = false
|
||||
|
||||
alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alertController = UIAlertController(
|
||||
title: title,
|
||||
message: (countdown > 0 && !autoCompletion) ? makeCountdownMessage(baseMessage: originalMessage, remainingSeconds: remainingSeconds) : message,
|
||||
preferredStyle: .alert
|
||||
)
|
||||
|
||||
let confirmAction = UIAlertAction(title: "\(remainingSeconds)", style: .default) { _ in
|
||||
let confirmAction = UIAlertAction(title: buttonTitle, style: .default) { _ in
|
||||
isAlertDismissed = true
|
||||
actionCancelled = false
|
||||
completion?()
|
||||
cancelButtonString = "Cancel"
|
||||
}
|
||||
|
||||
let cancelAction = UIAlertAction(title: SwiftLocalizationHelper.localizedString(forKey: cancelButtonString), style: .cancel) { _ in
|
||||
isAlertDismissed = true
|
||||
actionCancelled = true
|
||||
completion?()
|
||||
cancelButtonString = "Cancel"
|
||||
@@ -55,7 +70,6 @@ import UIKit
|
||||
if buttonTitle != "" && !autoCompletion {alertController.addAction(confirmAction)}
|
||||
|
||||
if(countdown == 0) {
|
||||
confirmAction.setValue(buttonTitle, forKey: "title")
|
||||
confirmAction.isEnabled = buttonTitle != ""
|
||||
}
|
||||
|
||||
@@ -65,22 +79,46 @@ import UIKit
|
||||
|
||||
// 倒计时
|
||||
let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main)
|
||||
timer.schedule(deadline: .now(), repeating: 1.0, leeway: .milliseconds(50))
|
||||
timer.schedule(deadline: .now() + (autoCompletion ? 0.5 : 1.0), repeating: autoCompletion ? 0.1: 1.0, leeway: .milliseconds(50))
|
||||
timer.setEventHandler {
|
||||
guard !isAlertDismissed else {
|
||||
timer.cancel()
|
||||
return
|
||||
}
|
||||
|
||||
remainingSeconds -= 1
|
||||
|
||||
if remainingSeconds <= 0 {
|
||||
isAlertDismissed = true
|
||||
timer.cancel()
|
||||
confirmAction.isEnabled = true
|
||||
confirmAction.setValue(buttonTitle, forKey: "title")
|
||||
if autoCompletion {
|
||||
alertController.message = originalMessage
|
||||
autoCompletion = false
|
||||
completion?()
|
||||
alertController.dismiss(animated: false)
|
||||
return
|
||||
}
|
||||
|
||||
if GenericUtils.isRunningOnMacAsiPadApp && buttonTitle != "" {
|
||||
alertController.dismiss(animated: false) {
|
||||
showAlert(
|
||||
in: viewController,
|
||||
title: title,
|
||||
message: originalMessage,
|
||||
withCancel: withCancel,
|
||||
buttonTitle: buttonTitle,
|
||||
countdown: 0,
|
||||
action: nil,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
confirmAction.isEnabled = true
|
||||
alertController.message = originalMessage
|
||||
} else {
|
||||
confirmAction.setValue("\(remainingSeconds)", forKey: "title")
|
||||
if !autoCompletion {alertController.message = makeCountdownMessage(baseMessage: originalMessage, remainingSeconds: remainingSeconds)}
|
||||
}
|
||||
}
|
||||
timer.resume()
|
||||
|
||||
@@ -1372,13 +1372,13 @@
|
||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="nE1-Al-qRc" userLabel="localMousePointerMode Stack">
|
||||
<rect key="frame" x="18" y="2848" width="380" height="56.5"/>
|
||||
<subviews>
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Local Mouse Pointer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tAd-bm-2IO">
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Local Mouse Cursor" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tAd-bm-2IO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.93902439019999995" green="0.9625305918" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="4FU-iP-c6T" userLabel="Mouse Mode">
|
||||
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="4FU-iP-c6T" userLabel="Mouse Mode">
|
||||
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
|
||||
<segments>
|
||||
<segment title="Captured"/>
|
||||
|
||||
@@ -152,13 +152,13 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Jnu-63-bcf" customClass="ToolBarContainerView">
|
||||
<rect key="frame" x="0.0" y="96" width="410" height="45"/>
|
||||
<rect key="frame" x="0.0" y="96" width="1300" height="45"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleAspectFill" distribution="fillEqually" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="4he-pe-kYB">
|
||||
<rect key="frame" x="0.0" y="-2.5" width="410" height="50"/>
|
||||
<rect key="frame" x="0.0" y="-2.5" width="1300" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" tag="40" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="fill" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nHH-6h-4D1" userLabel="Exit">
|
||||
<rect key="frame" x="0.0" y="9.5" width="50" height="31"/>
|
||||
<rect key="frame" x="0.0" y="9.5" width="177" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="sBF-hd-nF8"/>
|
||||
</constraints>
|
||||
@@ -174,7 +174,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Pdg-l4-BvF" userLabel="Undo">
|
||||
<rect key="frame" x="60" y="0.0" width="50" height="50"/>
|
||||
<rect key="frame" x="187" y="0.0" width="177.5" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="7KW-Xe-OEK"/>
|
||||
<constraint firstAttribute="width" constant="50" id="gHD-A0-AVS"/>
|
||||
@@ -191,7 +191,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rXW-Ms-2cJ" userLabel="Load">
|
||||
<rect key="frame" x="120" y="0.0" width="50" height="50"/>
|
||||
<rect key="frame" x="374.5" y="0.0" width="177" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="91g-27-mVH"/>
|
||||
<constraint firstAttribute="height" constant="50" id="kRj-b6-Bx1"/>
|
||||
@@ -207,7 +207,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LPA-ea-YHC" userLabel="Save">
|
||||
<rect key="frame" x="180" y="0.0" width="50" height="50"/>
|
||||
<rect key="frame" x="561.5" y="0.0" width="177" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="Lot-pn-o60"/>
|
||||
<constraint firstAttribute="height" constant="50" id="uWO-So-qxr"/>
|
||||
@@ -223,7 +223,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" tag="20" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dhG-Fo-0GK" userLabel="Trash">
|
||||
<rect key="frame" x="240" y="0.0" width="50" height="50"/>
|
||||
<rect key="frame" x="748.5" y="0.0" width="177" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="0vV-wV-Efz"/>
|
||||
<constraint firstAttribute="width" constant="50" id="j9W-Ja-bVn"/>
|
||||
@@ -239,7 +239,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Up4-28-sgF" userLabel="Add">
|
||||
<rect key="frame" x="300" y="0.0" width="50" height="50"/>
|
||||
<rect key="frame" x="935.5" y="0.0" width="177.5" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="rWU-US-9dl"/>
|
||||
<constraint firstAttribute="width" constant="50" id="wWj-wB-MRd"/>
|
||||
@@ -254,7 +254,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4pE-po-Zn1" userLabel="Edit">
|
||||
<rect key="frame" x="360" y="0.0" width="50" height="50"/>
|
||||
<rect key="frame" x="1123" y="0.0" width="177" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="oFn-jm-orG"/>
|
||||
<constraint firstAttribute="height" constant="50" id="sls-Vh-uxz"/>
|
||||
@@ -273,7 +273,7 @@
|
||||
</subviews>
|
||||
</stackView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Zll-IP-PFt" userLabel="Chevron View">
|
||||
<rect key="frame" x="179" y="45" width="52" height="25"/>
|
||||
<rect key="frame" x="624" y="45" width="52" height="25"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ChevronCompactUp" translatesAutoresizingMaskIntoConstraints="NO" id="76O-3K-aa8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="52" height="25"/>
|
||||
@@ -302,7 +302,7 @@
|
||||
</constraints>
|
||||
</view>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="7" translatesAutoresizingMaskIntoConstraints="NO" id="BVp-3O-vZ7" userLabel="widgetPanelStack" customClass="WidgetPanelStackView">
|
||||
<rect key="frame" x="-70" y="132" width="550" height="1110"/>
|
||||
<rect key="frame" x="375" y="132" width="550" height="1110"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Profile:" textAlignment="center" lineBreakMode="tailTruncation" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="f46-Pt-0Pv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="550" height="28"/>
|
||||
@@ -1940,13 +1940,13 @@
|
||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="IKt-3O-raJ" userLabel="localMousePointerMode Stack">
|
||||
<rect key="frame" x="0.0" y="2553" width="380" height="56.5"/>
|
||||
<subviews>
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Local Mouse Pointer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mdA-jF-9Mf">
|
||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Local Mouse Cursor" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mdA-jF-9Mf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.93902439019999995" green="0.9625305918" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="zLl-8w-K8J" userLabel="Mouse Mode">
|
||||
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="zLl-8w-K8J" userLabel="Mouse Mode">
|
||||
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
|
||||
<segments>
|
||||
<segment title="Captured"/>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
- (void)toggleStatsOverlay;
|
||||
- (void)toggleMouseCapture;
|
||||
- (void)toggleMouseVisible;
|
||||
- (void)expandSettingsView;
|
||||
- (void)disconnectAndQuitApp;
|
||||
|
||||
@end
|
||||
|
||||
@@ -1239,19 +1239,22 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
return;
|
||||
}
|
||||
switch (press.key.keyCode) {
|
||||
case UIKeyboardHIDUsageKeyboardQ:
|
||||
case UIKeyboardHIDUsageKeyboardD:
|
||||
[_interactionDelegate streamExitRequested];
|
||||
break;
|
||||
case UIKeyboardHIDUsageKeyboardS:
|
||||
case UIKeyboardHIDUsageKeyboardO:
|
||||
[_interactionDelegate toggleStatsOverlay];
|
||||
break;
|
||||
case UIKeyboardHIDUsageKeyboardS:
|
||||
[_interactionDelegate expandSettingsView];
|
||||
break;
|
||||
case UIKeyboardHIDUsageKeyboardM:
|
||||
[_interactionDelegate toggleMouseCapture];
|
||||
break;
|
||||
case UIKeyboardHIDUsageKeyboardC:
|
||||
[_interactionDelegate toggleMouseVisible];
|
||||
break;
|
||||
case UIKeyboardHIDUsageKeyboardD:
|
||||
case UIKeyboardHIDUsageKeyboardQ:
|
||||
[_interactionDelegate disconnectAndQuitApp];
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
<attribute name="keyboardToggleFingers" optional="YES" attributeType="Integer 16" defaultValueString="99" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="leftClickDelayMs" optional="YES" attributeType="Float" defaultValueString="15" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="liftStreamViewForKeyboard" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="localMousePointerMode" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="localMousePointerMode" optional="YES" attributeType="Integer 16" defaultValueString="2" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="localVolume" optional="YES" attributeType="Float" defaultValueString="1" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="mapControllerToMouse" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="micVolume" optional="YES" attributeType="Float" defaultValueString="1" usesScalarValueType="NO" syncable="YES"/>
|
||||
|
||||
@@ -4734,25 +4734,25 @@
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Select “Stage Manager” to enable full screen external display.\n\nKeyboard Shortcuts for VoidLink (Desktop Mode):\n\nCtrl + Alt + Shift + Q — Disconnect the current session\n\nCtrl + Alt + Shift + S — Toggle the statistics overlay style\n\nCtrl + Alt + Shift + M — Toggle mouse capture mode\n\nCtrl + Alt + Shift + C — Toggle mouse pointer visibility\n"
|
||||
"value" : "\nKeyboard Shortcuts for VoidLink (Desktop Mode):\n\nCtrl + Alt + Shift + D — Disconnect the current session\n\nCtrl + Alt + Shift + Q — Disconnect the current session and quit current app\n\nCtrl + Alt + Shift + S — Expand the settings menu\n\nCtrl + Alt + Shift + O — Toggle the statistics overlay\n\nCtrl + Alt + Shift + C — Toggle mouse pointer visibility"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "VoidLink 桌面模式快捷键:\n\n- Ctrl + Alt + Shift + Q — 断开当前会话\n\n- Ctrl + Alt + Shift + S — 切换性能信息叠加样式\n\n- Ctrl + Alt + Shift + M — 切换鼠标指针捕获模式\n\n- Ctrl + Alt + Shift + C — 切换鼠标指针可见性"
|
||||
"state" : "translated",
|
||||
"value" : "\nVoidLink 桌面模式快捷键:\n\nCtrl + Alt + Shift + D — 断开当前会话\n\nCtrl + Alt + Shift + Q — 断开当前会话并退出当前app\n\nCtrl + Alt + Shift + S — 展开设置菜单\n\nCtrl + Alt + Shift + O — 切换性能信息叠加\n\nCtrl + Alt + Shift + C — 切换鼠标指针可见性"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "VoidLink 桌面模式快捷鍵:\n\nCtrl + Alt + Shift + Q — 中斷目前連線\n\nCtrl + Alt + Shift + S — 切換統計資訊覆蓋樣式\n\nCtrl + Alt + Shift + M — 切換滑鼠指標捕捉模式\n\nCtrl + Alt + Shift + C — 切換滑鼠指標可見性"
|
||||
"state" : "translated",
|
||||
"value" : "\nVoidLink 桌面模式快速鍵:\n\nCtrl + Alt + Shift + D — 中斷目前連線\n\nCtrl + Alt + Shift + Q — 中斷目前連線並退出目前app\n\nCtrl + Alt + Shift + S — 展開設定選單\n\nCtrl + Alt + Shift + O — 切換統計資訊覆蓋\n\nCtrl + Alt + Shift + C — 切換滑鼠指標可見性"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "VoidLink 桌面模式快捷鍵:\n\nCtrl + Alt + Shift + Q — 中斷目前連線\n\nCtrl + Alt + Shift + S — 切換統計資訊覆蓋樣式\n\nCtrl + Alt + Shift + M — 切換滑鼠指標捕捉模式\n\nCtrl + Alt + Shift + C — 切換滑鼠指標可見性"
|
||||
"state" : "translated",
|
||||
"value" : "\nVoidLink 桌面模式快速鍵:\n\nCtrl + Alt + Shift + D — 中斷目前連線\n\nCtrl + Alt + Shift + Q — 中斷目前連線並退出目前app\n\nCtrl + Alt + Shift + S — 展開設定選單\n\nCtrl + Alt + Shift + O — 切換統計資訊覆蓋\n\nCtrl + Alt + Shift + C — 切換滑鼠指標可見性"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6911,6 +6911,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"macFirstLaunchTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "\nKeyboard Shortcuts for VoidLink (Desktop Mode):\n\nCtrl + Alt + Shift + D — Disconnect the current session\n\nCtrl + Alt + Shift + Q — Disconnect the current session and quit current app\n\nCtrl + Alt + Shift + S — Expand the settings menu\n\nCtrl + Alt + Shift + O — Toggle the statistics overlay\n\nCtrl + Alt + Shift + C — Toggle mouse pointer visibility\n\nBy default, the mouse cannot control the camera in 3D games. To stream games, please disconnect the current session, then go to Settings → Peripheral Section → Local Mouse Cursor, and select “Capture”."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "\nVoidLink 桌面模式快捷键:\n\nCtrl + Alt + Shift + D — 断开当前会话\n\nCtrl + Alt + Shift + Q — 断开当前会话并退出当前app\n\nCtrl + Alt + Shift + S — 展开设置菜单\n\nCtrl + Alt + Shift + O — 切换性能信息叠加\n\nCtrl + Alt + Shift + C — 切换鼠标指针可见性\n\n默认状态下鼠标无法在3D游戏中转动视角。如需串流游戏,请断开当前会话,前往设置菜单 -> 外设分区 -> 本地鼠标指针,选择“被窗口捕获”。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "\nVoidLink 桌面模式快速鍵:\n\nCtrl + Alt + Shift + D — 中斷目前連線\n\nCtrl + Alt + Shift + Q — 中斷目前連線並退出目前app\n\nCtrl + Alt + Shift + S — 展開設定選單\n\nCtrl + Alt + Shift + O — 切換統計資訊覆蓋\n\nCtrl + Alt + Shift + C — 切換滑鼠指標可見性\n\n預設狀態下,滑鼠無法在 3D 遊戲中轉動視角。如需進行串流遊戲,請中斷目前會話,前往設定選單 → 外設分區 → 本地滑鼠指標,選擇「被視窗捕獲」。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "\nVoidLink 桌面模式快速鍵:\n\nCtrl + Alt + Shift + D — 中斷目前連線\n\nCtrl + Alt + Shift + Q — 中斷目前連線並退出目前app\n\nCtrl + Alt + Shift + S — 展開設定選單\n\nCtrl + Alt + Shift + O — 切換統計資訊覆蓋\n\nCtrl + Alt + Shift + C — 切換滑鼠指標可見性\n\n預設狀態下,滑鼠無法在 3D 遊戲中轉動視角。如需進行串流遊戲,請中斷目前會話,前往設定選單 → 外設分區 → 本地滑鼠指標,選擇「被視窗捕獲」。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Manual_Add_Host_Fail" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -12241,7 +12270,7 @@
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"state" : "translated",
|
||||
"value" : "- 觸控板:拖曳方式與 Windows 筆記型電腦觸控板完全相同。快速輕點兩下,從第二次輕點開始進入拖曳模式。\n\n- 多点觸控:macOS 不支援。\n\n- 單點滑鼠:在 macOS 上提供類似觸控螢幕的體驗。"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -22,6 +22,16 @@ import UIKit
|
||||
return true
|
||||
}
|
||||
|
||||
@objc static func needUpdatePartialSettings() -> Bool {
|
||||
// let key = "needUpdateDefaultSettings20260226-1"
|
||||
let key = "needUpdatePartialSettings20260428"
|
||||
guard !UserDefaults.standard.bool(forKey: key) else {
|
||||
return false
|
||||
}
|
||||
UserDefaults.standard.set(true, forKey: key)
|
||||
return true
|
||||
}
|
||||
|
||||
@objc static func isEnableOswForNativeTouchSwitchFirstFlipping() -> Bool {
|
||||
let key = "enableOswForNativeTouchSwitchFlipped"
|
||||
guard !UserDefaults.standard.bool(forKey: key) else {
|
||||
@@ -78,6 +88,20 @@ import UIKit
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@objc static func isFirstStreamingOnMac() -> Bool {
|
||||
if !isRunningOnMacAsiPadApp {return false}
|
||||
let key = "hasStreamedOnMac"
|
||||
let defaults = UserDefaults.standard
|
||||
let launchedBefore = defaults.bool(forKey: key)
|
||||
|
||||
if !launchedBefore {
|
||||
defaults.set(true, forKey: key)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@objc static func gamepadOverlayFeatureTipTitle() -> String {
|
||||
SwiftLocalizationHelper.localizedString(forKey: "Gamepad Overlay")
|
||||
@@ -98,6 +122,13 @@ import UIKit
|
||||
@objc static func isIPad() -> Bool {
|
||||
return UIDevice.current.userInterfaceIdiom == .pad
|
||||
}
|
||||
|
||||
@objc static var isRunningOnMacAsiPadApp: Bool {
|
||||
if #available(iOS 14.0, *) {
|
||||
return ProcessInfo.processInfo.isiOSAppOnMac
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@objc static let liquidGlassEnabled: Bool = {
|
||||
if #available(iOS 26.0, tvOS 26.0, *) {
|
||||
|
||||
@@ -1740,6 +1740,15 @@ static NSMutableSet* hostList;
|
||||
[dataMan saveData];
|
||||
}
|
||||
|
||||
- (void)updatePartialSettings{
|
||||
if(![GenericUtils needUpdatePartialSettings]) return;
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
Settings* settings = [dataMan retrieveSettings];
|
||||
settings.touchMoveEventInterval = @(0);
|
||||
settings.localMousePointerMode = @(2);
|
||||
[dataMan saveData];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad{
|
||||
[super viewDidLoad];
|
||||
|
||||
@@ -1863,7 +1872,7 @@ static NSMutableSet* hostList;
|
||||
[IAPManager.shared fetchProducts];
|
||||
|
||||
[self changeDefaultSettings];
|
||||
|
||||
[self updatePartialSettings];
|
||||
/*
|
||||
if (@available(iOS 15.0, *)) {
|
||||
[IAPManager checkPurchaseInfo:AddOnProductPencilProPack completion:^(PurchaseInfo* info) {
|
||||
|
||||
@@ -1174,8 +1174,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
|
||||
[self addSetting:self.touchModeStack2 ofId:@"touchModeStack2" to:experimentalSection];
|
||||
|
||||
self.touchMoveEventIntervalStack.hasDynamicLabel = YES;
|
||||
[self addSetting:self.touchMoveEventIntervalStack ofId:@"touchMoveEventIntervalStack" to:experimentalSection];
|
||||
// self.touchMoveEventIntervalStack.hasDynamicLabel = YES;
|
||||
// [self addSetting:self.touchMoveEventIntervalStack ofId:@"touchMoveEventIntervalStack" to:experimentalSection];
|
||||
|
||||
self.relativeTouchSlideThresholdStack.hasInfoTag = YES;
|
||||
self.relativeTouchSlideThresholdStack.hasDynamicLabel = YES;
|
||||
@@ -2389,7 +2389,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
[self.onScreenWidgetSelector addTarget:self action:@selector(onScreenWidgetChanged) forControlEvents:UIControlEventValueChanged];
|
||||
[self onScreenWidgetChanged];
|
||||
|
||||
// touch move event interval for native-touch.
|
||||
/*
|
||||
[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];
|
||||
@@ -2398,6 +2398,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
[self.leftClickDelaySlider setValue:self->tempSettings.leftClickDelayMs.intValue animated:NO]; // Load old setting.
|
||||
[self.leftClickDelaySlider addTarget:self action:@selector(leftClickDelaySliderMoved:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
|
||||
[self leftClickDelaySliderMoved:self.leftClickDelaySlider];
|
||||
*/
|
||||
|
||||
// this part will enable/disable oscSelector & the asyncNativeTouchPriority selector
|
||||
uint8_t touchModeSelectorIndex = self->tempSettings.touchMode.intValue == NativeTouchOnly ? NativeTouch : self->tempSettings.touchMode.intValue;
|
||||
@@ -3183,10 +3184,10 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
|
||||
[self setHidden:!isNativeTouch forStack:self.pointerVelocityDividerStack];
|
||||
|
||||
[self touchMoveEventIntervalSliderMoved:self.touchMoveEventIntervalSlider];
|
||||
// [self touchMoveEventIntervalSliderMoved:self.touchMoveEventIntervalSlider];
|
||||
[self setHidden:!isNativeTouch forStack:self.pointerVelocityDividerStack];
|
||||
[self setHidden:!isNativeTouch forStack:self.pointerVelocityFactorStack];
|
||||
[self setHidden:!isNativeTouch forStack:self.touchMoveEventIntervalStack];
|
||||
// [self setHidden:!isNativeTouch forStack:self.touchMoveEventIntervalStack];
|
||||
|
||||
/*
|
||||
[self setHidden:(sender.selectedSegmentIndex!=RelativeTouch
|
||||
@@ -3384,7 +3385,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
// NSInteger fps = [self getChosenFrameRate];
|
||||
[self touchMoveEventIntervalSliderMoved:self.touchMoveEventIntervalSlider];
|
||||
// [self touchMoveEventIntervalSliderMoved:self.touchMoveEventIntervalSlider];
|
||||
[self updateBitrate];
|
||||
}
|
||||
|
||||
@@ -3993,7 +3994,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
||||
CGFloat localVolume = self.localVolumeSlider.value/100;
|
||||
CGFloat micVolume = self.micVolumeSlider.value/100;
|
||||
|
||||
uint16_t touchMoveEventInterval = (uint16_t)self.touchMoveEventIntervalSlider.value;
|
||||
uint16_t touchMoveEventInterval = 0;
|
||||
|
||||
BOOL reverseMouseWheelDirection = [self.reverseMouseWheelDirectionSelector selectedSegmentIndex] == 1;
|
||||
NSInteger asyncNativeTouchPriority = 1;
|
||||
|
||||
@@ -582,7 +582,9 @@
|
||||
NSString* cmdToolEdgeSide = _settings.slideToSettingsScreenEdge.intValue == UIRectEdgeLeft ? [LocalizationHelper localizedStringForKey:@"right"] : [LocalizationHelper localizedStringForKey:@"left"];
|
||||
uint8_t slideDist = (uint8_t)(_settings.slideToSettingsDistance.floatValue * 100);
|
||||
// 创建弹窗
|
||||
NSString* tipText = [LocalizationHelper localizedStringForKey:@"firstLaunchTip", settingsEdgeSide, slideDist, cmdToolEdgeSide, slideDist];
|
||||
NSString* tipText = (GenericUtils.isRunningOnMacAsiPadApp
|
||||
? [LocalizationHelper localizedStringForKey:@"macFirstLaunchTip"]
|
||||
: [LocalizationHelper localizedStringForKey:@"firstLaunchTip", settingsEdgeSide, slideDist, cmdToolEdgeSide, slideDist]) ;
|
||||
|
||||
[AlertControllerUtil showAlertIn:self
|
||||
title:[LocalizationHelper localizedStringForKey:@"First Launch Tips"]
|
||||
@@ -659,7 +661,7 @@
|
||||
//[_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig];
|
||||
[self reConfigStreamViewRealtime]; // call this method again to make sure all gestures are configured & added to the superview(self.view), including the gestures added from inside the streamview.
|
||||
|
||||
if([self isFirstStreaming]) [self popFirstStreamingTip];
|
||||
if([self isFirstStreaming] || GenericUtils.isFirstStreamingOnMac) [self popFirstStreamingTip];
|
||||
|
||||
#if TARGET_OS_TV
|
||||
if (!_menuTapGestureRecognizer || !_menuDoubleTapGestureRecognizer || !_playPauseTapGestureRecognizer) {
|
||||
|
||||
@@ -6095,30 +6095,30 @@
|
||||
}
|
||||
},
|
||||
"tAd-bm-2IO.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Local Mouse Pointer\"; ObjectID = \"tAd-bm-2IO\";",
|
||||
"comment" : "Class = \"UILabel\"; text = \"Local Mouse Cursor\"; ObjectID = \"tAd-bm-2IO\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Local Mouse Pointer"
|
||||
"value" : "Local Mouse Cursor"
|
||||
}
|
||||
},
|
||||
"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" : "本地滑鼠指標"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3422,30 +3422,30 @@
|
||||
}
|
||||
},
|
||||
"mdA-jF-9Mf.text" : {
|
||||
"comment" : "Class = \"UILabel\"; text = \"Local Mouse Pointer\"; ObjectID = \"mdA-jF-9Mf\";",
|
||||
"comment" : "Class = \"UILabel\"; text = \"Local Mouse Cursor\"; ObjectID = \"mdA-jF-9Mf\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Local Mouse Pointer"
|
||||
"value" : "Local Mouse Cursor"
|
||||
}
|
||||
},
|
||||
"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" : "本地滑鼠指標"
|
||||
}
|
||||
}
|
||||
@@ -3505,13 +3505,13 @@
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"state" : "translated",
|
||||
"value" : "異步多點觸控"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"state" : "translated",
|
||||
"value" : "異步多點觸控"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user