Merge remote-tracking branch 'refs/remotes/upstream/Integration' into feat/frame_pacing_metal
# Conflicts: # VoidLink/Base.lproj/iPad.storyboard # VoidLink/ViewControllers/SettingsViewController.m
This commit is contained in:
@@ -1292,7 +1292,7 @@
|
||||
"$(PROJECT_DIR)/libs/SDL2/lib/iOS-Sim",
|
||||
"$(PROJECT_DIR)/libs/FFmpeg/lib/iOS-Sim",
|
||||
);
|
||||
MARKETING_VERSION = 0.0.1;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.voidlink.tf.debug10.iOS;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
@@ -1357,7 +1357,7 @@
|
||||
"$(PROJECT_DIR)/libs/SDL2/lib/iOS-Sim",
|
||||
"$(PROJECT_DIR)/libs/FFmpeg/lib/iOS-Sim",
|
||||
);
|
||||
MARKETING_VERSION = 0.0.1;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.voidlink.tf.iOS;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -17,9 +17,10 @@ public struct AboutView: View {
|
||||
VStack(spacing: 10) {
|
||||
// App 图标
|
||||
Image(uiImage: UIImage(named: "AppIconMedium") ?? UIImage())
|
||||
.resizable()
|
||||
.frame(width: 80, height: 80)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 36))
|
||||
// .resizable()
|
||||
.resizable(capInsets:EdgeInsets(top: 3.5, leading: 3.5, bottom: 3.5, trailing: 3.5))
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 28))
|
||||
|
||||
// App 名称
|
||||
Text(Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? "App Name")
|
||||
@@ -56,7 +57,7 @@ public struct AboutView: View {
|
||||
}
|
||||
// 链接按钮
|
||||
if #available(iOS 14.0, *) {
|
||||
Link(SwiftLocalizationHelper.localizedString(forKey: "Join us"), destination: URL(string: "https://example.com")!)
|
||||
Link(SwiftLocalizationHelper.localizedString(forKey: "Join us"), destination: URL(string: SwiftLocalizationHelper.localizedString(forKey: "supportLink"))!)
|
||||
.padding(.top, 10)
|
||||
Spacer()
|
||||
// OK 按钮
|
||||
@@ -73,7 +74,7 @@ public struct AboutView: View {
|
||||
HStack(spacing: 20) {
|
||||
Button(SwiftLocalizationHelper.localizedString(forKey: "Join us")) {
|
||||
// 打开链接
|
||||
if let url = URL(string: "https://example.com") {
|
||||
if let url = URL(string: SwiftLocalizationHelper.localizedString(forKey: "supportLink")) {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
}
|
||||
@@ -81,6 +82,7 @@ public struct AboutView: View {
|
||||
.background(Color.blue)
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(12)
|
||||
.frame(height: 33)
|
||||
.frame(minWidth: 100)
|
||||
|
||||
Button("OK") {
|
||||
@@ -90,6 +92,7 @@ public struct AboutView: View {
|
||||
.background(Color.blue)
|
||||
.foregroundColor(.white)
|
||||
.cornerRadius(12)
|
||||
.frame(height: 33)
|
||||
.frame(minWidth: 100)
|
||||
}
|
||||
.padding(.top, 10)
|
||||
|
||||
@@ -28,7 +28,7 @@ import SwiftUI
|
||||
])
|
||||
|
||||
// 🎯 设置弹窗大小
|
||||
preferredContentSize = CGSize(width: 600, height: 450)
|
||||
preferredContentSize = CGSize(width: 530, height: 450)
|
||||
//preferredContentSize = CGSize(width:150, height:120 )
|
||||
|
||||
// ⚠️ 一定要设置以下样式才会生效 preferredContentSize
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="XvO-F3-j4u"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="WRy-3f-gEP" customClass="UIScrollView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="2000" height="2500"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="2000" height="5000"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="zpX-lo-MLA" userLabel="Resolutionstak">
|
||||
@@ -581,7 +581,7 @@
|
||||
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
|
||||
<segments>
|
||||
<segment title="Stage Manager"/>
|
||||
<segment title="AirPlay"/>
|
||||
<segment title="AirPlay (mirroring)"/>
|
||||
</segments>
|
||||
<color key="tintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="selectedSegmentTintColor" systemColor="linkColor"/>
|
||||
@@ -847,27 +847,6 @@
|
||||
<constraint firstAttribute="width" constant="380" id="pkz-ek-bOk"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="20" id="12a-Wi-LlL" userLabel="pipStack">
|
||||
<rect key="frame" x="382" y="1899" width="280" height="31"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable PiP" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3rP-dh-TJi" userLabel="pipLabel">
|
||||
<rect key="frame" x="0.0" y="0.0" width="130" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="130" id="ir2-ut-mD3"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VTC-Z9-IYM" userLabel="pipSwitch">
|
||||
<rect key="frame" x="150" y="0.0" width="132" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="130" id="ADb-7C-hgx"/>
|
||||
</constraints>
|
||||
</switch>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="6hG-dw-YSr" userLabel="renderingBackend Stack">
|
||||
<rect key="frame" x="20" y="1166" width="380" height="56.5"/>
|
||||
<subviews>
|
||||
@@ -1008,12 +987,32 @@
|
||||
</switch>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="20" id="12a-Wi-LlL" userLabel="pipStack">
|
||||
<rect key="frame" x="432" y="1860" width="280" height="31"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable PiP" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3rP-dh-TJi" userLabel="pipLabel">
|
||||
<rect key="frame" x="0.0" y="0.0" width="130" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="130" id="ir2-ut-mD3"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VTC-Z9-IYM" userLabel="pipSwitch">
|
||||
<rect key="frame" x="150" y="0.0" width="132" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="130" id="ADb-7C-hgx"/>
|
||||
</constraints>
|
||||
</switch>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
<size key="freeformSize" width="2000" height="2500"/>
|
||||
<size key="freeformSize" width="2000" height="5000"/>
|
||||
<connections>
|
||||
<outlet property="HdrStack" destination="dH7-Sy-EdJ" id="cJm-bj-Aqo"/>
|
||||
<outlet property="audioConfigSelector" destination="iZL-dA-jk9" id="Yja-os-o6g"/>
|
||||
<outlet property="audioConfigStack" destination="qnG-5F-2YY" id="kFX-VK-vuK"/>
|
||||
<outlet property="audioOnPcStack" destination="Bbr-Wj-Z75" id="c2K-3R-whg"/>
|
||||
@@ -1048,6 +1047,7 @@
|
||||
<outlet property="gyroModeStack" destination="kAD-mK-aP8" id="GvL-Yx-S2t"/>
|
||||
<outlet property="gyroSensitivitySlider" destination="3Ge-IB-PBj" id="Pdg-ke-KG3"/>
|
||||
<outlet property="gyroSensitivityStack" destination="T3L-Kz-2yA" id="iQS-ce-h0z"/>
|
||||
<outlet property="hdrStack" destination="dH7-Sy-EdJ" id="cJm-bj-Aqo"/>
|
||||
<outlet property="hdrSwitch" destination="wIq-fF-X8l" id="Ozz-h0-nJL"/>
|
||||
<outlet property="liftStreamViewForKeyboardSelector" destination="MM5-O0-vK3" id="tSC-Rp-Qfg"/>
|
||||
<outlet property="liftStreamViewForKeyboardStack" destination="mes-so-dfK" id="nXR-Ot-Ydf"/>
|
||||
@@ -1120,7 +1120,7 @@
|
||||
</items>
|
||||
</navigationBar>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-383.45323741007195" y="1500"/>
|
||||
<point key="canvasLocation" x="-503" y="1978"/>
|
||||
</scene>
|
||||
<!--Reveal View Controller-->
|
||||
<scene sceneID="rR7-ZT-bc7">
|
||||
@@ -1749,7 +1749,7 @@
|
||||
<image name="tray.full.fill" catalog="system" width="128" height="88"/>
|
||||
<image name="video.and.waveform" catalog="system" width="128" height="94"/>
|
||||
<systemColor name="linkColor">
|
||||
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="secondarySystemGroupedBackgroundColor">
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
@@ -1758,13 +1758,13 @@
|
||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemBrownColor">
|
||||
<color red="0.63529411764705879" green="0.51764705882352946" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.63529411759999999" green="0.51764705879999995" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemGray3Color">
|
||||
<color red="0.7803921568627451" green="0.7803921568627451" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.78039215689999997" green="0.78039215689999997" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
<systemColor name="systemTealColor">
|
||||
<color red="0.18823529411764706" green="0.69019607843137254" blue="0.7803921568627451" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<objects>
|
||||
<viewController id="dgh-JZ-Q7z" customClass="MainFrameViewController" sceneMemberID="viewController">
|
||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="Rtu-AT-Alw" customClass="AppCollectionView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="756"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.3333333432674408" green="0.3333333432674408" blue="0.3333333432674408" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="15" minimumInteritemSpacing="15" id="YcZ-cR-3tK">
|
||||
@@ -1585,7 +1585,6 @@
|
||||
</view>
|
||||
<size key="freeformSize" width="1200" height="2500"/>
|
||||
<connections>
|
||||
<outlet property="HdrStack" destination="kFw-d7-BTn" id="3aT-Gh-bDO"/>
|
||||
<outlet property="audioConfigSelector" destination="hfR-K8-Ti4" id="4La-bI-jLq"/>
|
||||
<outlet property="audioConfigStack" destination="Rld-CY-qzs" id="dmf-m8-sor"/>
|
||||
<outlet property="audioOnPcStack" destination="aud-Zf-37T" id="58Y-ri-ILs"/>
|
||||
@@ -1614,6 +1613,7 @@
|
||||
<outlet property="gyroModeStack" destination="5Ep-SA-IBh" id="2qw-Sb-8O6"/>
|
||||
<outlet property="gyroSensitivitySlider" destination="mHC-z4-AWQ" id="GHN-po-QYw"/>
|
||||
<outlet property="gyroSensitivityStack" destination="Nd5-0L-wpv" id="Qo0-Z3-gkm"/>
|
||||
<outlet property="hdrStack" destination="kFw-d7-BTn" id="3aT-Gh-bDO"/>
|
||||
<outlet property="hdrSwitch" destination="Kgb-YU-AFW" id="ksG-A4-HhS"/>
|
||||
<outlet property="liftStreamViewForKeyboardSelector" destination="TJx-6E-kgr" id="KnL-15-Q6G"/>
|
||||
<outlet property="liftStreamViewForKeyboardStack" destination="mgf-RQ-AVP" id="xH0-F0-dth"/>
|
||||
|
||||
@@ -248,8 +248,8 @@ static const float REFRESH_CYCLE = 2.0f;
|
||||
[NSLayoutConstraint activateConstraints:@[
|
||||
[lockIconView.centerXAnchor constraintEqualToAnchor:_iconBackgroundView.centerXAnchor constant:0],
|
||||
[lockIconView.centerYAnchor constraintEqualToAnchor:_iconBackgroundView.centerYAnchor constant:computerIconMonitorCenterYOffset],
|
||||
[lockIconView.widthAnchor constraintEqualToConstant:18.5*_sizeFactor],
|
||||
[lockIconView.heightAnchor constraintEqualToConstant:18.5*_sizeFactor]
|
||||
[lockIconView.widthAnchor constraintEqualToConstant:17.05*_sizeFactor],
|
||||
[lockIconView.heightAnchor constraintEqualToConstant:17.05*_sizeFactor]
|
||||
]];
|
||||
lockIconView.hidden = true;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22 34C26.4183 34 30 37.5817 30 42V48C30 52.4183 26.4183 56 22 56H16C11.7199 56 8.22523 52.6389 8.01074 48.4121L8 48V42C8 37.5817 11.5817 34 16 34H22ZM16 38C13.7909 38 12 39.7909 12 42V48L12.0049 48.2061C12.1087 50.2512 13.7488 51.8913 15.7939 51.9951L16 52H22L22.2061 51.9951C24.3194 51.8879 26 50.14 26 48V42C26 39.7909 24.2091 38 22 38H16Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M48 34C52.4183 34 56 37.5817 56 42V48C56 52.4183 52.4183 56 48 56H42C37.7199 56 34.2252 52.6389 34.0107 48.4121L34 48V42C34 37.5817 37.5817 34 42 34H48ZM42 38C39.7909 38 38 39.7909 38 42V48L38.0049 48.2061C38.1087 50.2512 39.7488 51.8913 41.7939 51.9951L42 52H48L48.2061 51.9951C50.3194 51.8879 52 50.14 52 48V42C52 39.7909 50.2091 38 48 38H42Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22 8C26.4183 8 30 11.5817 30 16V22C30 26.4183 26.4183 30 22 30H16C11.7199 30 8.22523 26.6389 8.01074 22.4121L8 22V16C8 11.5817 11.5817 8 16 8H22ZM16 12C13.7909 12 12 13.7909 12 16V22L12.0049 22.2061C12.1087 24.2512 13.7488 25.8913 15.7939 25.9951L16 26H22L22.2061 25.9951C24.3194 25.8879 26 24.14 26 22V16C26 13.7909 24.2091 12 22 12H16Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M48 8C52.4183 8 56 11.5817 56 16V22C56 26.4183 52.4183 30 48 30H42C37.7199 30 34.2252 26.6389 34.0107 22.4121L34 22V16C34 11.5817 37.5817 8 42 8H48ZM42 12C39.7909 12 38 13.7909 38 16V22L38.0049 22.2061C38.1087 24.2512 39.7488 25.8913 41.7939 25.9951L42 26H48L48.2061 25.9951C50.3194 25.8879 52 24.14 52 22V16C52 13.7909 50.2091 12 48 12H42Z" fill="black"/>
|
||||
<svg width="60" height="60" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 13.0002C9.433 13.0002 11 14.5672 11 16.5002V18.5002C10.9999 20.4331 9.43292 22.0002 7.5 22.0002H5.5C3.56708 22.0002 2.00012 20.4331 2 18.5002V16.5002C2 14.5672 3.567 13.0002 5.5 13.0002H7.5ZM5.5 15.0002C4.67157 15.0002 4 15.6718 4 16.5002V18.5002L4.00781 18.6535C4.08471 19.4098 4.72341 20.0002 5.5 20.0002H7.5L7.65332 19.9924C8.35923 19.9207 8.92041 19.3594 8.99219 18.6535L9 18.5002V16.5002C9 15.7236 8.40971 15.0848 7.65332 15.008L7.5 15.0002H5.5Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.5 13.0002C20.433 13.0002 22 14.5672 22 16.5002V18.5002C21.9999 20.4331 20.4329 22.0002 18.5 22.0002H16.5C14.5671 22.0002 13.0001 20.4331 13 18.5002V16.5002C13 14.5672 14.567 13.0002 16.5 13.0002H18.5ZM16.5 15.0002C15.6716 15.0002 15 15.6718 15 16.5002V18.5002L15.0078 18.6535C15.0847 19.4098 15.7234 20.0002 16.5 20.0002H18.5L18.6533 19.9924C19.3592 19.9207 19.9204 19.3594 19.9922 18.6535L20 18.5002V16.5002C20 15.7236 19.4097 15.0848 18.6533 15.008L18.5 15.0002H16.5Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.3604 2.61058C16.5319 1.43904 18.4319 1.43907 19.6035 2.61058L21.3711 4.37913C22.5424 5.55072 22.5426 7.44982 21.3711 8.62132L19.6035 10.3889C18.4319 11.5605 16.5319 11.5605 15.3604 10.3889L13.5928 8.62132C12.4214 7.44984 12.4215 5.55071 13.5928 4.37913L15.3604 2.61058ZM18.1895 4.02464C17.7989 3.63418 17.1649 3.63415 16.7744 4.02464L15.0068 5.79319C14.6166 6.18372 14.6165 6.81682 15.0068 7.20726L16.7744 8.97483L16.8506 9.04417C17.2171 9.34293 17.7468 9.34292 18.1133 9.04417L18.1895 8.97483L19.957 7.20726L20.0264 7.13108C20.3462 6.7384 20.3228 6.15918 19.957 5.79319L18.1895 4.02464Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 2.00023C9.433 2.00023 11 3.56723 11 5.50023V7.50023C10.9999 9.43312 9.43292 11.0002 7.5 11.0002H5.5C3.56708 11.0002 2.00012 9.43312 2 7.50023V5.50023C2 3.56723 3.567 2.00023 5.5 2.00023H7.5ZM5.5 4.00023C4.67157 4.00023 4 4.6718 4 5.50023V7.50023L4.00781 7.65355C4.08471 8.40984 4.72341 9.00023 5.5 9.00023H7.5L7.65332 8.99241C8.35924 8.92074 8.92041 8.35943 8.99219 7.65355L9 7.50023V5.50023C9 4.72357 8.40971 4.08485 7.65332 4.00804L7.5 4.00023H5.5Z" fill="black"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -14,6 +14,7 @@
|
||||
#import "OnScreenButtonState.h"
|
||||
#import "OSCProfilesManager.h"
|
||||
|
||||
|
||||
@interface LayoutOnScreenControls ()
|
||||
@end
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
#import "OnScreenButtonState.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
#define DEFAULT_TEMPLATE_NAME @"高级控件模板(Advanced widget templates)"
|
||||
#define DEFAULT_TEMPLATE_NAME1 @"控件模板 / Widget templates"
|
||||
#define DEFAULT_TEMPLATE_NAME2 @"旧版屏显控件 / Legacy on-screen controls"
|
||||
|
||||
/**
|
||||
This object contains information pertaining to any of the user created, custom on screen controller layout configurations, or 'profiles.' The object contains a 'name' property for easy reference, as well as an 'isSelected' property which is used to determine whether this particular custom OSC layout should show on screen during game stream view. Only one 'OSCProfile' is set to 'isSelected' at any given time. The object also contains an array of 'OnScreenButtonStates' which provides information that allows us to move and hide/unhide each of the 19 on screen buttons. Note that the 'buttonStates' property should contain an NSMutableArray of ENCODED 'OnScreenButtonState' objects. This allows us to save the 'OSCProfile' object to NSUserDefaults.
|
||||
|
||||
@@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* Lets the caller of this method know whether a profile with a given name already exists in persistent storage
|
||||
*/
|
||||
- (BOOL) profileNameAlreadyExist:(NSString*)name;
|
||||
- (BOOL) profileName:(NSString*) name alreadyExistIn:(NSMutableArray*)profiles;
|
||||
- (OSCProfile *) findProfileByName:(NSString*) name inProfileArray:(NSMutableArray*)profiles;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -142,7 +142,11 @@ static CGRect streamViewBounds;
|
||||
|
||||
- (void) importEncodedProfiles:(NSMutableArray* )profilesEncoded {
|
||||
NSMutableArray* targetProfiles = [_currentProfiles mutableCopy]; //_currentProfiles is availabled as long as getAllProfiles was called before calling this method (_currentProfiles avoids frequent accessing persisted data)
|
||||
if([self profileName:DEFAULT_TEMPLATE_NAME alreadyExistIn:targetProfiles] && targetProfiles.count > 1) [targetProfiles removeObjectAtIndex:1];
|
||||
OSCProfile* profile;
|
||||
profile = [self findProfileByName:DEFAULT_TEMPLATE_NAME1 inProfileArray:targetProfiles];
|
||||
if(profile && targetProfiles.count > 1) [targetProfiles removeObject:profile];
|
||||
profile = [self findProfileByName:DEFAULT_TEMPLATE_NAME2 inProfileArray:targetProfiles];
|
||||
if(profile && targetProfiles.count > 1) [targetProfiles removeObject:profile];
|
||||
if(targetProfiles.count > 0) [targetProfiles removeObjectAtIndex:0];
|
||||
NSMutableArray* localEncodedPofiles = [self encodedProfilesFromArray:targetProfiles];
|
||||
[profilesEncoded addObjectsFromArray:localEncodedPofiles];
|
||||
@@ -393,14 +397,14 @@ static CGRect streamViewBounds;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) profileName:(NSString*) name alreadyExistIn:(NSMutableArray*)profiles {
|
||||
- (OSCProfile *) findProfileByName:(NSString*) name inProfileArray:(NSMutableArray*)profiles {
|
||||
/* Iterate through the decoded profiles and return 'YES' if one of the profiles' 'name' properties equals the 'name' passed into this method */
|
||||
for (OSCProfile *profile in profiles) {
|
||||
if ([profile.name isEqualToString:name]) {
|
||||
return YES;
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (OnScreenButtonState *)unarchiveButtonStateEncoded:(NSData *)data {
|
||||
|
||||
@@ -361,7 +361,7 @@ import UIKit
|
||||
if self.shape == "round"{ // we'll make custom osc buttons round & smaller
|
||||
NSLayoutConstraint.activate([
|
||||
self.widthAnchor.constraint(equalToConstant: CGFloat(Int(60 * self.widthFactor / 2) * 2)),
|
||||
self.heightAnchor.constraint(equalToConstant: CGFloat(Int(60 * self.heightFactor / 2) * 2)),])
|
||||
self.heightAnchor.constraint(equalToConstant: CGFloat(Int(60 * self.widthFactor / 2) * 2)),])
|
||||
}
|
||||
if self.shape == "square" {
|
||||
NSLayoutConstraint.activate([
|
||||
@@ -587,7 +587,7 @@ import UIKit
|
||||
// illustrate offset distance in edit mode
|
||||
// let offsetSign = self.selfViewOnTheRight ? -1 : 1 // dprecated
|
||||
// let illlustrationPoint = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame)/4)
|
||||
self.crossMarkLayer.position = CGPointMake(CGRectGetMidX(self.stickBallLayer.frame), CGRectGetMidY(self.stickBallLayer.frame)-stickIndicatorOffset)
|
||||
self.stickBallLayer.position = CGPointMake(CGRectGetMidX(self.crossMarkLayer.frame), CGRectGetMidY(self.crossMarkLayer.frame)-stickIndicatorOffset)
|
||||
}
|
||||
CATransaction.commit()
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
NSMutableSet<NSNumber *> *pointerIdPool; //pre-defined pool of pointerIds.
|
||||
NSMutableSet<NSNumber *> *unassignedPointerIds;
|
||||
NSMutableSet *blacklistedTouches;
|
||||
bool doNotBlockTouchEvents;
|
||||
|
||||
NSMutableDictionary *pointerObjDict;
|
||||
|
||||
@@ -59,6 +60,7 @@
|
||||
}
|
||||
self->activePointerIds = [NSMutableSet set];
|
||||
self->blacklistedTouches = [NSMutableSet set];
|
||||
doNotBlockTouchEvents = true;
|
||||
|
||||
self->asyncNativeTouch = settings.asyncNativeTouchPriority.intValue != AsyncNativeTouchOff;
|
||||
|
||||
@@ -164,7 +166,8 @@
|
||||
//check if touch point is spawned on the left or right upper half screen edges, event to remote PC. this is for better handling in-stream slide gesture
|
||||
CGPoint initialPoint = [touch locationInView:self->streamView];
|
||||
if(initialPoint.y < slideGestureVerticalThreshold && (initialPoint.x < EDGE_TOLERANCE || initialPoint.x > screenWidthWithThreshold)) {
|
||||
[blacklistedTouches addObject:touchAddrObj];
|
||||
doNotBlockTouchEvents = false;
|
||||
// [blacklistedTouches addObject:touchAddrObj];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,8 +191,8 @@
|
||||
|
||||
- (void)sendTouchEvent:(UITouch*)touch withTouchtype:(uint8_t)touchType{
|
||||
//if(touchPointSpawnedAtUpperScreenEdge && touchType != LI_TOUCH_EVENT_UP) return; // we're done here. this touch event will not be sent to the remote PC. and this must be checked after coord selector finishes populating new relative coords, or the app will crash
|
||||
if([blacklistedTouches containsObject:@((uintptr_t)touch)]) return;
|
||||
|
||||
// if([blacklistedTouches containsObject:@((uintptr_t)touch)]) return;
|
||||
|
||||
CGPoint targetCoords;
|
||||
//NSLog(@"selecting coords: %d", touch.phase == UITouchPhaseMoved);
|
||||
// NSLog(@"excluded count: %d", (uint32_t)[excludedPointerIds count]);
|
||||
@@ -211,6 +214,7 @@
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
if (asyncNativeTouch) dispatch_async(dispatch_get_global_queue(touchDownQos, 0), ^{
|
||||
for (UITouch* touch in touches){
|
||||
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
|
||||
[self handleTouchDown:touch]; //generate & populate pointerId
|
||||
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
|
||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
|
||||
@@ -218,6 +222,7 @@
|
||||
});
|
||||
else{
|
||||
for (UITouch* touch in touches){
|
||||
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
|
||||
[self handleTouchDown:touch]; //generate & populate pointerId
|
||||
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
|
||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
|
||||
@@ -228,14 +233,16 @@
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
if (asyncNativeTouch) dispatch_async(dispatch_get_global_queue(touchMoveQos, 0), ^{
|
||||
for (UITouch* touch in touches){
|
||||
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
|
||||
if(self->activateCoordSelector) [self updatePointerObjInDict:touch];
|
||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_MOVE];
|
||||
if(self->doNotBlockTouchEvents) [self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_MOVE];
|
||||
[[self getPointerObjFromDict:touch] doesNeedResetCoords]; // execute the judging of doesReachBoundary for current pointer instance. (happens after the event is sent to Sunshine service)
|
||||
usleep(self->touchMoveEventIntervalUs);
|
||||
}
|
||||
});
|
||||
else {
|
||||
for (UITouch* touch in touches){
|
||||
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
|
||||
if(self->activateCoordSelector) [self updatePointerObjInDict:touch];
|
||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_MOVE];
|
||||
[[self getPointerObjFromDict:touch] doesNeedResetCoords]; // execute the judging of doesReachBoundary for current pointer instance. (happens after the event is sent to Sunshine service)
|
||||
@@ -248,14 +255,18 @@
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
if(asyncNativeTouch) dispatch_async(dispatch_get_global_queue(touchEndQos, 0), ^{
|
||||
for (UITouch* touch in touches){
|
||||
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
|
||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_UP]; //send touch event before remove pointerId
|
||||
[self removePointerId:touch]; //then remove pointerId
|
||||
if(self->activateCoordSelector) [self removePointerObjFromDict:touch];
|
||||
[self->blacklistedTouches removeObject:@((uintptr_t)touch)];
|
||||
//[self->blacklistedTouches removeObject:@((uintptr_t)touch)];
|
||||
}
|
||||
self->doNotBlockTouchEvents = true;
|
||||
//if(self->touchPointSpawnedAtUpperScreenEdge && [[event allTouches] count] == [touches count])
|
||||
});
|
||||
else{
|
||||
for (UITouch* touch in touches){
|
||||
// continue to the next loop if current touch is already captured by OSC. works only in regular native touch
|
||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_UP]; //send touch event before remove pointerId
|
||||
[self removePointerId:touch]; //then remove pointerId
|
||||
if(self->activateCoordSelector) [self removePointerObjFromDict:touch];
|
||||
@@ -293,7 +304,6 @@
|
||||
- (CGPoint)selectCoordsFor:(UITouch *)touch{
|
||||
NativeTouchPointer *pointer = [pointerObjDict objectForKey:@((uintptr_t)touch)];
|
||||
if(pointer == nil) return CGPointMake(0, 0);
|
||||
// NSLog(@"using relative Coords: intialX %f, divider loc %f", pointer.initialPoint.x, pointerVelocityDividerLocationByPoints);
|
||||
return pointer.useRelativeCoords ? pointer.latestRelativePoint : pointer.latestPoint;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- (void)userInteractionEnded;
|
||||
- (void)streamExitRequested;
|
||||
- (void)toggleStatsOverlay;
|
||||
- (void)localMousePointerMode;
|
||||
- (void)toggleMouseCapture;
|
||||
- (void)toggleMouseVisible;
|
||||
|
||||
@end
|
||||
|
||||
@@ -828,7 +828,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
[interactionDelegate toggleStatsOverlay];
|
||||
break;
|
||||
case UIKeyboardHIDUsageKeyboardM:
|
||||
[interactionDelegate localMousePointerMode];
|
||||
[interactionDelegate toggleMouseCapture];
|
||||
break;
|
||||
case UIKeyboardHIDUsageKeyboardC:
|
||||
[interactionDelegate toggleMouseVisible];
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<attribute name="settingsMenuMode" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="settingsMenuWidth" attributeType="Float" defaultValueString="370" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="showKeyboardToolbar" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="slideToSettingsDistance" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="slideToSettingsDistance" optional="YES" attributeType="Float" defaultValueString="0.2" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="slideToSettingsScreenEdge" optional="YES" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="NO" syncable="YES"/>
|
||||
<attribute name="statsOverlayEnabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||
<attribute name="statsOverlayLevel" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||
|
||||
@@ -1,29 +1,6 @@
|
||||
{
|
||||
"sourceLanguage" : "en",
|
||||
"strings" : {
|
||||
"\n1. From %@ edge, slide %d%% screen width to open settings menu\n\n2. From %@ edge, slide %d%% screen width to open command tool\n\n3. Back to Streaming from settings menu: slide from left edge\n\n4. Slide from upper 40%% of screen edge to avoid sending touch events to PC side" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "\n1. 展开设置菜单: 从%@边缘滑动%d%%屏幕宽度\n\n2. 打开命令工具: 从%@边缘滑动%d%%屏幕宽度\n\n3. 返回串流 / 收起设置菜单: 从左边缘滑动\n\n4. 从40%%上半边缘滑动避免触控事件影响PC端"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "\n1. 展開設定選單:從%@邊緣滑動%d%%的螢幕寬度\n\n2. 開啟指令工具:從%@邊緣滑動%d%%的螢幕寬度\n\n3. 從設定選單返回串流:從左側邊緣滑動\n\n4. 從螢幕邊緣上方40%%處滑動以避免將觸控事件傳送到電腦端"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "\n1. 展開設定選單:從%@邊緣滑動%d%%的螢幕寬度\n\n2. 開啟指令工具:從%@邊緣滑動%d%%的螢幕寬度\n\n3. 從設定選單返回串流:從左側邊緣滑動\n\n4. 從螢幕邊緣上方40%%處滑動以避免將觸控事件傳送到電腦端"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"\nHost processing latency min/max/avg: %.1f/%.1f/%.1f ms" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -248,7 +225,7 @@
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"state" : "translated",
|
||||
"value" : "\n\n您裝置的遠端工作階段連線被阻擋。在此網路上連線時,串流可能無法運作。"
|
||||
}
|
||||
},
|
||||
@@ -306,7 +283,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"[ Open on-screen widget tool ]" : {
|
||||
"[ On-screen widget tool ]" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
@@ -329,7 +306,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"[ Switch among on-screen widget profiles ]" : {
|
||||
"[ Switch on-screen widget profile ]" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
@@ -1474,6 +1451,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"emulatedControllerTypeStackDoc" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/uscwmv3vz8g30rmk?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bz6ggagp0ly4loq3?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bz6ggagp0ly4loq3?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bz6ggagp0ly4loq3?singleDoc#"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"emulatedControllerTypeStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sunshine emulates game controller via VigemBus, which support DS4 & Xbox360. \n\n- Xbox360 does not support gyro.\n\n- When “both” is selected, the app will map built-in gyro as player0 & external game controller as player1"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sunshine 通过 VigemBus 模拟游戏手柄,支持 DS4 和 Xbox 360。\n\n- Xbox 360 不支持陀螺仪。\n\n- 当选择“同时映射”时,app会将内置陀螺仪映射为玩家0,外接手柄映射为玩家1。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sunshine 透過 VigemBus 模擬遊戲控制器,支援 DS4 和 Xbox 360。\n\n- Xbox 360 不支援陀螺儀。\n\n- 當選擇「同時映射」時,app 會將內建陀螺儀對應為玩家0,外接控制器對應為玩家1。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sunshine 透過 VigemBus 模擬遊戲控制器,支援 DS4 和 Xbox 360。\n\n- Xbox 360 不支援陀螺儀。\n\n- 當選擇「同時映射」時,app 會將內建陀螺儀對應為玩家0,外接控制器對應為玩家1。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Enter a new command and alias" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -1664,6 +1699,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"externalDisplayModeStackDoc" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bu3hki4pezy93g6r?singleDoc# "
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/cqbse6t4o6f9hil1?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/cqbse6t4o6f9hil1?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/cqbse6t4o6f9hil1?singleDoc#"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"externalDisplayModeStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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 — 切换鼠标指针可见性"
|
||||
}
|
||||
},
|
||||
"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 — 切換滑鼠指標可見性"
|
||||
}
|
||||
},
|
||||
"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 — 切換滑鼠指標可見性"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Failed to import profiles" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -1779,6 +1872,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"firstLaunchTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "\n1. From %@ edge, slide %d%% screen width to open settings menu\n\n2. From %@ edge, slide %d%% screen width to open toolbox menu\n\n3. Slide from top 40%% of screen edge to avoid sending touch events to PC side"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "\n1. 展开设置菜单: 从%@边缘滑动%d%%屏幕宽度\n\n2. 打开工具箱菜单: 从%@边缘滑动%d%%屏幕宽度\n\n3. 从40%%上半边缘滑动避免触控事件影响PC端"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "\n1. 展開設定選單:從%@邊緣滑動%d%%的螢幕寬度\n\n2. 開啟工具箱選單:從%@邊緣滑動%d%%的螢幕寬度\n\n3. 從螢幕邊緣上方40%%處滑動以避免將觸控事件傳送到電腦端"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "\n1. 展開設定選單:從%@邊緣滑動%d%%的螢幕寬度\n\n2. 開啟工具箱選單:從%@邊緣滑動%d%%的螢幕寬度\n\n3. 從螢幕邊緣上方40%%處滑動以避免將觸控事件傳送到電腦端"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"FPS: %5.2f Network dropped frames: %.2f%% Network latency: %@" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -1894,6 +2016,93 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"gyroModeStackDoc" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/uscwmv3vz8g30rmk?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bz6ggagp0ly4loq3?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bz6ggagp0ly4loq3?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bz6ggagp0ly4loq3?singleDoc#"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"gyroModeStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- Gyro support for external game controllers is available on iOS 14+.\n\n- If a session is started with gyro mode disabled, it cannot be enabled during streaming."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 外接手柄的陀螺仪支持适用于 iOS 14 及以上版本。\n\n- 如果在启动会话时关闭了陀螺仪模式,则在串流过程中无法热切换开启。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 外接控制器的陀螺儀支援適用於 iOS 14 以上版本。\n\n- 若在啟動階段時未啟用陀螺儀模式,則無法在串流過程中熱切換開啟。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 外接控制器的陀螺儀支援適用於 iOS 14 以上版本。\n\n- 若在啟動階段時未啟用陀螺儀模式,則無法在串流過程中熱切換開啟。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"hdrStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "HDR video stream decoding is not supported on current device"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "当前系统不支持HDR视频流解码"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "當前裝置不支援HDR視訊串流解碼"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "當前裝置不支援HDR視訊串流解碼"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Height" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -2239,6 +2448,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"localMousePointerModeStackDoc" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/zdf5l29s3vohs6iq?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/yfao3s5bhl93rs01?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/yfao3s5bhl93rs01?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/yfao3s5bhl93rs01?singleDoc#"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"localMousePointerModeStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- Captured: mouse pointer captured & limited within app window\n\n- Hidden: local mouse pointer is hidden.\n\n- Visible: local mouse pointer is visible to reduce the feeling of latency\n\nDo not select hidden/visible for any game play that uses mouse for camera control."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 被窗口捕获:鼠标指针被限制在app窗口内。\n\n- 隐藏:不显示本地鼠标指针。\n\n- 可见:显示iOS本地鼠标指针,减少延迟感。\n\n请勿使用 隐藏/可见 模式操作任何使用鼠标控制视角的游戏。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 被視窗捕獲:滑鼠游標被限制在應用程式視窗內。\n\n- 隱藏:不顯示本機滑鼠游標。\n\n- 可見:顯示 iOS 本機滑鼠游標,減少延遲感。\n\n請勿使用「隱藏/可見」模式操作任何需用滑鼠控制視角的遊戲。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 被視窗捕獲:滑鼠游標被限制在應用程式視窗內。\n\n- 隱藏:不顯示本機滑鼠游標。\n\n- 可見:顯示 iOS 本機滑鼠游標,減少延遲感。\n\n請勿使用「隱藏/可見」模式操作任何需用滑鼠控制視角的遊戲。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Manual_Add_Host_Fail" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -2302,7 +2569,7 @@
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"state" : "translated",
|
||||
"value" : "无法执行网络测试. 请检查网络连接后重试."
|
||||
}
|
||||
},
|
||||
@@ -2429,7 +2696,7 @@
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"state" : "translated",
|
||||
"value" : "网络测试成功. 如果仍然无法连接远程主机, 请检查主机端防火墙设置."
|
||||
}
|
||||
},
|
||||
@@ -2769,6 +3036,81 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Online Documentation" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "在线支持文档"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "線上支援文件"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "線上支援文件"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"onScreenWidgetStackDoc" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/zrg0ga93avz4s747?singleDoc# "
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/zrg0ga93avz4s747?singleDoc# "
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/zrg0ga93avz4s747?singleDoc# "
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"onScreenWidgetStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- VoidLink supports rich, powerful custom on screen widgets including keyboard buttons, gamepad button & joysticks, mouse touchpad & button. Check online document for detail.\n\n- Multi-finger tap gesture is available for launching widget layout tool during streaming."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- VoidLink具备丰富而强大的自定义屏显控件,类型包括:键盘按键、手柄按键和摇杆、鼠标触摸板和按键等。详见在线文档。 \n\n- 可通过多指轻按手势在串流时打开控件布局工具。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。\n\n- 可透過多指輕點手勢,在串流時開啟控制元件佈局工具。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。\n\n- 可透過多指輕點手勢,在串流時開啟控制元件佈局工具。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Open widget tool in streaming by:\nSliding from %@ screen edge to open cmd tool.\nOr tap %d fingers on stream view, number of fingers required:" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -2792,6 +3134,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"optimizeGamesStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Recommended to keep this option enabled. Sunshine relies on it to load preset parameters."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sunshine 依据该选项状态决定是否加载一些预置参数,建议保持开启。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sunshine 依據此選項的狀態決定是否載入一些預設參數,建議保持開啟。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sunshine 依據此選項的狀態決定是否載入一些預設參數,建議保持開啟。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Options" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -2907,6 +3278,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"pipStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- Enable auto picture-in-picture by switching on Settings -> Multitasking & Gestures -> Start PiP Automatically.\n\n- PiP can be manually started in toolbox menu.\n\n- PiP connection timeout is also defined by “Background Session” settings in “Others” section\n\n-PiP is available for iOS15+"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- App切后台时自动开启画中画, 需要打开 iOS 设置-> 多任务与手势 -> 自动开启画中画。\n\n- 画中画可在工具箱菜单中手动开启。\n\n- 画中画时长由 “其他 -> 后台会话” 设置项控制\n\n- 仅 iOS15+ 支持画中画。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- App 切到背景時會自動啟用子母畫面,需開啟 iOS 「設定」→「多工與手勢」→「自動啟用子母畫面」。\n\n- 子母畫面也可透過工具箱選單手動啟用。\n\n- 子母畫面顯示時長由「其他」→「背景執行」設定項目控制。\n\n- 子母畫面功能自 iOS 15 起支援。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- App 切到背景時會自動啟用子母畫面,需開啟 iOS 「設定」→「多工與手勢」→「自動啟用子母畫面」。\n\n- 子母畫面也可透過工具箱選單手動啟用。\n\n- 子母畫面顯示時長由「其他」→「背景執行」設定項目控制。\n\n- 子母畫面功能自 iOS 15 起支援。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Pofiles imported" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -3782,6 +4182,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"slideToSettingsDistanceStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "A sufficient sliding distance ensures the menu is not triggered by unintentional touches."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "手势所要求的滑动距离, 可有效防止因误触展开菜单。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "手勢所需的滑動距離,可有效避免因誤觸而展開選單。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "手勢所需的滑動距離,可有效避免因誤觸而展開選單。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Slow connection to PC, Reduce your bitrate" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -3805,6 +4234,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"softKeyboardGestureStackDoc" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/rgc9if4xrf352555?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/ok4egvu4lt37wc1f?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/ok4egvu4lt37wc1f?singleDoc#"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/ok4egvu4lt37wc1f?singleDoc#"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"softKeyboardGestureStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Soft keyboard gesture is able to locate the remote typing area by the lowest touch point of your tap gesture to lift the stream view to proper height.\nCheck the online document for details."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "软键盘手势能够根据位置最低的触点定位远程文字输入位置,并将串流视图提升到合适高度。\n详见在线文档。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "軟體鍵盤手勢可根據最低位置的觸控點,定位遠端文字輸入的位置,並將串流畫面提升至適當高度。\n詳情請參閱線上說明文件。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "軟體鍵盤手勢可根據最低位置的觸控點,定位遠端文字輸入的位置,並將串流畫面提升至適當高度。\n詳情請參閱線上說明文件。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Stereo (surround sound available for iOS18+)" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -3851,6 +4338,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"supportLink" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/dhmg3h27ls8mwt4a?singleDoc# 《About VoidLink》"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/fdi4rxkxykhl5zpp?singleDoc# 《关于 VoidLink》"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/fdi4rxkxykhl5zpp?singleDoc# 《关于 VoidLink》"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/fdi4rxkxykhl5zpp?singleDoc# 《关于 VoidLink》"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Tap %d Fingers to Change OSC Layout in Stream View" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@@ -4266,13 +4782,42 @@
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 觸控板:拖曳方式與 Windows 筆記型電腦觸控板完全相同。快速輕點兩下,從第二次輕點開始進入拖曳模式。\n\n- 原生觸控:即多點觸控傳遞,macOS 不支援。\n\n- 絕對觸控:在 macOS 上提供類似觸控螢幕的體驗。"
|
||||
"value" : "- 觸控板:拖曳方式與 Windows 筆記型電腦觸控板完全相同。快速輕點兩下,從第二次輕點開始進入拖曳模式。\n\n- 多点觸控:macOS 不支援。\n\n- 單點滑鼠:在 macOS 上提供類似觸控螢幕的體驗。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "- 觸控板:拖曳方式與 Windows 筆記型電腦觸控板完全相同。快速輕點兩下,從第二次輕點開始進入拖曳模式。\n\n- 原生觸控:即多點觸控傳遞,macOS 不支援。\n\n- 絕對觸控:在 macOS 上提供類似觸控螢幕的體驗。"
|
||||
"value" : "- 觸控板:拖曳方式與 Windows 筆記型電腦觸控板完全相同。快速輕點兩下,從第二次輕點開始進入拖曳模式。\n\n- 多点觸控:macOS 不支援。\n\n- 單點滑鼠:在 macOS 上提供類似觸控螢幕的體驗。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"unlockDisplayOrientationStackTip" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "iPad is unable to lock run-time display orientation due to stage manager support. If necessary please manually lock display orientation."
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "为支持台前调度,iPad无法自动锁定显示方向。如有必要请手动锁定。"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "為支援幕前調度,iPad 無法自動鎖定顯示方向。如有需要,請手動鎖定。"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "為支援幕前調度,iPad 無法自動鎖定顯示方向。如有需要,請手動鎖定。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -79,8 +79,8 @@ static UIImage* noImage;
|
||||
#else
|
||||
// Rasterizing the cell layer increases rendering performance by quite a bit
|
||||
// but we want it unrasterized for tvOS where it must be scaled.
|
||||
self.layer.shouldRasterize = YES;
|
||||
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
self.layer.shouldRasterize = NO;
|
||||
// self.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
|
||||
if (@available(iOS 13.4.1, *)) {
|
||||
// Allow the button style to change when moused over
|
||||
|
||||
+26
-15
@@ -81,9 +81,8 @@
|
||||
- (void) reloadOnScreenWidgetViews {
|
||||
NSLog(@"reloadOnScreenWidgets %f", CACurrentMediaTime());
|
||||
OnScreenWidgetView.editMode = true;
|
||||
[self->selectedWidgetView.stickBallLayer removeFromSuperlayer];
|
||||
[self->selectedWidgetView.crossMarkLayer removeFromSuperlayer];
|
||||
|
||||
[self clearStickIndicator];
|
||||
|
||||
for (UIView *subview in self.view.subviews) {
|
||||
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
||||
[subview removeFromSuperview];
|
||||
@@ -168,7 +167,7 @@
|
||||
[profilesManager saveProfileWithName:@"Default" andButtonLayers:self.layoutOSC.OSCButtonLayers];
|
||||
[profilesManager importDefaultTemplates];
|
||||
}*/
|
||||
if (![profilesManager profileName:DEFAULT_TEMPLATE_NAME alreadyExistIn:allProfiles]){
|
||||
if (![profilesManager findProfileByName:DEFAULT_TEMPLATE_NAME1 inProfileArray:allProfiles]){
|
||||
[profilesManager importDefaultTemplates];
|
||||
}
|
||||
|
||||
@@ -239,6 +238,11 @@
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(OSCLayoutChanged) name:@"OSCLayoutChanged" object:nil]; // used to notifiy this view controller that the user made a change to the OSC layout so that the VC can either fade in or out its 'Undo button' which will signify to the user whether there are any OSC layout changes to undo
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationWillResignActive:)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:nil];
|
||||
|
||||
OnScreenWidgetView.editMode = true;
|
||||
[self handleMissingToolBarIcon:toolbarRootView];
|
||||
@@ -247,6 +251,11 @@
|
||||
|
||||
#pragma mark - Class Helper Functions
|
||||
|
||||
- (void)applicationWillResignActive:(NSNotification *)notification {
|
||||
[self saveTapped:nil];
|
||||
}
|
||||
|
||||
|
||||
/* fades the 'Undo Button' in or out depending on whether the user has any OSC layout changes to undo */
|
||||
- (void) OSCLayoutChanged {
|
||||
if ([self.layoutOSC.layoutChanges count] > 0) {
|
||||
@@ -617,7 +626,7 @@
|
||||
[savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||
[self.oscProfilesTableViewController profileViewRefresh]; // execute this will reset layout in OSC tool!
|
||||
}]];
|
||||
[self presentViewController:savedAlertController animated:YES completion:nil];
|
||||
if(sender) [self presentViewController:savedAlertController animated:YES completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,6 +654,11 @@
|
||||
label.numberOfLines = 1;
|
||||
}
|
||||
|
||||
- (void)clearStickIndicator{
|
||||
[self->selectedWidgetView.stickBallLayer removeFromSuperlayer];
|
||||
[self->selectedWidgetView.crossMarkLayer removeFromSuperlayer];
|
||||
}
|
||||
|
||||
- (void)widgetViewTapped: (NSNotification *)notification{
|
||||
//self.undoButton.alpha = selectedWidgetView.layoutChanges.count>1 && !CGPointEqualToPoint(selectedWidgetView.layoutChanges.lastObject.CGPointValue, selectedWidgetView.initialCenter)? 1.0 : 0.3;
|
||||
|
||||
@@ -653,8 +667,7 @@
|
||||
|
||||
OnScreenWidgetView* widgetView = (OnScreenWidgetView* )notification.object;
|
||||
|
||||
[self->selectedWidgetView.stickBallLayer removeFromSuperlayer];
|
||||
[self->selectedWidgetView.crossMarkLayer removeFromSuperlayer];
|
||||
[self clearStickIndicator];
|
||||
self->widgetViewSelected = true;
|
||||
self->controllerLayerSelected = false;
|
||||
self->selectedWidgetView = widgetView;
|
||||
@@ -695,8 +708,7 @@
|
||||
}
|
||||
if(showStickIndicatorOffsetStack){
|
||||
// illustrating the indicator offset,
|
||||
[selectedWidgetView.stickBallLayer removeFromSuperlayer];
|
||||
[selectedWidgetView.crossMarkLayer removeFromSuperlayer];
|
||||
[self clearStickIndicator];
|
||||
selectedWidgetView.touchBeganLocation = CGPointMake(CGRectGetWidth(selectedWidgetView.frame)/2, CGRectGetHeight(selectedWidgetView.frame)/4);
|
||||
[selectedWidgetView showStickIndicator];// this will create the indicator CAShapeLayers
|
||||
[self.stickIndicatorOffsetSlider setValue:self->selectedWidgetView.stickIndicatorOffset];
|
||||
@@ -733,8 +745,7 @@
|
||||
- (void)legacyOscLayerTapped: (NSNotification *)notification{
|
||||
[self enableCommonWidgetTools];
|
||||
CALayer* controllerLayer = (CALayer* )notification.object;
|
||||
[self->selectedWidgetView.stickBallLayer removeFromSuperlayer];
|
||||
[self->selectedWidgetView.crossMarkLayer removeFromSuperlayer];
|
||||
[self clearStickIndicator];
|
||||
self->widgetViewSelected = false;
|
||||
self->selectedWidgetView = nil;
|
||||
|
||||
@@ -1109,6 +1120,9 @@
|
||||
}
|
||||
|
||||
- (void) presentProfilesTableView{
|
||||
[self saveTapped:nil];
|
||||
[self clearStickIndicator];
|
||||
selectedWidgetView = nil;
|
||||
UIStoryboard *storyboard;
|
||||
BOOL isIPhone = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone);
|
||||
if (isIPhone) {
|
||||
@@ -1133,8 +1147,6 @@
|
||||
|
||||
self.widgetPanelStack.hidden = YES;
|
||||
|
||||
[self->selectedWidgetView.stickBallLayer removeFromSuperlayer];
|
||||
[self->selectedWidgetView.crossMarkLayer removeFromSuperlayer];
|
||||
_oscProfilesTableViewController.currentOSCButtonLayers = self.layoutOSC.OSCButtonLayers;
|
||||
|
||||
[self presentViewController:_oscProfilesTableViewController animated:YES completion:nil];
|
||||
@@ -1241,8 +1253,7 @@
|
||||
if(!isToolbarHidden && self->selectedWidgetView != nil && [self layerIsOverlappingWithTrashcanButton:selectedWidgetView.layer]){
|
||||
[self->selectedWidgetView removeFromSuperview];
|
||||
[self.OnScreenWidgetViews removeObject:self->selectedWidgetView];
|
||||
[selectedWidgetView.stickBallLayer removeFromSuperlayer];
|
||||
[selectedWidgetView.crossMarkLayer removeFromSuperlayer];
|
||||
[self clearStickIndicator];
|
||||
[selectedWidgetView.buttonDownVisualEffectLayer removeFromSuperlayer];
|
||||
}
|
||||
|
||||
|
||||
@@ -1133,8 +1133,8 @@ static NSMutableSet* hostList;
|
||||
if(self.settingsExpandedInStreamView) [revealController buttonsInStreaming];
|
||||
else [revealController buttonsNotInStreaming];
|
||||
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
TemporarySettings* currentSettings = [dataMan getSettings];
|
||||
// DataManager* dataMan = [[DataManager alloc] init];
|
||||
// TemporarySettings* currentSettings = [dataMan getSettings];
|
||||
|
||||
[streamFrameViewController setUserInteractionEnabledForStreamView:!_settingsExpandedInStreamView || position == FrontViewPositionLeft];
|
||||
[settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.resolutionStack];
|
||||
@@ -1269,6 +1269,19 @@ static NSMutableSet* hostList;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isFirstLaunch {
|
||||
NSString *key = @"appHasLaunchedBefore";
|
||||
BOOL launchedBefore = [[NSUserDefaults standardUserDefaults] boolForKey:key];
|
||||
|
||||
if (!launchedBefore) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:key];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize]; // iOS 12+ 可省略
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (bool)isIPhone{
|
||||
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone);
|
||||
}
|
||||
@@ -1347,7 +1360,7 @@ static NSMutableSet* hostList;
|
||||
button.tintColor = [ThemeManager appPrimaryColor];
|
||||
[button setTitleColor:button.tintColor forState:UIControlStateNormal];
|
||||
|
||||
button.frame = CGRectMake(0, 0, buttonHeight, buttonHeight);
|
||||
button.frame = CGRectMake(0, 0, buttonHeight*1.3, buttonHeight*1.05);
|
||||
|
||||
// 添加点击事件
|
||||
[button addTarget:self action:@selector(helpButtonTapped) forControlEvents:UIControlEventTouchUpInside];
|
||||
@@ -1774,6 +1787,7 @@ static NSMutableSet* hostList;
|
||||
//[self simulateSettingsButtonPress]; //force reload resolution table in the setting
|
||||
//[self simulateSettingsButtonPress];
|
||||
[self updateResolutionAccordingly];
|
||||
if([self isFirstLaunch])[self helpButtonTapped];
|
||||
}
|
||||
|
||||
|
||||
@@ -2114,7 +2128,7 @@ static NSMutableSet* hostList;
|
||||
if(gesture.state == UIGestureRecognizerStateBegan){
|
||||
if(locationInView.x < 30) {
|
||||
snapshot = [[UIView alloc] init];
|
||||
snapshot.backgroundColor = [ThemeManager appPrimaryColor];
|
||||
snapshot.backgroundColor = [UIColor systemBlueColor];
|
||||
screenHeight = [UIScreen mainScreen].bounds.size.height;
|
||||
snapshot.frame = CGRectMake(locationInSuperView.x,0, 2, screenHeight);
|
||||
[self.revealViewController.view addSubview:snapshot];
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *codecStack;
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *yuv444Stack;
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *pipStack;
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *HdrStack;
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *hdrStack;
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *framepacingStack;
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *reverseMouseWheelDirectionStack;
|
||||
@property (strong, nonatomic) IBOutlet UIStackView *citrixX1MouseStack;
|
||||
@@ -136,7 +136,7 @@
|
||||
- (void)saveSettings;
|
||||
+ (bool)isLandscapeNow;
|
||||
- (void)updateResolutionTable;
|
||||
- (void)widget:(UISlider*)widget setEnabled:(bool)enabled;
|
||||
- (void)widget:(UIView*)widget setEnabled:(bool)enabled;
|
||||
- (void)updateTheme;
|
||||
- (void)hideDynamicLabelsWhenOverlapped:(UIView* )view;
|
||||
- (void)setHidden:(BOOL)hidden forStack:(UIStackView* )stack;
|
||||
|
||||
@@ -516,14 +516,15 @@ BOOL isCustomResolution(CGSize res) {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[videoSection setSectionWithIcon:[UIImage systemImageNamed:@"waveform"] andSize:20];
|
||||
}
|
||||
[self addSetting:self.resolutionStack ofId:@"resolutionStack" withInfoTag:YES withDynamicLabel:YES to:videoSection];
|
||||
[self addSetting:self.resolutionStack ofId:@"resolutionStack" withInfoTag:NO withDynamicLabel:YES to:videoSection];
|
||||
[self addSetting:self.fpsStack ofId:@"fpsStack" withInfoTag:NO withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.bitrateStack ofId:@"bitrateStack" withInfoTag:YES withDynamicLabel:YES to:videoSection];
|
||||
[self addSetting:self.framepacingStack ofId:@"framepacingStack" withInfoTag:NO withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.codecStack ofId:@"codecStack" withInfoTag:NO withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.HdrStack ofId:@"HdrStack" withInfoTag:NO withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.hdrStack ofId:@"hdrStack" withInfoTag:![self hdrSupported] withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.yuv444Stack ofId:@"yuv444Stack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.pipStack ofId:@"pipStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.pipStack ofId:@"pipStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.frameQueueSizeStack ofId:@"frameQueueSizeStack" withInfoTag:NO withDynamicLabel:NO to:videoSection];
|
||||
[self addSetting:self.renderingBackendStack ofId:@"renderingBackendStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
|
||||
|
||||
@@ -600,10 +601,9 @@ BOOL isCustomResolution(CGSize res) {
|
||||
[self addSetting:self.unlockDisplayOrientationStack ofId:@"unlockDisplayOrientationStack" withInfoTag:YES withDynamicLabel:NO to:otherSection];
|
||||
[self addSetting:self.backgroundSessionTimerStack ofId:@"backgroundSessionTimerStack" withInfoTag:NO withDynamicLabel:YES to:otherSection];
|
||||
[self addSetting:self.optimizeGamesStack ofId:@"optimizeGamesStack" withInfoTag:YES withDynamicLabel:NO to:otherSection];
|
||||
[self addSetting:self.multiControllerStack ofId:@"multiControllerStack" withInfoTag:YES withDynamicLabel:NO to:otherSection];
|
||||
[self addSetting:self.softKeyboardToolbarStack ofId:@"softKeyboardToolbarStack" withInfoTag:YES withDynamicLabel:NO to:otherSection];
|
||||
[self addSetting:self.multiControllerStack ofId:@"multiControllerStack" withInfoTag:NO withDynamicLabel:NO to:otherSection];
|
||||
[self addSetting:self.softKeyboardToolbarStack ofId:@"softKeyboardToolbarStack" withInfoTag:NO withDynamicLabel:NO to:otherSection];
|
||||
[self addSetting:self.performanceGraphStack ofId:@"performanceGraphStack" withInfoTag:YES withDynamicLabel:NO to:otherSection];
|
||||
|
||||
[otherSection addToParentStack:_parentStack];
|
||||
[otherSection setExpanded:YES];
|
||||
|
||||
@@ -614,7 +614,7 @@ BOOL isCustomResolution(CGSize res) {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[experimentalSection setSectionWithIcon:[UIImage imageNamed:@"flask"] andSize:20];
|
||||
}
|
||||
[self addSetting:self.touchMoveEventIntervalStack ofId:@"touchMoveEventIntervalStack" withInfoTag:YES withDynamicLabel:YES to:experimentalSection];
|
||||
[self addSetting:self.touchMoveEventIntervalStack ofId:@"touchMoveEventIntervalStack" withInfoTag:NO withDynamicLabel:YES to:experimentalSection];
|
||||
[experimentalSection addToParentStack:_parentStack];
|
||||
[experimentalSection setExpanded:YES];
|
||||
}
|
||||
@@ -950,13 +950,14 @@ BOOL isCustomResolution(CGSize res) {
|
||||
[stack addSubview:button];
|
||||
[NSLayoutConstraint activateConstraints:@[
|
||||
[button.trailingAnchor constraintEqualToAnchor:stack.trailingAnchor constant:-4],
|
||||
[button.bottomAnchor constraintEqualToAnchor:stack.arrangedSubviews[0].bottomAnchor constant:0],
|
||||
[button.centerYAnchor constraintEqualToAnchor:stack.arrangedSubviews[0].centerYAnchor constant:0],
|
||||
]];
|
||||
}
|
||||
|
||||
- (void)infoButtonTapped:(UIButton* )sender{
|
||||
|
||||
NSString* tipText = @"";
|
||||
NSString* onlineDocLink = @"";
|
||||
bool showOnlineDocAction = false;
|
||||
tipText = sender.superview.accessibilityIdentifier;
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"bitrateStack"]){
|
||||
@@ -966,6 +967,7 @@ BOOL isCustomResolution(CGSize res) {
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"yuv444Stack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"yuv444StackTip"];
|
||||
showOnlineDocAction = true;
|
||||
onlineDocLink = @"https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/koeimmrvt4o17auc?singleDoc#";
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"touchModeStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"touchModeStackTip"];
|
||||
@@ -979,10 +981,58 @@ BOOL isCustomResolution(CGSize res) {
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"pointerVelocityFactorStackTip"];
|
||||
showOnlineDocAction = true;
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"hdrStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"hdrStackTip"];
|
||||
showOnlineDocAction = false;
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"pipStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"pipStackTip"];
|
||||
showOnlineDocAction = false;
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"softKeyboardGestureStack" ]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"softKeyboardGestureStackTip"];
|
||||
showOnlineDocAction = true;
|
||||
onlineDocLink = [LocalizationHelper localizedStringForKey:@"softKeyboardGestureStackDoc"];
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"slideToSettingsDistanceStack" ]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"slideToSettingsDistanceStackTip"];
|
||||
showOnlineDocAction = false;
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"unlockDisplayOrientationStack" ]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"unlockDisplayOrientationStackTip"];
|
||||
showOnlineDocAction = false;
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"optimizeGamesStack" ]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"optimizeGamesStackTip"];
|
||||
showOnlineDocAction = false;
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"localMousePointerModeStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"localMousePointerModeStackTip"];
|
||||
showOnlineDocAction = true;
|
||||
onlineDocLink = [LocalizationHelper localizedStringForKey:@"localMousePointerModeStackDoc"];
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"onScreenWidgetStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"onScreenWidgetStackTip"];
|
||||
showOnlineDocAction = true;
|
||||
onlineDocLink = [LocalizationHelper localizedStringForKey:@"onScreenWidgetStackDoc"];
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"externalDisplayModeStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"externalDisplayModeStackTip"];
|
||||
showOnlineDocAction = true;
|
||||
onlineDocLink = [LocalizationHelper localizedStringForKey:@"externalDisplayModeStackDoc"];
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"emulatedControllerTypeStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"emulatedControllerTypeStackTip"];
|
||||
showOnlineDocAction = true;
|
||||
onlineDocLink = [LocalizationHelper localizedStringForKey:@"emulatedControllerTypeStackDoc"];
|
||||
}
|
||||
if([sender.superview.accessibilityIdentifier isEqualToString: @"gyroModeStack"]){
|
||||
tipText = [LocalizationHelper localizedStringForKey:@"gyroModeStackTip"];
|
||||
showOnlineDocAction = true;
|
||||
onlineDocLink = [LocalizationHelper localizedStringForKey:@"gyroModeStackDoc"];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Tips"] message: [LocalizationHelper localizedStringForKey:@"%@", tipText] preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
|
||||
@@ -1005,7 +1055,7 @@ BOOL isCustomResolution(CGSize res) {
|
||||
UIAlertAction *readInstruction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Online Documentation"]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action){
|
||||
NSURL *url = [NSURL URLWithString:@"https://b23.tv/J8qEXOr"];
|
||||
NSURL *url = [NSURL URLWithString:onlineDocLink];
|
||||
if ([[UIApplication sharedApplication] canOpenURL:url]) {
|
||||
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
|
||||
}
|
||||
@@ -1280,9 +1330,9 @@ BOOL isCustomResolution(CGSize res) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10)) {
|
||||
if (![self hdrSupported]) {
|
||||
[self.hdrSwitch setOn:NO];
|
||||
[self.hdrSwitch setEnabled:NO];
|
||||
[self widget:self.hdrSwitch setEnabled:NO];
|
||||
}
|
||||
else {
|
||||
[self.hdrSwitch setOn:currentSettings.enableHdr];
|
||||
@@ -1324,6 +1374,7 @@ BOOL isCustomResolution(CGSize res) {
|
||||
[self emulatedControllerTypeChanged:self.emulatedControllerTypeSelector];
|
||||
|
||||
|
||||
|
||||
[self.audioOnPcSwitch setOn:currentSettings.playAudioOnPC];
|
||||
_lastSelectedResolutionIndex = resolution;
|
||||
[self.resolutionSelector setSelectedSegmentIndex:resolution];
|
||||
@@ -1544,7 +1595,7 @@ BOOL isCustomResolution(CGSize res) {
|
||||
[_softKeyboardGestureSelector setSelectedSegmentIndex:_softKeyboardGestureSelector.selectedSegmentIndex-1];
|
||||
}
|
||||
for (NSInteger i = 0; i < _softKeyboardGestureSelector.numberOfSegments; i++) {
|
||||
[_softKeyboardGestureSelector setEnabled:![self isCustomOswEnabled] ? true : i+3 != oswLayoutFingers forSegmentAtIndex:i]; // 或 NO 来禁用
|
||||
[_softKeyboardGestureSelector setEnabled:![self isCustomOswEnabled] || i == 3 ? true : i+3 != oswLayoutFingers forSegmentAtIndex:i]; // 或 NO 来禁用
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1643,13 +1694,21 @@ BOOL isCustomResolution(CGSize res) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void) widget:(UISlider*)widget setEnabled:(bool)enabled{
|
||||
[widget setEnabled:enabled];
|
||||
if(enabled){
|
||||
widget.alpha = 1.0;
|
||||
[widget setValue:widget.value + 0.0001]; // this is for low iOS version (like iOS14), only setting this minor value change is able to make widget visibility clear
|
||||
- (void) widget:(UIView*)widget setEnabled:(bool)enabled{
|
||||
if([widget isKindOfClass:[UISlider class]]){
|
||||
UISlider* widgetPtr = (UISlider* )widget;
|
||||
[widgetPtr setEnabled:enabled];
|
||||
if(enabled){
|
||||
widgetPtr.alpha = 1.0;
|
||||
[widgetPtr setValue:widgetPtr.value + 0.0001]; // this is for low iOS version (like iOS14), only setting this minor value change is able to make widget visibility clear
|
||||
}
|
||||
else widgetPtr.alpha = 0.5; // this is for updating widget visibility on low iOS version like mini5 ios14
|
||||
}
|
||||
|
||||
if([widget isKindOfClass:[UISwitch class]]){
|
||||
widget.userInteractionEnabled = enabled;
|
||||
widget.alpha = enabled ? 1 : 0.5;
|
||||
}
|
||||
else widget.alpha = 0.5; // this is for updating widget visibility on low iOS version like mini5 ios14
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1891,6 +1950,10 @@ BOOL isCustomResolution(CGSize res) {
|
||||
[self updateBitrateText];
|
||||
}
|
||||
|
||||
- (bool)hdrSupported{
|
||||
return VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) && (AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10);
|
||||
}
|
||||
|
||||
- (void) updateBitrateText {
|
||||
// Display bitrate in Mbps
|
||||
UILabel* label = [self findDynamicLabelFromStack:self.bitrateStack];
|
||||
|
||||
@@ -160,11 +160,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isFirstLaunch {
|
||||
NSString *key = @"hasLaunchedBefore";
|
||||
BOOL launchedBefore = [[NSUserDefaults standardUserDefaults] boolForKey:key];
|
||||
- (BOOL)isFirstStreaming {
|
||||
NSString *key = @"hasStreamedBefore";
|
||||
BOOL streamedBefore = [[NSUserDefaults standardUserDefaults] boolForKey:key];
|
||||
|
||||
if (!launchedBefore) {
|
||||
if (!streamedBefore) {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:key];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize]; // iOS 12+ 可省略
|
||||
return YES;
|
||||
@@ -267,7 +267,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)presentCommandManagerViewController{
|
||||
- (void)presentToolboxViewController{
|
||||
ToolboxViewController* oldToolboxVC = toolBoxViewController;
|
||||
toolBoxViewController = [[ToolboxViewController alloc] init];
|
||||
toolBoxViewController.specialEntryDelegate = self;
|
||||
@@ -287,7 +287,7 @@
|
||||
[self.view addGestureRecognizer:_slideToSettingsRecognizer];
|
||||
|
||||
|
||||
_slideToCmdToolRecognizer = [[CustomEdgeSlideGestureRecognizer alloc] initWithTarget:self action:@selector(presentCommandManagerViewController)];
|
||||
_slideToCmdToolRecognizer = [[CustomEdgeSlideGestureRecognizer alloc] initWithTarget:self action:@selector(presentToolboxViewController)];
|
||||
if(_settings.slideToSettingsScreenEdge.intValue == UIRectEdgeLeft) _slideToCmdToolRecognizer.edges = UIRectEdgeRight;
|
||||
else _slideToCmdToolRecognizer.edges = UIRectEdgeLeft; // _commandManager triggered by sliding from another side.
|
||||
_slideToCmdToolRecognizer.normalizedThresholdDistance = _settings.slideToSettingsDistance.floatValue;
|
||||
@@ -476,8 +476,7 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)popFirstLaunchTip {
|
||||
return; // temp disable
|
||||
- (void)popFirstStreamingTip {
|
||||
// 初始化倒计时秒数
|
||||
__block NSInteger remainingSeconds = 16;
|
||||
|
||||
@@ -485,9 +484,25 @@
|
||||
NSString* cmdToolEdgeSide = _settings.slideToSettingsScreenEdge.intValue == UIRectEdgeLeft ? [LocalizationHelper localizedStringForKey:@"right"] : [LocalizationHelper localizedStringForKey:@"left"];
|
||||
uint8_t slideDist = (uint8_t)(_settings.slideToSettingsDistance.floatValue * 100);
|
||||
// 创建弹窗
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"First Launch Tips"]
|
||||
message:[LocalizationHelper localizedStringForKey:@"\n1. From %@ edge, slide %d%% screen width to open settings menu\n\n2. From %@ edge, slide %d%% screen width to open command tool\n\n3. Back to Streaming from settings menu: slide from left edge\n\n4. Slide from upper 40%% of screen edge to avoid sending touch events to PC side", settingsEdgeSide, slideDist, cmdToolEdgeSide, slideDist]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
NSString* tipText = [LocalizationHelper localizedStringForKey:@"firstLaunchTip", settingsEdgeSide, slideDist, cmdToolEdgeSide, slideDist];
|
||||
|
||||
UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"First Launch Tips"] message: [LocalizationHelper localizedStringForKey:@"%@", tipText] preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
paragraphStyle.alignment = NSTextAlignmentLeft;
|
||||
|
||||
NSDictionary *attributes = @{
|
||||
NSParagraphStyleAttributeName: paragraphStyle,
|
||||
NSFontAttributeName: [UIFont systemFontOfSize:14]
|
||||
};
|
||||
|
||||
NSAttributedString *attributedMessage = [[NSAttributedString alloc] initWithString:tipText
|
||||
attributes:attributes];
|
||||
|
||||
// 使用 KVC 设置 attributedMessage(注意审核风险)
|
||||
[tipsAlertController setValue:attributedMessage forKey:@"attributedMessage"];
|
||||
|
||||
// 添加确认按钮(初始禁用)
|
||||
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Got it! (15)"]
|
||||
@@ -495,10 +510,10 @@
|
||||
handler:^(UIAlertAction * _Nonnull action) {
|
||||
}];
|
||||
confirmAction.enabled = NO;
|
||||
[alert addAction:confirmAction];
|
||||
[tipsAlertController addAction:confirmAction];
|
||||
|
||||
// 显示弹窗
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
[self presentViewController:tipsAlertController animated:YES completion:nil];
|
||||
|
||||
// 使用dispatch_source_t实现精确倒计时
|
||||
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
|
||||
@@ -577,7 +592,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 isFirstLaunch]) [self popFirstLaunchTip];
|
||||
if([self isFirstStreaming]) [self popFirstStreamingTip];
|
||||
|
||||
#if TARGET_OS_TV
|
||||
if (!_menuTapGestureRecognizer || !_menuDoubleTapGestureRecognizer || !_playPauseTapGestureRecognizer) {
|
||||
|
||||
@@ -30,8 +30,8 @@ import UIKit
|
||||
private let titleLabel = UILabel()
|
||||
@objc public var specialEntries : NSMutableArray = ["widgetSwitchTool", "widgetLayoutTool", "bringUpSoftKeyboard", "enterPip"]
|
||||
private let specialEntryAliasDic : [String:String] = [
|
||||
"widgetSwitchTool":SwiftLocalizationHelper.localizedString(forKey: "[ Switch among on-screen widget profiles ]"),
|
||||
"widgetLayoutTool":SwiftLocalizationHelper.localizedString(forKey: "[ Open on-screen widget tool ]"),
|
||||
"widgetSwitchTool":SwiftLocalizationHelper.localizedString(forKey: "[ Switch on-screen widget profile ]"),
|
||||
"widgetLayoutTool":SwiftLocalizationHelper.localizedString(forKey: "[ On-screen widget tool ]"),
|
||||
"bringUpSoftKeyboard":SwiftLocalizationHelper.localizedString(forKey: "[ Bring up soft keyboard ]"),
|
||||
"enterPip":SwiftLocalizationHelper.localizedString(forKey: "[ Enter picture-in-picture mode ]")
|
||||
]
|
||||
@@ -149,8 +149,7 @@ import UIKit
|
||||
NSLayoutConstraint.activate([
|
||||
|
||||
// Set the width and height of the view
|
||||
|
||||
view.widthAnchor.constraint(equalTo: view.superview!.widthAnchor, multiplier: isIPhone() ? 0.7 : 0.8),
|
||||
view.widthAnchor.constraint(equalTo: view.superview!.widthAnchor, multiplier: isIPhone() ? 0.6 : 0.8),
|
||||
view.heightAnchor.constraint(equalTo: view.superview!.heightAnchor, multiplier: 0.99),
|
||||
// Set the width and height of the view
|
||||
//view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 60),
|
||||
@@ -177,7 +176,7 @@ import UIKit
|
||||
exitButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
||||
|
||||
// EditButton constraints
|
||||
editButton.leadingAnchor.constraint(equalTo: exitButton.trailingAnchor, constant: 50),
|
||||
editButton.leadingAnchor.constraint(equalTo: exitButton.trailingAnchor, constant: 25),
|
||||
editButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
||||
|
||||
// AddButton constraints
|
||||
@@ -185,11 +184,11 @@ import UIKit
|
||||
addButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
||||
|
||||
// DeleteButton constraints
|
||||
deleteButton.trailingAnchor.constraint(equalTo: addButton.leadingAnchor, constant: -50),
|
||||
deleteButton.trailingAnchor.constraint(equalTo: addButton.leadingAnchor, constant: -25),
|
||||
deleteButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
||||
|
||||
// DeleteButton constraints
|
||||
pinButton.trailingAnchor.constraint(equalTo: deleteButton.leadingAnchor, constant: -50),
|
||||
pinButton.trailingAnchor.constraint(equalTo: deleteButton.leadingAnchor, constant: -25),
|
||||
pinButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
||||
])
|
||||
}
|
||||
@@ -208,7 +207,7 @@ import UIKit
|
||||
pinButton.backgroundColor = highlightColor
|
||||
}
|
||||
else{
|
||||
pinButton.backgroundColor = viewBackgroundColor
|
||||
pinButton.backgroundColor = .clear
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3140,37 +3140,37 @@
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
"value" : "台前调度(可全屏)"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "幕前調度"
|
||||
"value" : "幕前調度(可全螢幕)"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "幕前調度"
|
||||
"value" : "幕前調度(可全螢幕)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"VWB-YB-Ptj.segmentTitles[1]" : {
|
||||
"comment" : "Class = \"UISegmentedControl\"; VWB-YB-Ptj.segmentTitles[1] = \"AirPlay\"; ObjectID = \"VWB-YB-Ptj\";",
|
||||
"comment" : "Class = \"UISegmentedControl\"; VWB-YB-Ptj.segmentTitles[1] = \"AirPlay (mirroring)\"; ObjectID = \"VWB-YB-Ptj\";",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "AirPlay"
|
||||
"value" : "AirPlay (mirroring)"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
"state" : "needs_review",
|
||||
"value" : "隔空播放(镜像)"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
@@ -3181,7 +3181,7 @@
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"state" : "needs_review",
|
||||
"value" : "螢幕鏡像輸出"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2834,19 +2834,19 @@
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "台前调度"
|
||||
"value" : "台前调度(可全屏)"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "幕前調度"
|
||||
"value" : "幕前調度(可全螢幕)"
|
||||
}
|
||||
},
|
||||
"zh-HK" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "幕前調度"
|
||||
"value" : "幕前調度(可全螢幕)"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2864,7 +2864,7 @@
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "隔空播放"
|
||||
"value" : "隔空播放(镜像)"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
|
||||
Reference in New Issue
Block a user