From 5759c122edfdc60ddf0b164a6773ca661c91f35f Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Tue, 22 Jul 2025 00:47:00 +0800 Subject: [PATCH 01/21] update about page --- VoidLink/AboutView.swift | 6 ++-- VoidLink/Localization/Localizable.xcstrings | 29 +++++++++++++++++++ .../ViewControllers/MainFrameViewController.m | 2 +- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/VoidLink/AboutView.swift b/VoidLink/AboutView.swift index 206967aa..16553caf 100644 --- a/VoidLink/AboutView.swift +++ b/VoidLink/AboutView.swift @@ -56,7 +56,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 +73,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 +81,7 @@ public struct AboutView: View { .background(Color.blue) .foregroundColor(.white) .cornerRadius(12) + .frame(height: 33) .frame(minWidth: 100) Button("OK") { @@ -90,6 +91,7 @@ public struct AboutView: View { .background(Color.blue) .foregroundColor(.white) .cornerRadius(12) + .frame(height: 33) .frame(minWidth: 100) } .padding(.top, 10) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 07db9814..9d4cee84 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -3851,6 +3851,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" : { diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index 46f7f0b9..fb22b5f6 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -1348,7 +1348,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]; From e63ce4d10136b6fea5687c575976ed8d27cc5878 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Tue, 22 Jul 2025 21:41:38 +0800 Subject: [PATCH 02/21] re-enable and update first launch tip --- .../VoidLink v1.0.xcdatamodel/contents | 2 +- VoidLink/Localization/Localizable.xcstrings | 52 +++++++++++-------- .../StreamFrameViewController.m | 27 +++++++--- 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents index 5d378bcb..f59b2133 100644 --- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents +++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents @@ -51,7 +51,7 @@ - + diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 9d4cee84..85a1c7bd 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -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" : { @@ -1779,6 +1756,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" : { diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index c3dab216..6d70c02b 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -420,7 +420,6 @@ #endif - (void)popFirstLaunchTip { - return; // temp disable // 初始化倒计时秒数 __block NSInteger remainingSeconds = 16; @@ -428,9 +427,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)"] @@ -438,10 +453,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()); From 0f443af35558db097a68608a179bee9a10643a89 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Tue, 22 Jul 2025 23:57:13 +0800 Subject: [PATCH 03/21] tweak toolbox view --- VoidLink/ViewControllers/StreamFrameViewController.m | 4 ++-- VoidLink/ViewControllers/ToolboxViewController.swift | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index 6d70c02b..83adac63 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -244,7 +244,7 @@ } } -- (void)presentCommandManagerViewController{ +- (void)presentToolboxViewController{ ToolboxViewController* oldToolboxVC = toolBoxViewController; toolBoxViewController = [[ToolboxViewController alloc] init]; toolBoxViewController.specialEntryDelegate = self; @@ -264,7 +264,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; diff --git a/VoidLink/ViewControllers/ToolboxViewController.swift b/VoidLink/ViewControllers/ToolboxViewController.swift index 22e8d1f0..ef9ae286 100644 --- a/VoidLink/ViewControllers/ToolboxViewController.swift +++ b/VoidLink/ViewControllers/ToolboxViewController.swift @@ -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 } } From b8478bfedcca8f245c4dd2acbcaadb86ab01f601 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 23 Jul 2025 13:10:16 +0800 Subject: [PATCH 04/21] HDR info button --- VoidLink/Base.lproj/iPad.storyboard | 12 ++++---- VoidLink/Base.lproj/iPhone.storyboard | 4 +-- VoidLink/Localization/Localizable.xcstrings | 29 +++++++++++++++++++ .../ViewControllers/SettingsViewController.h | 2 +- .../ViewControllers/SettingsViewController.m | 14 +++++++-- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard index 4ec8402b..b3f02769 100644 --- a/VoidLink/Base.lproj/iPad.storyboard +++ b/VoidLink/Base.lproj/iPad.storyboard @@ -60,7 +60,7 @@ - + @@ -935,7 +935,6 @@ - @@ -964,6 +963,7 @@ + @@ -1660,19 +1660,19 @@ - + - + - + - + diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard index fc1c9a67..9fb1c0e7 100644 --- a/VoidLink/Base.lproj/iPhone.storyboard +++ b/VoidLink/Base.lproj/iPhone.storyboard @@ -13,7 +13,7 @@ - + @@ -1585,7 +1585,6 @@ - @@ -1614,6 +1613,7 @@ + diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 85a1c7bd..1ae1e730 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -1900,6 +1900,35 @@ } } }, + "hdrStackTip" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "HDR video stream decoding is not supported on current device" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "当前系统不支持HDR视频流解码" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "當前裝置不支援HDR視訊串流解碼" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "當前裝置不支援HDR視訊串流解碼" + } + } + } + }, "Height" : { "extractionState" : "manual", "localizations" : { diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h index d42528b1..ebc85e00 100644 --- a/VoidLink/ViewControllers/SettingsViewController.h +++ b/VoidLink/ViewControllers/SettingsViewController.h @@ -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; diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 76b0ce7f..462998ca 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -519,7 +519,7 @@ BOOL isCustomResolution(CGSize res) { [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]; [videoSection addToParentStack:_parentStack]; @@ -973,6 +973,11 @@ BOOL isCustomResolution(CGSize res) { showOnlineDocAction = true; } + if([sender.superview.accessibilityIdentifier isEqualToString: @"hdrStack"]){ + tipText = [LocalizationHelper localizedStringForKey:@"hdrStackTip"]; + showOnlineDocAction = false; + } + @@ -1271,7 +1276,7 @@ BOOL isCustomResolution(CGSize res) { break; } - if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10)) { + if ([self hdrSupported]) { [self.hdrSwitch setOn:NO]; [self.hdrSwitch setEnabled:NO]; } @@ -1862,6 +1867,11 @@ BOOL isCustomResolution(CGSize res) { [self updateBitrateText]; } +- (bool)hdrSupported{ + return false; + return !VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10); +} + - (void) updateBitrateText { // Display bitrate in Mbps UILabel* label = [self findDynamicLabelFromStack:self.bitrateStack]; From 9198960cc7f5e31a04e1f80469c5179af0d12cef Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 23 Jul 2025 13:52:14 +0800 Subject: [PATCH 05/21] - pipStack --- VoidLink/Localization/Localizable.xcstrings | 52 +++++++++++++++++++ .../ViewControllers/SettingsViewController.m | 11 ++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 1ae1e730..833648f0 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -2804,6 +2804,29 @@ } } }, + "Online Documentation" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在线支持文档" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "線上支援文件" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "線上支援文件" + } + } + } + }, "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" : { @@ -2942,6 +2965,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 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" : { diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 462998ca..c8a48d5f 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -950,6 +950,7 @@ BOOL isCustomResolution(CGSize res) { - (void)infoButtonTapped:(UIButton* )sender{ NSString* tipText = @""; + NSString* onlineDocLink = @""; bool showOnlineDocAction = false; tipText = sender.superview.accessibilityIdentifier; if([sender.superview.accessibilityIdentifier isEqualToString: @"bitrateStack"]){ @@ -959,6 +960,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/wr4ywd4vatrb3y07?singleDoc#"; } if([sender.superview.accessibilityIdentifier isEqualToString: @"touchModeStack"]){ tipText = [LocalizationHelper localizedStringForKey:@"touchModeStackTip"]; @@ -972,11 +974,15 @@ 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; + } @@ -1003,7 +1009,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]; } @@ -1868,7 +1874,6 @@ BOOL isCustomResolution(CGSize res) { } - (bool)hdrSupported{ - return false; return !VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10); } From a8c1451a28519a22c6b6d9afbf79f6b3ca3a0a72 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 23 Jul 2025 17:14:08 +0800 Subject: [PATCH 06/21] yuv444Stack info button --- VoidLink/ViewControllers/SettingsViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index c8a48d5f..09495f77 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -960,7 +960,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/wr4ywd4vatrb3y07?singleDoc#"; + onlineDocLink = @"https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/koeimmrvt4o17auc?singleDoc#"; } if([sender.superview.accessibilityIdentifier isEqualToString: @"touchModeStack"]){ tipText = [LocalizationHelper localizedStringForKey:@"touchModeStackTip"]; From ff991dd6173c52e3485a3a16c81e512a29ceb6f2 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 23 Jul 2025 20:10:42 +0800 Subject: [PATCH 07/21] - PiP stack tip - settings menu interaction minor fix --- VoidLink/Localization/Localizable.xcstrings | 34 ++++++++++++++++++- .../ViewControllers/SettingsViewController.m | 8 +++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 833648f0..dc04ab40 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -2971,7 +2971,7 @@ "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 also defined by “Background Session” settings in “Others” section\n\n-PiP is available for iOS15+" + "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" : { @@ -3892,6 +3892,38 @@ } } }, + "softKeyboardGestureStackDoc" : { + "extractionState" : "manual" + }, + "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" : { diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 09495f77..de106087 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -978,11 +978,15 @@ BOOL isCustomResolution(CGSize res) { 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 = @"softKeyboardGestureStackDoc"; + } @@ -1526,7 +1530,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 来禁用 } } From 0e8980da95c55d1dfbd45f896cda67191a75a6a9 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 23 Jul 2025 23:59:20 +0800 Subject: [PATCH 08/21] fill in stack tips --- VoidLink/Localization/Localizable.xcstrings | 227 +++++++++++++++++- .../ViewControllers/SettingsViewController.m | 34 ++- 2 files changed, 252 insertions(+), 9 deletions(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index dc04ab40..c12b0448 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -225,7 +225,7 @@ }, "zh-Hant" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "\n\n您裝置的遠端工作階段連線被阻擋。在此網路上連線時,串流可能無法運作。" } }, @@ -2274,6 +2274,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" : "needs_review", + "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" : { @@ -2827,6 +2885,58 @@ } } }, + "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." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "VoidLink具备丰富而强大的自定义屏显控件,类型包括:键盘按键、手柄按键和摇杆、鼠标触摸板和按键等。详见在线文档。 " + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。" + } + } + } + }, "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" : { @@ -2850,6 +2960,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" : { @@ -3869,6 +4008,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" : { @@ -3893,7 +4061,33 @@ } }, "softKeyboardGestureStackDoc" : { - "extractionState" : "manual" + "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", @@ -4425,6 +4619,35 @@ } } }, + "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 無法自動鎖定顯示方向。如有需要,請手動鎖定。" + } + } + } + }, "Unsupported on this device" : { "extractionState" : "manual", "localizations" : { diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index de106087..e855b86d 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -595,8 +595,8 @@ 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]; [otherSection addToParentStack:_parentStack]; [otherSection setExpanded:YES]; @@ -607,7 +607,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]; } @@ -943,7 +943,7 @@ 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], ]]; } @@ -985,12 +985,32 @@ BOOL isCustomResolution(CGSize res) { if([sender.superview.accessibilityIdentifier isEqualToString: @"softKeyboardGestureStack" ]){ tipText = [LocalizationHelper localizedStringForKey:@"softKeyboardGestureStackTip"]; showOnlineDocAction = true; - onlineDocLink = @"softKeyboardGestureStackDoc"; + 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"]; } - - UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Tips"] message: [LocalizationHelper localizedStringForKey:@"%@", tipText] preferredStyle:UIAlertControllerStyleAlert]; From a707b21446eaa848d5578d7ce40d21963709e270 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 10:30:38 +0800 Subject: [PATCH 09/21] - stack tips: external display --- VoidLink/Base.lproj/iPad.storyboard | 50 +++++++-------- VoidLink/Input/StreamView.h | 2 +- VoidLink/Input/StreamView.m | 2 +- VoidLink/Localization/Localizable.xcstrings | 62 ++++++++++++++++++- .../ViewControllers/MainFrameViewController.m | 2 +- .../ViewControllers/SettingsViewController.m | 5 ++ VoidLink/mul.lproj/iPad.xcstrings | 16 ++--- VoidLink/mul.lproj/iPhone.xcstrings | 8 +-- 8 files changed, 105 insertions(+), 42 deletions(-) diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard index b3f02769..bb8d1122 100644 --- a/VoidLink/Base.lproj/iPad.storyboard +++ b/VoidLink/Base.lproj/iPad.storyboard @@ -60,7 +60,7 @@ - + @@ -581,7 +581,7 @@ - + @@ -847,27 +847,6 @@ - - - - - - - - - - - - - @@ -930,10 +909,31 @@ + + + + + + + + + + + + + - + @@ -1033,7 +1033,7 @@ - + diff --git a/VoidLink/Input/StreamView.h b/VoidLink/Input/StreamView.h index 6b7943c6..1fff07fc 100644 --- a/VoidLink/Input/StreamView.h +++ b/VoidLink/Input/StreamView.h @@ -22,7 +22,7 @@ - (void)userInteractionEnded; - (void)streamExitRequested; - (void)toggleStatsOverlay; -- (void)localMousePointerMode; +- (void)toggleMouseCapture; - (void)toggleMouseVisible; @end diff --git a/VoidLink/Input/StreamView.m b/VoidLink/Input/StreamView.m index cf7b9963..29e8636d 100644 --- a/VoidLink/Input/StreamView.m +++ b/VoidLink/Input/StreamView.m @@ -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]; diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index c12b0448..b6719d24 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -1641,6 +1641,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" : { @@ -4608,13 +4666,13 @@ "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 上提供類似觸控螢幕的體驗。" } } } diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index fb22b5f6..95d2c879 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -1135,7 +1135,7 @@ static NSMutableSet* hostList; else [revealController buttonsNotInStreaming]; DataManager* dataMan = [[DataManager alloc] init]; - TemporarySettings* currentSettings = [dataMan getSettings]; + // TemporarySettings* currentSettings = [dataMan getSettings]; [streamFrameViewController setUserInteractionEnabledForStreamView:!_settingsExpandedInStreamView || position == FrontViewPositionLeft]; [settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.resolutionStack]; diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index e855b86d..c60fd7e2 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -1009,6 +1009,11 @@ BOOL isCustomResolution(CGSize res) { showOnlineDocAction = true; onlineDocLink = [LocalizationHelper localizedStringForKey:@"onScreenWidgetStackDoc"]; } + if([sender.superview.accessibilityIdentifier isEqualToString: @"externalDisplayModeStack"]){ + tipText = [LocalizationHelper localizedStringForKey:@"externalDisplayModeStackTip"]; + showOnlineDocAction = true; + onlineDocLink = [LocalizationHelper localizedStringForKey:@"externalDisplayModeStackDoc"]; + } UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Tips"] message: [LocalizationHelper localizedStringForKey:@"%@", tipText] preferredStyle:UIAlertControllerStyleAlert]; diff --git a/VoidLink/mul.lproj/iPad.xcstrings b/VoidLink/mul.lproj/iPad.xcstrings index b5710063..44f9e595 100644 --- a/VoidLink/mul.lproj/iPad.xcstrings +++ b/VoidLink/mul.lproj/iPad.xcstrings @@ -3068,37 +3068,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" : { @@ -3109,7 +3109,7 @@ }, "zh-HK" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "螢幕鏡像輸出" } } diff --git a/VoidLink/mul.lproj/iPhone.xcstrings b/VoidLink/mul.lproj/iPhone.xcstrings index a26d0f7f..32b2c72c 100644 --- a/VoidLink/mul.lproj/iPhone.xcstrings +++ b/VoidLink/mul.lproj/iPhone.xcstrings @@ -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" : { From a7fc2a65e0d2be270446d568e5ba6c997b1774c4 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 16:02:30 +0800 Subject: [PATCH 10/21] - emulated controller type tip - HDR switch fixes --- VoidLink/Localization/Localizable.xcstrings | 66 +++++++++++++++++-- .../ViewControllers/SettingsViewController.h | 2 +- .../ViewControllers/SettingsViewController.m | 34 +++++++--- 3 files changed, 87 insertions(+), 15 deletions(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index b6719d24..eb635a53 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -1451,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" : "needs_review", + "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" : { @@ -2972,25 +3030,25 @@ "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." + "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具备丰富而强大的自定义屏显控件,类型包括:键盘按键、手柄按键和摇杆、鼠标触摸板和按键等。详见在线文档。 " + "value" : "- VoidLink具备丰富而强大的自定义屏显控件,类型包括:键盘按键、手柄按键和摇杆、鼠标触摸板和按键等。详见在线文档。 \n\n- 可通过多指轻按手势在串流时打开控件布局工具。" } }, "zh-Hant" : { "stringUnit" : { "state" : "translated", - "value" : "VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。" + "value" : "- VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。\n\n- 可透過多指輕點手勢,在串流時開啟控制元件佈局工具。" } }, "zh-HK" : { "stringUnit" : { "state" : "translated", - "value" : "VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。" + "value" : "- VoidLink 提供豐富且強大的自訂螢幕顯示元件,類型包含:鍵盤按鍵、手把按鍵與搖桿、滑鼠觸控板及按鍵等。詳細資訊請參考線上說明文件。\n\n- 可透過多指輕點手勢,在串流時開啟控制元件佈局工具。" } } } diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h index ebc85e00..6e39d57a 100644 --- a/VoidLink/ViewControllers/SettingsViewController.h +++ b/VoidLink/ViewControllers/SettingsViewController.h @@ -125,7 +125,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; diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index c60fd7e2..e975a8cb 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -514,7 +514,7 @@ 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]; @@ -522,6 +522,7 @@ BOOL isCustomResolution(CGSize res) { [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]; [videoSection addToParentStack:_parentStack]; [videoSection setExpanded:YES]; @@ -1014,6 +1015,11 @@ BOOL isCustomResolution(CGSize res) { showOnlineDocAction = true; onlineDocLink = [LocalizationHelper localizedStringForKey:@"externalDisplayModeStackDoc"]; } + if([sender.superview.accessibilityIdentifier isEqualToString: @"emulatedControllerTypeStack"]){ + tipText = [LocalizationHelper localizedStringForKey:@"emulatedControllerTypeStackTip"]; + showOnlineDocAction = true; + onlineDocLink = [LocalizationHelper localizedStringForKey:@"emulatedControllerTypeStackDoc"]; + } UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Tips"] message: [LocalizationHelper localizedStringForKey:@"%@", tipText] preferredStyle:UIAlertControllerStyleAlert]; @@ -1311,9 +1317,9 @@ BOOL isCustomResolution(CGSize res) { break; } - if ([self hdrSupported]) { + if (![self hdrSupported]) { [self.hdrSwitch setOn:NO]; - [self.hdrSwitch setEnabled:NO]; + [self widget:self.hdrSwitch setEnabled:NO]; } else { [self.hdrSwitch setOn:currentSettings.enableHdr]; @@ -1654,13 +1660,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 } /* @@ -1903,7 +1917,7 @@ BOOL isCustomResolution(CGSize res) { } - (bool)hdrSupported{ - return !VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10); + return VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) && (AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10); } - (void) updateBitrateText { From b7d7b9a058c121454ca068b92fa4e38a4202f373 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 16:24:40 +0800 Subject: [PATCH 11/21] gyroModeStack tip --- VoidLink/Localization/Localizable.xcstrings | 68 +++++++++++++++++-- .../ViewControllers/SettingsViewController.m | 6 ++ 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index eb635a53..1b845f4b 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -1462,7 +1462,7 @@ }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/bz6ggagp0ly4loq3?singleDoc#" } }, @@ -2016,6 +2016,64 @@ } } }, + "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" : { @@ -2027,7 +2085,7 @@ }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "当前系统不支持HDR视频流解码" } }, @@ -2407,7 +2465,7 @@ }, "zh-Hant" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/yfao3s5bhl93rs01?singleDoc#" } }, @@ -2511,7 +2569,7 @@ }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "无法执行网络测试. 请检查网络连接后重试." } }, @@ -2638,7 +2696,7 @@ }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "网络测试成功. 如果仍然无法连接远程主机, 请检查主机端防火墙设置." } }, diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index e975a8cb..cf6b85ef 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -1020,6 +1020,11 @@ BOOL isCustomResolution(CGSize res) { 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]; @@ -1357,6 +1362,7 @@ BOOL isCustomResolution(CGSize res) { [self emulatedControllerTypeChanged:self.emulatedControllerTypeSelector]; + [self.audioOnPcSwitch setOn:currentSettings.playAudioOnPC]; _lastSelectedResolutionIndex = resolution; [self.resolutionSelector setSelectedSegmentIndex:resolution]; From 08ef392fca5ee95742ae2327ccf19b03244c9b24 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 19:25:05 +0800 Subject: [PATCH 12/21] save osw profile when temporarily leaving osw layout tool --- VoidLink/Input/CustomOSC/LayoutOnScreenControls.m | 1 + .../LayoutOnScreenControlsViewController.m | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/VoidLink/Input/CustomOSC/LayoutOnScreenControls.m b/VoidLink/Input/CustomOSC/LayoutOnScreenControls.m index 566a56ed..a8cbea90 100644 --- a/VoidLink/Input/CustomOSC/LayoutOnScreenControls.m +++ b/VoidLink/Input/CustomOSC/LayoutOnScreenControls.m @@ -14,6 +14,7 @@ #import "OnScreenButtonState.h" #import "OSCProfilesManager.h" + @interface LayoutOnScreenControls () @end diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 1e881a1c..52e5f6c2 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -239,6 +239,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 +252,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) { @@ -1109,6 +1119,7 @@ } - (void) presentProfilesTableView{ + [self saveTapped:nil]; UIStoryboard *storyboard; BOOL isIPhone = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone); if (isIPhone) { From e0d03baf1c4d3ea990e40e3bd3f3cc13b436a32d Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 19:37:36 +0800 Subject: [PATCH 13/21] osw reshape fix --- VoidLink/Input/OnScreenWidgetView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift index 2cea3abc..f2e0c994 100644 --- a/VoidLink/Input/OnScreenWidgetView.swift +++ b/VoidLink/Input/OnScreenWidgetView.swift @@ -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([ From 6941f006b3a7bc667bd00822686ef234ca8dfc49 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 19:46:41 +0800 Subject: [PATCH 14/21] tweak lockIcon size --- VoidLink/HostCardView.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VoidLink/HostCardView.m b/VoidLink/HostCardView.m index 85ed5a21..9081bb2b 100644 --- a/VoidLink/HostCardView.m +++ b/VoidLink/HostCardView.m @@ -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; From 2e7abf0eb208d2532da505693926896a25926812 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 19:58:13 +0800 Subject: [PATCH 15/21] change default app icon --- VoidLink/.DS_Store | Bin 14340 -> 14340 bytes .../icon-pc-app.imageset/icon-pc-app.svg | 10 +++++----- VoidLink/UIAppView.m | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/VoidLink/.DS_Store b/VoidLink/.DS_Store index d5e91d03f49ced7b3311ebbaa10da5d91c509663..d331c5b61d5de9427ab4290f6f9281b88636252e 100644 GIT binary patch delta 445 zcmZoEXeroGtID`@a-C|ShGccMxrwEYg07jVQLTBbhhp4i?bx?eE zPHtX)_vAeS@{B!`15}kJN2r-G3Cm2Lpe8O9FTh`%kzekaoSzp^lv$hM5dY88$NPVK~Qdo8bc^6C)3!6r(buKBEPrC8HCg h3!^V%7-KkN24gN`-eftAfX(?De7u9yvxX#l766ZhZe;)f delta 460 zcmZoEXeroGtID`za-C|Sxg07KSt&T#qg}I@Qf`y@ZZ7nB&oLQARd6(KzgLnb{;*9)q&*c2P zfTGm0%+&Je^rFm^;DW^D%)E4E`wt9YpzPoSrWq#BQx{8agNSm7K*ZoAV@O_pUMeT2 zvV%8NjDta!!I{B_A(SDDp^{+&!yJYc44WB_GF)PK&hV3wnNg5YnNgq7g3*!Di_wQM hlrfGmp0R+jl(B5GyhZ>c!{&SqKHkCMX-}$o8UO^=a?bz& diff --git a/VoidLink/Images.xcassets/icon-pc-app.imageset/icon-pc-app.svg b/VoidLink/Images.xcassets/icon-pc-app.imageset/icon-pc-app.svg index 04e56c40..0c43597f 100644 --- a/VoidLink/Images.xcassets/icon-pc-app.imageset/icon-pc-app.svg +++ b/VoidLink/Images.xcassets/icon-pc-app.imageset/icon-pc-app.svg @@ -1,6 +1,6 @@ - - - - - + + + + + diff --git a/VoidLink/UIAppView.m b/VoidLink/UIAppView.m index abe6d208..b02538b8 100644 --- a/VoidLink/UIAppView.m +++ b/VoidLink/UIAppView.m @@ -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 From 75e88ee31e036b1817642ac9ce14b3f09b22a3be Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 20:32:58 +0800 Subject: [PATCH 16/21] tweak aboutView --- VoidLink/AboutView.swift | 7 ++++--- VoidLink/AboutViewController.swift | 2 +- VoidLink/ViewControllers/MainFrameViewController.m | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/VoidLink/AboutView.swift b/VoidLink/AboutView.swift index 16553caf..d1d2d443 100644 --- a/VoidLink/AboutView.swift +++ b/VoidLink/AboutView.swift @@ -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") diff --git a/VoidLink/AboutViewController.swift b/VoidLink/AboutViewController.swift index b82eb1f8..be751ec2 100644 --- a/VoidLink/AboutViewController.swift +++ b/VoidLink/AboutViewController.swift @@ -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 diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index 95d2c879..cf8deebc 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -2115,7 +2115,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]; From 619e936c391975a92334846dda3f22296604c398 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 20:50:19 +0800 Subject: [PATCH 17/21] pop aboutView upon first app launch --- .../ViewControllers/MainFrameViewController.m | 16 +++++++++++++++- .../ViewControllers/StreamFrameViewController.m | 12 ++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index cf8deebc..3041ea50 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -1134,7 +1134,7 @@ static NSMutableSet* hostList; if(self.settingsExpandedInStreamView) [revealController buttonsInStreaming]; else [revealController buttonsNotInStreaming]; - DataManager* dataMan = [[DataManager alloc] init]; + // DataManager* dataMan = [[DataManager alloc] init]; // TemporarySettings* currentSettings = [dataMan getSettings]; [streamFrameViewController setUserInteractionEnabledForStreamView:!_settingsExpandedInStreamView || position == FrontViewPositionLeft]; @@ -1270,6 +1270,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); } @@ -1775,6 +1788,7 @@ static NSMutableSet* hostList; //[self simulateSettingsButtonPress]; //force reload resolution table in the setting //[self simulateSettingsButtonPress]; [self updateResolutionAccordingly]; + if([self isFirstLaunch])[self helpButtonTapped]; } diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index 83adac63..4c3ecca4 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -137,11 +137,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; @@ -419,7 +419,7 @@ } #endif -- (void)popFirstLaunchTip { +- (void)popFirstStreamingTip { // 初始化倒计时秒数 __block NSInteger remainingSeconds = 16; @@ -535,7 +535,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) { From 08a2312099a31c400478f3b16a705ff9f218bb9c Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 21:11:06 +0800 Subject: [PATCH 18/21] toolbox ui string update --- VoidLink/Localization/Localizable.xcstrings | 4 ++-- VoidLink/ViewControllers/ToolboxViewController.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 1b845f4b..d5129bae 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -283,7 +283,7 @@ } } }, - "[ Open on-screen widget tool ]" : { + "[ On-screen widget tool ]" : { "extractionState" : "manual", "localizations" : { "zh-Hans" : { @@ -306,7 +306,7 @@ } } }, - "[ Switch among on-screen widget profiles ]" : { + "[ Switch on-screen widget profile ]" : { "extractionState" : "manual", "localizations" : { "zh-Hans" : { diff --git a/VoidLink/ViewControllers/ToolboxViewController.swift b/VoidLink/ViewControllers/ToolboxViewController.swift index ef9ae286..5d446728 100644 --- a/VoidLink/ViewControllers/ToolboxViewController.swift +++ b/VoidLink/ViewControllers/ToolboxViewController.swift @@ -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 ]") ] From ed56d26b1c79dbae4c45b85f18d4b147b87994c2 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 24 Jul 2025 22:01:42 +0800 Subject: [PATCH 19/21] fix unable to open osw profile table --- .../CustomOSCViewControl/LayoutOnScreenControlsViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 52e5f6c2..e1ca4231 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -627,7 +627,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]; } } From ce21c398b5daa138d4ada798d83f77e54a9a8447 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Fri, 25 Jul 2025 00:36:04 +0800 Subject: [PATCH 20/21] - fix on-screen widget tool selectedWidgetView bug - update & replace new widget template bin file --- VoidLink/Input/CustomOSC/OSCProfile.h | 3 +- VoidLink/Input/CustomOSC/OSCProfilesManager.h | 2 +- VoidLink/Input/CustomOSC/OSCProfilesManager.m | 12 +++++--- VoidLink/Input/OnScreenWidgetView.swift | 2 +- VoidLink/PresetConfigs/widgetTemplates.bin | Bin 50741 -> 125388 bytes .../LayoutOnScreenControlsViewController.m | 28 +++++++++--------- 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/VoidLink/Input/CustomOSC/OSCProfile.h b/VoidLink/Input/CustomOSC/OSCProfile.h index ff22b639..04dc2af5 100644 --- a/VoidLink/Input/CustomOSC/OSCProfile.h +++ b/VoidLink/Input/CustomOSC/OSCProfile.h @@ -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. diff --git a/VoidLink/Input/CustomOSC/OSCProfilesManager.h b/VoidLink/Input/CustomOSC/OSCProfilesManager.h index 93cf5afc..58cc6bf3 100644 --- a/VoidLink/Input/CustomOSC/OSCProfilesManager.h +++ b/VoidLink/Input/CustomOSC/OSCProfilesManager.h @@ -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 diff --git a/VoidLink/Input/CustomOSC/OSCProfilesManager.m b/VoidLink/Input/CustomOSC/OSCProfilesManager.m index fd469676..bc1e0141 100644 --- a/VoidLink/Input/CustomOSC/OSCProfilesManager.m +++ b/VoidLink/Input/CustomOSC/OSCProfilesManager.m @@ -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 { diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift index f2e0c994..cca8b716 100644 --- a/VoidLink/Input/OnScreenWidgetView.swift +++ b/VoidLink/Input/OnScreenWidgetView.swift @@ -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() } diff --git a/VoidLink/PresetConfigs/widgetTemplates.bin b/VoidLink/PresetConfigs/widgetTemplates.bin index 4ca211d17b6f5eaf848555462eb535e404e2e0d3..5d091aa22d00de634a849a2b2cc38df741bac9e3 100755 GIT binary patch literal 125388 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 Q!U&-mplKS)V|>W~000%dDgXcg literal 50741 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 diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index e1ca4231..fd720ff9 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -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]; } @@ -655,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; @@ -663,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; @@ -705,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]; @@ -743,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; @@ -1120,6 +1121,8 @@ - (void) presentProfilesTableView{ [self saveTapped:nil]; + [self clearStickIndicator]; + selectedWidgetView = nil; UIStoryboard *storyboard; BOOL isIPhone = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone); if (isIPhone) { @@ -1144,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]; @@ -1252,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]; } From 87ad97c00f425e7151a4a84f5a71b63fe50ed797 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Fri, 25 Jul 2025 01:09:03 +0800 Subject: [PATCH 21/21] bump up to 1.0.0 --- VoidLink.xcodeproj/project.pbxproj | 4 ++-- VoidLink/Input/PureNativeTouchHandler.m | 22 ++++++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/VoidLink.xcodeproj/project.pbxproj b/VoidLink.xcodeproj/project.pbxproj index f7e9d4fc..021f2f00 100644 --- a/VoidLink.xcodeproj/project.pbxproj +++ b/VoidLink.xcodeproj/project.pbxproj @@ -1148,7 +1148,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 = ""; @@ -1207,7 +1207,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 = ""; diff --git a/VoidLink/Input/PureNativeTouchHandler.m b/VoidLink/Input/PureNativeTouchHandler.m index 3b029709..27c58962 100644 --- a/VoidLink/Input/PureNativeTouchHandler.m +++ b/VoidLink/Input/PureNativeTouchHandler.m @@ -34,6 +34,7 @@ NSMutableSet *pointerIdPool; //pre-defined pool of pointerIds. NSMutableSet *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; }