From 386516ade946f6447481694cb41aa64e6684dd5a Mon Sep 17 00:00:00 2001 From: Acaki Date: Mon, 11 Aug 2025 15:46:08 +0800 Subject: [PATCH 01/17] fix: ios12 compatibility --- VoidLink/AppDelegate.h | 1 + VoidLink/AppDelegate.m | 21 +++++++++++++++++++ VoidLink/SceneDelegate.h | 1 + VoidLink/SceneDelegate.m | 1 + .../StreamFrameViewController.m | 20 +++++++++++++----- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/VoidLink/AppDelegate.h b/VoidLink/AppDelegate.h index 4604f3bf..779b275d 100644 --- a/VoidLink/AppDelegate.h +++ b/VoidLink/AppDelegate.h @@ -10,6 +10,7 @@ @interface AppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) NSString *pcUuidToLoad; @property (strong, nonatomic) void (^shortcutCompletionHandler)(BOOL); diff --git a/VoidLink/AppDelegate.m b/VoidLink/AppDelegate.m index 22f0179e..e1a163ff 100644 --- a/VoidLink/AppDelegate.m +++ b/VoidLink/AppDelegate.m @@ -60,6 +60,27 @@ static NSString* DB_NAME = @"Limelight_iOS.sqlite"; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for command tool customization after application launch (works only when user default is nil) [CommandManager presetDefaultCommands]; + + // For iOS 12 and below, we need to manually create the window + if (@available(iOS 13.0, *)) { + // Scene delegate will handle window creation + } else { + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + + NSString *storyboardName; + if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) { + storyboardName = @"iPad"; + } else { + storyboardName = @"iPhone"; + } + + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil]; + UIViewController *initialViewController = [storyboard instantiateInitialViewController]; + + self.window.rootViewController = initialViewController; + [self.window makeKeyAndVisible]; + } + return YES; } diff --git a/VoidLink/SceneDelegate.h b/VoidLink/SceneDelegate.h index 3a908f88..6763caa0 100644 --- a/VoidLink/SceneDelegate.h +++ b/VoidLink/SceneDelegate.h @@ -1,5 +1,6 @@ #import +API_AVAILABLE(ios(13.0)) @interface SceneDelegate : UIResponder @property (strong, nonatomic) UIWindow * window; diff --git a/VoidLink/SceneDelegate.m b/VoidLink/SceneDelegate.m index 58344cfd..275aaedc 100644 --- a/VoidLink/SceneDelegate.m +++ b/VoidLink/SceneDelegate.m @@ -1,6 +1,7 @@ #import "SceneDelegate.h" #import "StreamFrameViewController.h" +API_AVAILABLE(ios(13.0)) @implementation SceneDelegate static UIView *_sharedStreamVideoRenderView = nil; diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index 57373ac3..df926aec 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -810,7 +810,9 @@ - (void) returnToMainFrame { // Reset display mode back to default [self updatePreferredDisplayMode:NO]; - [SceneDelegate clearExternalDisplayRenderView]; + if (@available(iOS 13.0, *)) { + [SceneDelegate clearExternalDisplayRenderView]; + } if (_settings.enablePIP) { [self cleanupPiPController]; @@ -834,7 +836,9 @@ if (_streamVideoRenderView) { // Remove from current superview before passing it [_streamVideoRenderView removeFromSuperview]; - [SceneDelegate setExternalDisplayRenderView:_streamVideoRenderView]; + if (@available(iOS 13.0, *)) { + [SceneDelegate setExternalDisplayRenderView:_streamVideoRenderView]; + } NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; [nc postNotificationName:@"ScreenChanged" object:self]; } else { @@ -847,7 +851,9 @@ - (void)extScreenDidDisconnect:(NSNotification *)notification { Log(LOG_I, @"External Screen Disconnected"); if(UIScreen.screens.count < 2) { - [SceneDelegate clearExternalDisplayRenderView]; + if (@available(iOS 13.0, *)) { + [SceneDelegate clearExternalDisplayRenderView]; + } // Add the render view back to the local StreamView if AirPlay was active if ([self isAirPlayEnabled]) { if (_streamVideoRenderView && _streamView) { @@ -878,9 +884,13 @@ - (void) reloadAirPlayConfig{ if (UIScreen.screens.count == 1){return;} if (![self isAirPlaying] && [self isAirPlayEnabled]){ - [SceneDelegate setExternalDisplayRenderView:_streamVideoRenderView]; + if (@available(iOS 13.0, *)) { + [SceneDelegate setExternalDisplayRenderView:_streamVideoRenderView]; + } }else if ([self isAirPlaying] && ![self isAirPlayEnabled]){ - [SceneDelegate clearExternalDisplayRenderView]; + if (@available(iOS 13.0, *)) { + [SceneDelegate clearExternalDisplayRenderView]; + } } } From 4cb060f4967df77e27fb8553bff6b61cb211dd1c Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Mon, 11 Aug 2025 19:52:08 +0800 Subject: [PATCH 02/17] - feat: add several on-screen gamepad button widgets --- VoidLink/Input/CommandManager.swift | 7 ++++++- VoidLink/Input/OnScreenWidgetView.swift | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/VoidLink/Input/CommandManager.swift b/VoidLink/Input/CommandManager.swift index 2266a801..8d113f1a 100644 --- a/VoidLink/Input/CommandManager.swift +++ b/VoidLink/Input/CommandManager.swift @@ -90,7 +90,12 @@ import UIKit "OSCDOWN" : DOWN_FLAG, "OSCLEFT" : LEFT_FLAG, "OSCRIGHT" : RIGHT_FLAG, - "DS4TOUCH" : TOUCHPAD_FLAG, + "DS4TCHBTN" : TOUCHPAD_FLAG, + "PADDLE1" : PADDLE1_FLAG, + "PADDLE2" : PADDLE2_FLAG, + "PADDLE3" : PADDLE3_FLAG, + "PADDLE4" : PADDLE4_FLAG, + "MISC" : MISC_FLAG, "OSCL2" : 0, "L2" : 0, "LT" : 0, diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift index d802b1f3..852cfe41 100644 --- a/VoidLink/Input/OnScreenWidgetView.swift +++ b/VoidLink/Input/OnScreenWidgetView.swift @@ -194,7 +194,7 @@ import UIKit case "RSPAD", "RSVPAD": self.comboButtonStrings = ["OSCR3"] case "DS4TOUCH": - self.comboButtonStrings = ["DS4TOUCH"] + self.comboButtonStrings = ["DS4TCHBTN"] default: break } } From 1f4865c4686963abf351a32f694d28a9ff09c72c Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Mon, 11 Aug 2025 23:32:00 +0800 Subject: [PATCH 03/17] - insert videoRenderView for iOS12 --- VoidLink/ViewControllers/StreamFrameViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index df926aec..64f287e8 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -369,6 +369,7 @@ }); } } else { + [self->_streamView insertSubview:self->_streamVideoRenderView atIndex:0]; // Fallback on earlier versions } From 5cf9ea74f47898da70cfa32c031fd21c1d95578b Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Tue, 12 Aug 2025 01:26:27 +0800 Subject: [PATCH 04/17] iOS 12 compatibility: settings menu --- .../ViewControllers/SettingsViewController.m | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 0bb1cba4..12b28d78 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -941,6 +941,7 @@ BOOL isCustomResolution(int resolutionSelected) { } else { [button setTitle:@"info" forState:UIControlStateNormal]; button.titleLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightBold]; + button.titleLabel.accessibilityIdentifier = @"infoButton"; } button.accessibilityIdentifier = @"infoButton"; button.translatesAutoresizingMaskIntoConstraints = NO; @@ -1288,14 +1289,17 @@ BOOL isCustomResolution(int resolutionSelected) { _bitrate = bitrateTable[[self getSliderValueForBitrate:[currentSettings.bitrate intValue]]]; // Get the size of the screen with and without safe area insets - UIWindow *window = UIApplication.sharedApplication.windows.firstObject; - CGFloat screenScale = window.screen.scale; - CGFloat safeAreaWidth = (window.frame.size.width - window.safeAreaInsets.left - window.safeAreaInsets.right) * screenScale; - CGFloat fullScreenWidth = window.frame.size.width * screenScale; - CGFloat fullScreenHeight = window.frame.size.height * screenScale; + // UIWindow *window = UIApplication.sharedApplication.windows.firstObject; + // CGFloat screenScale = window.screen.scale; + // CGFloat safeAreaWidth = (window.frame.size.width - window.safeAreaInsets.left - window.safeAreaInsets.right) * screenScale; + // CGFloat fullScreenWidth = window.frame.size.width * screenScale; + // CGFloat fullScreenHeight = window.frame.size.height * screenScale; [self.resolutionSelector removeSegmentAtIndex:0 animated:NO]; // remove 360p [self.resolutionSelector removeSegmentAtIndex:5 animated:NO]; // remove custom segment + // iOS12 compatibility: + self.resolutionSelector.selectedSegmentIndex = 3; + [self.resolutionSelector setNeedsLayout]; resolutionTable[5] = CGSizeMake([currentSettings.width integerValue], [currentSettings.height integerValue]); // custom initial value [self updateResolutionTable]; @@ -1343,7 +1347,7 @@ BOOL isCustomResolution(int resolutionSelected) { // Only enable the 4K option for "recent" devices. We'll judge that by whether // they support HEVC decoding (A9 or later). - [self.resolutionSelector setEnabled:NO forSegmentAtIndex:3]; + [self.resolutionSelector setEnabled:NO forSegmentAtIndex:2]; } switch (currentSettings.preferredCodec) { case CODEC_PREF_AUTO: @@ -2053,7 +2057,16 @@ BOOL isCustomResolution(int resolutionSelected) { label.layer.filters = nil; label.textColor = [ThemeManager textColor]; } else { - // Fallback on earlier versions + UIView *view = label; + bool isPartOfSelector = false; + while (view) { + if ([view isKindOfClass:[UISegmentedControl class]]) { + isPartOfSelector = true; + break; + } + view = view.superview; + } + if(!isPartOfSelector) label.textColor = [UIColor whiteColor]; } } [self updateThemeForLabels:subview]; @@ -2067,7 +2080,7 @@ BOOL isCustomResolution(int resolutionSelected) { if (@available(iOS 13.0, *)) { selector.selectedSegmentTintColor = [ThemeManager appSecondaryColor]; } else { - // Fallback on earlier versions + selector.tintColor = [ThemeManager appSecondaryColor]; } } [self updateThemeForSelectors:subview]; @@ -2088,11 +2101,9 @@ BOOL isCustomResolution(int resolutionSelected) { - (void)updateTheme{ self.view.backgroundColor = [ThemeManager appBackgroundColor]; - if (@available(iOS 13.0, *)) { - [self updateThemeForLabels:self.view]; - [self updateThemeForSelectors:self.view]; - [self updateThemeForSliders:self.view]; - } + [self updateThemeForLabels:self.view]; + [self updateThemeForSelectors:self.view]; + [self updateThemeForSliders:self.view]; } - (void) saveSettings { From d73c0ee319e29234fc5f9b4216c88e6471890b1d Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Tue, 12 Aug 2025 13:26:42 +0800 Subject: [PATCH 05/17] iOS12 compatibility: on-screen widget layout Tool --- VoidLink/Localization/Localizable.xcstrings | 69 +++++++++++++++++++ .../LayoutOnScreenControlsViewController.m | 5 +- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index a1275f2c..87f5a3c3 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -1290,6 +1290,29 @@ } } }, + "Del" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "刪除" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "刪除" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "刪除" + } + } + } + }, "Delete" : { "extractionState" : "manual", "localizations" : { @@ -2448,6 +2471,29 @@ } } }, + "Load" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "加載" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "加載" + } + } + } + }, "Local Keyboard Toggle Disabled" : { "extractionState" : "manual", "localizations" : { @@ -4903,6 +4949,29 @@ } } }, + "Undo" : { + "extractionState" : "manual", + "localizations" : { + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "回撤" + } + }, + "zh-Hant" : { + "stringUnit" : { + "state" : "translated", + "value" : "回撤" + } + }, + "zh-HK" : { + "stringUnit" : { + "state" : "translated", + "value" : "回撤" + } + } + } + }, "unlockDisplayOrientationStackTip" : { "extractionState" : "manual", "localizations" : { diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index c5761881..4221d353 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -978,9 +978,11 @@ UIButton *button = (UIButton *)subview; button.imageView.image = [button.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; button.tintColor = [UIColor systemTealColor]; - if(!button.imageView.image){ + if(@available(iOS 13.0, *)) nil; + else{ NSLog(@"missing image %d", button==_saveButton); button.titleLabel.font = [UIFont systemFontOfSize:18 weight:UIFontWeightMedium]; + [button setImage:nil forState:UIControlStateNormal]; if(button==_exitButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Exit"] forState:UIControlStateNormal]; if(button==trashCanButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Del"] forState:UIControlStateNormal]; if(button==undoButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Undo"] forState:UIControlStateNormal]; @@ -988,6 +990,7 @@ if(button==_loadButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Load"] forState:UIControlStateNormal]; if(button==_addButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Add"] forState:UIControlStateNormal]; if(button==_editButton) [button setTitle:[LocalizationHelper localizedStringForKey:@"Edit"] forState:UIControlStateNormal]; + } } [self handleMissingToolBarIcon:subview]; From 9b149a1eb53dc77b97e9ebaec6c882ce9f52c3ff Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 13 Aug 2025 20:05:13 +0800 Subject: [PATCH 06/17] iOS12 compatibility: toolbox menu --- VoidLink/ViewControllers/StreamFrameViewController.m | 1 + VoidLink/ViewControllers/ToolboxViewController.swift | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index 64f287e8..c3a2d89d 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -247,6 +247,7 @@ toolBoxViewController = [[ToolboxViewController alloc] init]; toolBoxViewController.specialEntryDelegate = self; toolBoxViewController.specialEntries = oldToolboxVC.specialEntries; + toolBoxViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; [self presentViewController:toolBoxViewController animated:YES completion:^{ //[self->toolBoxViewController setupConstraints]; }]; diff --git a/VoidLink/ViewControllers/ToolboxViewController.swift b/VoidLink/ViewControllers/ToolboxViewController.swift index 5d446728..e778e9f4 100644 --- a/VoidLink/ViewControllers/ToolboxViewController.swift +++ b/VoidLink/ViewControllers/ToolboxViewController.swift @@ -149,8 +149,8 @@ import UIKit NSLayoutConstraint.activate([ // Set the width and height of the view - view.widthAnchor.constraint(equalTo: view.superview!.widthAnchor, multiplier: isIPhone() ? 0.6 : 0.8), - view.heightAnchor.constraint(equalTo: view.superview!.heightAnchor, multiplier: 0.99), + view.widthAnchor.constraint(equalTo: view.superview!.widthAnchor, multiplier: isIPhone() ? 0.6 : 0.52), + view.heightAnchor.constraint(equalTo: view.superview!.heightAnchor, multiplier: 0.93), // Set the width and height of the view //view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 60), //view.trailingAnchor.constraint(equalTo: view.superview!.trailingAnchor, constant: -60), @@ -310,6 +310,7 @@ import UIKit // Configure cell appearance cell.backgroundColor = .clear // Set background color of the cell cell.textLabel?.textColor = UIColor.white // Set font color of the text + cell.textLabel?.font = UIFont.systemFont(ofSize: 18.5) // Set selected background view From 6e20c126c37ff08e118f0f73dfdfdd420b0ab236 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 13 Aug 2025 23:25:02 +0800 Subject: [PATCH 07/17] - iOS compatibility: on-screen widget profile tableView --- VoidLink/Base.lproj/iPad.storyboard | 28 +++++++++---------- VoidLink/Base.lproj/iPhone.storyboard | 10 +++---- .../LayoutOnScreenControlsViewController.m | 2 ++ .../OSCProfilesTableViewController.m | 2 +- .../ToolboxViewController.swift | 5 ++-- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard index 97966d35..fcdd15f5 100644 --- a/VoidLink/Base.lproj/iPad.storyboard +++ b/VoidLink/Base.lproj/iPad.storyboard @@ -1618,11 +1618,11 @@ - + - - + + @@ -1663,13 +1663,13 @@ - - - - - - - + + + + + + + @@ -1696,19 +1696,19 @@ - + - + - + - + diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard index 43bc87b4..c847fdfa 100644 --- a/VoidLink/Base.lproj/iPhone.storyboard +++ b/VoidLink/Base.lproj/iPhone.storyboard @@ -676,12 +676,12 @@ - + - - + + @@ -727,8 +727,8 @@ - - + + diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 4221d353..89c4d540 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -1224,6 +1224,8 @@ _oscProfilesTableViewController.currentOSCButtonLayers = self.layoutOSC.OSCButtonLayers; + // _oscProfilesTableViewController.modalPresentationStyle = UIModalPresentationCurrentContext; + _oscProfilesTableViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext; [self presentViewController:_oscProfilesTableViewController animated:YES completion:nil]; } diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m index 06546075..ddbaa1af 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m @@ -85,7 +85,7 @@ const double NAV_BAR_HEIGHT = 50; forCellReuseIdentifier:@"Cell"]; // Register the custom cell nib file with the table view self.tableView.alpha = 0.7; //self.tableView.backgroundColor = [[UIColor colorWithRed:0.5 green:0.7 blue:1.0 alpha:1.0] colorWithAlphaComponent:0.2]; // set background color & transparency - self.tableView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.1]; // set background color & transparency + self.tableView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; // set background color & transparency // self.tableView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2]; // set background color & transparency } diff --git a/VoidLink/ViewControllers/ToolboxViewController.swift b/VoidLink/ViewControllers/ToolboxViewController.swift index e778e9f4..37d07f9b 100644 --- a/VoidLink/ViewControllers/ToolboxViewController.swift +++ b/VoidLink/ViewControllers/ToolboxViewController.swift @@ -26,7 +26,7 @@ import UIKit private let exitButton = UIButton(type: .system) private let pinButton = UIButton(type: .system) private let viewBackgroundColor = UIColor(white: 0.2, alpha: 0.8); - private let highlightColor = UIColor(white: 0.39, alpha: 0.8); + private let highlightColor = UIColor(white: 0.55, alpha: 0.8); private let titleLabel = UILabel() @objc public var specialEntries : NSMutableArray = ["widgetSwitchTool", "widgetLayoutTool", "bringUpSoftKeyboard", "enterPip"] private let specialEntryAliasDic : [String:String] = [ @@ -88,7 +88,8 @@ import UIKit view.backgroundColor = viewBackgroundColor tableView.backgroundColor = .clear tableView.rowHeight = isIPhone() ? 47 : 60 - tableView.separatorColor = highlightColor + tableView.separatorColor = .white.withAlphaComponent(0.33) + tableView.separatorInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) // Configure buttons addButton.setTitle(SwiftLocalizationHelper.localizedString(forKey: "Add / Duplicate"), for: .normal) deleteButton.setTitle(SwiftLocalizationHelper.localizedString(forKey: "Delete"), for: .normal) From 9d2f7704c7df9fa0a199334a949391d6841f6102 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 13 Aug 2025 23:34:29 +0800 Subject: [PATCH 08/17] iOS12 fix: widget layout tool trashcan button --- .../LayoutOnScreenControlsViewController.m | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 89c4d540..52a83fe2 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -1241,7 +1241,8 @@ OnScreenWidgetView* widget = (OnScreenWidgetView* )sender; [self.layoutOSC updateGuidelinesForOnScreenWidget:widget]; [self.view bringSubviewToFront:widget]; - trashCanButton.tintColor = [self layerIsOverlappingWithTrashcanButton:widget.layer] ? [UIColor redColor] : trashCanStoryBoardColor; + trashCanButton.tintColor = trashCanButton.titleLabel.textColor = [self layerIsOverlappingWithTrashcanButton:widget.layer] ? [UIColor redColor] : trashCanStoryBoardColor; + self.undoButton.alpha = 1.0; } @@ -1292,10 +1293,8 @@ // -------- for OSC buttons [self.layoutOSC touchesMoved:touches withEvent:event]; - if ([self layerIsOverlappingWithTrashcanButton:self.layoutOSC.layerBeingDragged]) { // check if user is dragging around a button and hovering it over the trash can button - trashCanButton.tintColor = [UIColor redColor]; - } - else trashCanButton.tintColor = trashCanStoryBoardColor; + + trashCanButton.tintColor = trashCanButton.tintColor = [self layerIsOverlappingWithTrashcanButton:self.layoutOSC.layerBeingDragged] ? [UIColor redColor] : trashCanStoryBoardColor; } - (bool)touchWithinTashcanButton:(UITouch* )touch { @@ -1369,7 +1368,7 @@ } - trashCanButton.tintColor = trashCanStoryBoardColor; + trashCanButton.tintColor = trashCanButton.titleLabel.textColor = trashCanStoryBoardColor; widgetPanelMovedByTouch = false; } From ccc85772d39b3c454661b2c6d4cf0ccf2cb83601 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Wed, 13 Aug 2025 23:52:48 +0800 Subject: [PATCH 09/17] iOS 12 fix: UIAppView playIcon --- .../play.circle.fill.imageset/play.circle.fill.svg | 6 +++--- VoidLink/UIAppView.m | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/VoidLink/Images.xcassets/play.circle.fill.imageset/play.circle.fill.svg b/VoidLink/Images.xcassets/play.circle.fill.imageset/play.circle.fill.svg index c5320593..2d77d137 100644 --- a/VoidLink/Images.xcassets/play.circle.fill.imageset/play.circle.fill.svg +++ b/VoidLink/Images.xcassets/play.circle.fill.imageset/play.circle.fill.svg @@ -3,9 +3,9 @@ - + - - + + diff --git a/VoidLink/UIAppView.m b/VoidLink/UIAppView.m index 54d9793b..b69b34f8 100644 --- a/VoidLink/UIAppView.m +++ b/VoidLink/UIAppView.m @@ -183,8 +183,10 @@ static UIImage* noImage; _appOverlay = playIcon; } else { - _appOverlay = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Play"]]; - + UIImageView* playIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"play.circle.fill"]]; + playIcon.tintColor = [[UIColor blackColor] colorWithAlphaComponent:0.55]; + _appOverlay = playIcon; + } From 2bf39aeb2ea2569ea2c4f3138e7251ece271cbae Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 00:01:53 +0800 Subject: [PATCH 10/17] waterMark for iOS12 --- .../ViewControllers/MainFrameViewController.m | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index e22244bd..687ef78c 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -1211,7 +1211,7 @@ static NSMutableSet* hostList; - (void)waterMarkTapped { // Handle the tap action here, e.g., open a URL - NSURL *url = [NSURL URLWithString:@"https://www.wolai.com/k8RVqMrgYgC9NB4tXdz46H"]; + NSURL *url = [NSURL URLWithString:[LocalizationHelper localizedStringForKey:@"supportLink"]]; if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; } @@ -1231,7 +1231,8 @@ static NSMutableSet* hostList; - (void)attachWaterMark { // Create and configure the label - if(false){ + if (@available(iOS 13.0, *)) return; + else { [self->waterMark removeFromSuperview]; self->waterMark = [[UILabel alloc] init]; self->waterMark.translatesAutoresizingMaskIntoConstraints = NO; @@ -1240,18 +1241,8 @@ static NSMutableSet* hostList; self->waterMark.text = [LocalizationHelper localizedStringForKey:@"waterMarkText"]; CGFloat labelHeight = 60; // the app is unable to automatically lock screen orientation in app window resizable mode(aka. not require fullscreen) - - // if(![self isFullScreenRequired]){ - if(false){ - NSString* screenRotationTip = [LocalizationHelper localizedStringForKey:@"screenRotationTIp"]; - self->waterMark.text = [NSString stringWithFormat:@"%@\n%@", self->waterMark.text, screenRotationTip]; - self->waterMark.numberOfLines = 0; // Allow multiline text - self->waterMark.font = [UIFont systemFontOfSize:19]; - labelHeight = 80; - } - - self->waterMark.textColor = UIColor.blackColor; - self->waterMark.alpha = 0.35; + self->waterMark.textColor = UIColor.whiteColor; + self->waterMark.alpha = 0.2; self->waterMark.textAlignment = NSTextAlignmentCenter; self->waterMark.backgroundColor = [UIColor clearColor]; self->waterMark.userInteractionEnabled = YES; // Enable user interaction for tap gesture From 087e38c9d755f40f7e3cadb97a8dff36ae6bda18 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 00:32:47 +0800 Subject: [PATCH 11/17] change default selected resolution index --- .../Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents index c49f6af2..09e011ee 100644 --- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents +++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents @@ -46,7 +46,7 @@ - + From e844b5df65edbcad0b1bc69f5a61509a00a3c345 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 00:57:13 +0800 Subject: [PATCH 12/17] disable external display settings stack for iOS12 --- VoidLink/ViewControllers/SettingsViewController.m | 4 +++- VoidLink/ViewControllers/StreamFrameViewController.m | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 12b28d78..71de503d 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -573,7 +573,9 @@ BOOL isCustomResolution(int resolutionSelected) { if (@available(iOS 13.0, *)) { [peripheralSection setSectionWithIcon:[UIImage imageNamed:@"cable.connector.video"] andSize:20]; } - [self addSetting:self.externalDisplayModeStack ofId:@"externalDisplayModeStack" withInfoTag:YES withDynamicLabel:NO to:peripheralSection]; + if (@available(iOS 13.0, *)) { + [self addSetting:self.externalDisplayModeStack ofId:@"externalDisplayModeStack" withInfoTag:YES withDynamicLabel:NO to:peripheralSection]; + } [self addSetting:self.localMousePointerModeStack ofId:@"localMousePointerModeStack" withInfoTag:YES withDynamicLabel:NO to:peripheralSection]; [self addSetting:self.reverseMouseWheelDirectionStack ofId:@"reverseMouseWheelDirectionStack" withInfoTag:NO withDynamicLabel:NO to:peripheralSection]; [self addSetting:self.citrixX1MouseStack ofId:@"citrixX1MouseStack" withInfoTag:NO withDynamicLabel:NO to:peripheralSection]; diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m index c3a2d89d..089fe14e 100644 --- a/VoidLink/ViewControllers/StreamFrameViewController.m +++ b/VoidLink/ViewControllers/StreamFrameViewController.m @@ -834,7 +834,7 @@ - (void)extScreenDidConnect:(NSNotification *)notification { Log(LOG_I, @"External Screen Connected"); if ([self isAirPlayEnabled] && [notification.object isKindOfClass:[UIScreen class]]) { - UIScreen *extScreen = (UIScreen *)notification.object; + // UIScreen *extScreen = (UIScreen *)notification.object; if (_streamVideoRenderView) { // Remove from current superview before passing it [_streamVideoRenderView removeFromSuperview]; From ee370ec97886f941da367276b5420e51850d59f3 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 01:04:10 +0800 Subject: [PATCH 13/17] iOS 12 fix: docked navigation bar tint color --- VoidLink/ViewControllers/SWRevealViewController.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/VoidLink/ViewControllers/SWRevealViewController.m b/VoidLink/ViewControllers/SWRevealViewController.m index eb08e380..7fd9b381 100755 --- a/VoidLink/ViewControllers/SWRevealViewController.m +++ b/VoidLink/ViewControllers/SWRevealViewController.m @@ -940,14 +940,15 @@ const int FrontViewPositionNone = 0xff; _dockedNavBar.standardAppearance = navBarAppearanceStandard; _dockedNavBar.scrollEdgeAppearance = navBarAppearanceStandard; } else { - _dockedNavBar.backgroundColor = [UIColor clearColor]; - _dockedNavBar.backgroundColor = [ThemeManager appBackgroundColor]; + _dockedNavBar.barTintColor = [UIColor clearColor]; + _dockedNavBar.barTintColor = [ThemeManager appBackgroundColor]; _dockedNavBar.shadowImage = [UIImage new]; // remove bottom line for navbar } // 创建导航项 - _navItem = [[UINavigationItem alloc] initWithTitle:[LocalizationHelper localizedStringForKey:@"Settings"]]; + if (@available(iOS 13.0, *)) _navItem = [[UINavigationItem alloc] initWithTitle:[LocalizationHelper localizedStringForKey:@"Settings"]]; + else _navItem = [[UINavigationItem alloc] initWithTitle:@""]; [self setupBackButton]; From 6a2c3d7b286f693cb8b2bb811d30930dce763497 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 01:28:23 +0800 Subject: [PATCH 14/17] settings stack gyro check --- VoidLink/ViewControllers/SettingsViewController.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 71de503d..49f3d2d3 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -1403,6 +1403,8 @@ BOOL isCustomResolution(int resolutionSelected) { [self.gyroModeSelector setEnabled:false forSegmentAtIndex:1]; [self.gyroModeSelector setEnabled:false forSegmentAtIndex:3]; } + CMMotionManager *motionManager = [[CMMotionManager alloc] init]; + [self.gyroModeSelector setEnabled:[motionManager isGyroAvailable] forSegmentAtIndex:2]; [self.emulatedControllerTypeSelector setSelectedSegmentIndex:[self controllerTypeToSegmentIndex:currentSettings.emulatedControllerType.intValue]]; [self.emulatedControllerTypeSelector addTarget:self action:@selector(emulatedControllerTypeChanged:) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved. From dd6dbdf1aa58d1b12c8133ec36a6fb363a1d1f1a Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 02:10:55 +0800 Subject: [PATCH 15/17] localization fix --- VoidLink/Localization/Localizable.xcstrings | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings index 87f5a3c3..56c0ec09 100644 --- a/VoidLink/Localization/Localizable.xcstrings +++ b/VoidLink/Localization/Localizable.xcstrings @@ -493,27 +493,21 @@ "Add Host" : { "extractionState" : "manual", "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "添加主机" - } - }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "添加主机" } }, "zh-Hant" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "新增主機" } }, "zh-HK" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "新增主機" } } From 83593a0ea7603147f9a0775e0302e1734bddf756 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 02:17:55 +0800 Subject: [PATCH 16/17] iOS 12 widget layout tool trashcan button fix 2 --- .../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 52a83fe2..1fdeb0e5 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -1294,7 +1294,7 @@ // -------- for OSC buttons [self.layoutOSC touchesMoved:touches withEvent:event]; - trashCanButton.tintColor = trashCanButton.tintColor = [self layerIsOverlappingWithTrashcanButton:self.layoutOSC.layerBeingDragged] ? [UIColor redColor] : trashCanStoryBoardColor; + trashCanButton.tintColor = trashCanButton.titleLabel.textColor = [self layerIsOverlappingWithTrashcanButton:self.layoutOSC.layerBeingDragged] ? [UIColor redColor] : trashCanStoryBoardColor; } - (bool)touchWithinTashcanButton:(UITouch* )touch { From 85e6eb9eb6b96a4c40e805445186243f42112962 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Thu, 14 Aug 2025 09:11:03 +0800 Subject: [PATCH 17/17] deployment target: iOS 12.0 --- VoidLink.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VoidLink.xcodeproj/project.pbxproj b/VoidLink.xcodeproj/project.pbxproj index b47186eb..78820fb7 100644 --- a/VoidLink.xcodeproj/project.pbxproj +++ b/VoidLink.xcodeproj/project.pbxproj @@ -1182,7 +1182,7 @@ INFOPLIST_FILE = "VoidLink/Limelight-Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = "VoidLink - beta"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.games"; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks",