diff --git a/VoidLink/Images.xcassets/gamecontroller.circle.regular.imageset/Contents.json b/VoidLink/Images.xcassets/gamecontroller.circle.regular.imageset/Contents.json
new file mode 100644
index 00000000..bb128f53
--- /dev/null
+++ b/VoidLink/Images.xcassets/gamecontroller.circle.regular.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "gamecontroller.circle.svg",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/VoidLink/Images.xcassets/gamecontroller.circle.regular.imageset/gamecontroller.circle.svg b/VoidLink/Images.xcassets/gamecontroller.circle.regular.imageset/gamecontroller.circle.svg
new file mode 100644
index 00000000..71c89fea
--- /dev/null
+++ b/VoidLink/Images.xcassets/gamecontroller.circle.regular.imageset/gamecontroller.circle.svg
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/VoidLink/Images.xcassets/gamecontroller.circle.tag.imageset/Contents.json b/VoidLink/Images.xcassets/gamecontroller.circle.tag.imageset/Contents.json
new file mode 100644
index 00000000..d9d22101
--- /dev/null
+++ b/VoidLink/Images.xcassets/gamecontroller.circle.tag.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "gamecontroller.circle.tag.svg",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/VoidLink/Images.xcassets/gamecontroller.circle.tag.imageset/gamecontroller.circle.tag.svg b/VoidLink/Images.xcassets/gamecontroller.circle.tag.imageset/gamecontroller.circle.tag.svg
new file mode 100644
index 00000000..f3971993
--- /dev/null
+++ b/VoidLink/Images.xcassets/gamecontroller.circle.tag.imageset/gamecontroller.circle.tag.svg
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift
index 65334486..84bf585a 100644
--- a/VoidLink/Input/OnScreenWidgetView.swift
+++ b/VoidLink/Input/OnScreenWidgetView.swift
@@ -19,6 +19,7 @@ import ObjectiveC.runtime
@objc public static var mapping: [Int16:OnScreenWidgetView] = [:]
@objc public static var isRestoring: Bool = false
@objc public static var hasRestoredFromAutoDock: Bool = false
+ @objc public static var autoDockRestoreInitByViewResize: Bool = false
@objc public static func set(widget:OnScreenWidgetView, for key:Int16) {
mapping[key] = widget
}
@@ -694,12 +695,12 @@ import ObjectiveC.runtime
private func tweakAlpha(tweakBorderAlpha:Bool, tweakLabelAlpha:Bool = true){
// setup default border from self.backgroundAlpha
- let realBackgroundAlpha = abs(self.backgroundAlpha) - 0.18 // offset to be consistent with legacy onScreen controller layer opacity
+ let realBackgroundAlpha = max(abs(self.backgroundAlpha) - 0.18, 0) // offset to be consistent with legacy onScreen controller layer opacity
self.backgroundColor = UIColor(white:self.backgroundAlpha>0 ? 0.1 : 0.9, alpha: realBackgroundAlpha) // offset to be consistent with legacy onScreen controller layer opacity
if tweakBorderAlpha {
- borderAlpha = realBackgroundAlpha * 1.01
- defaultBorderColor = UIColor(white: self.backgroundAlpha>0 ? 0.1 : 0.9, alpha: abs(borderAlpha)).cgColor
+ borderAlpha = realBackgroundAlpha * 1.005 * (self.backgroundAlpha>0 ? 1 : -1)
+ defaultBorderColor = UIColor(white: borderAlpha>0 ? 0.1 : 0.9, alpha: abs(borderAlpha)).cgColor
self.layer.borderColor = defaultBorderColor
}
@@ -824,6 +825,9 @@ import ObjectiveC.runtime
private func setSquareWidgetCornerRadius(){
let shortSideLen = min(self.layer.bounds.size.width, self.layer.bounds.size.height)
self.layer.cornerRadius = shortSideLen/2 < 16 ? shortSideLen/3.2 : 16
+ if #available(iOS 13.0, *) {
+ self.layer.cornerCurve = .continuous
+ }
}
func containsNonLatin(_ text: String) -> Bool {
@@ -866,6 +870,7 @@ import ObjectiveC.runtime
)
label.attributedText = attr
label.textAlignment = .center
+ label.baselineAdjustment = .alignCenters
}
private func setupView() {
@@ -900,7 +905,6 @@ import ObjectiveC.runtime
self.translatesAutoresizingMaskIntoConstraints = true // this is mandatory to prevent unexpected key view location change
- self.setSquareWidgetCornerRadius()
self.layer.borderWidth = self.borderWidth
self.tweakAlpha(tweakBorderAlpha: false, tweakLabelAlpha: false)
@@ -927,7 +931,7 @@ import ObjectiveC.runtime
label.isHidden = self.widgetLabel.uppercased() == self.touchPadString // allow touchPad label to be display if it's different from touchPad cmdString
}
}
-
+
if !self.functionalButtonString.isEmpty{
self.layer.borderWidth = self.borderWidth
}
@@ -935,11 +939,10 @@ import ObjectiveC.runtime
if self.shape == "round" {
//setup round buttons
self.layer.cornerRadius = self.frame.width/2
- // self.layer.borderWidth = self.borderWidth
label.minimumScaleFactor = 0.15 // Adjust the scale factor for oscButtons
}
if self.shape == "square" || self.shape == "largeSquare" {
- //just do nothing here
+ self.setSquareWidgetCornerRadius()
}
@@ -1809,6 +1812,9 @@ import ObjectiveC.runtime
buttonDownVisualEffectLayer.borderColor = standardHighlightColor.cgColor
buttonDownVisualEffectLayer.frame = self.bounds.insetBy(dx: -buttonDownVisualEffectLayer.borderWidth, dy: -buttonDownVisualEffectLayer.borderWidth) // Adjust the inset as needed
buttonDownVisualEffectLayer.cornerRadius = self.layer.cornerRadius + buttonDownVisualEffectLayer.borderWidth
+ if self.shape == "square" {if #available(iOS 13.0, *) {
+ buttonDownVisualEffectLayer.cornerCurve = .continuous
+ }}
buttonDownVisualEffectLayer.backgroundColor = UIColor.clear.cgColor;
buttonDownVisualEffectLayer.fillColor = UIColor.clear.cgColor;
@@ -3379,6 +3385,10 @@ import ObjectiveC.runtime
completion: {_ in
self.autoDockIsDocked = false
self.restartAutoDockCountdown()
+ if OnScreenWidgetView.autoDockRestoreInitByViewResize {
+ OnScreenWidgetView.autoDockRestoreInitByViewResize = false
+ OnScreenWidgetView.hasRestoredFromAutoDock = false
+ }
}
)
}
diff --git a/VoidLink/Localization/Localizable.xcstrings b/VoidLink/Localization/Localizable.xcstrings
index d00f6317..cd7df14a 100644
--- a/VoidLink/Localization/Localizable.xcstrings
+++ b/VoidLink/Localization/Localizable.xcstrings
@@ -5488,7 +5488,7 @@
},
"zh-Hant" : {
"stringUnit" : {
- "state" : "needs_review",
+ "state" : "translated",
"value" : "- 螢幕控制項佈局(包含虛擬手把、虛擬按鍵等),以及設定選單中標記 [手把圖示] 的選項(如體感控制參數),皆保存在遊戲配置中。\n\n- 串流過程中,由螢幕 %@ 邊緣向內滑動 %@ 螢幕寬度,即可在工具箱選單中開啟[切換遊戲配置]"
}
},
diff --git a/VoidLink/Utility/GenericUtils.swift b/VoidLink/Utility/GenericUtils.swift
index 2f2e2b38..760e66ed 100644
--- a/VoidLink/Utility/GenericUtils.swift
+++ b/VoidLink/Utility/GenericUtils.swift
@@ -269,7 +269,11 @@ import UIKit
return UIScreen.main.bounds.height
}
-
+ @objc static var iOS18Available: Bool {
+ if #available(iOS 18.0, *) {return true}
+ else {return false}
+ }
+
@objc(parentViewControllerForView:)
static func parentViewController(for view: UIView?) -> UIViewController? {
var responder: UIResponder? = view
diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m
index 2757cbbe..c09cf510 100644
--- a/VoidLink/ViewControllers/MainFrameViewController.m
+++ b/VoidLink/ViewControllers/MainFrameViewController.m
@@ -1613,16 +1613,28 @@ static NSMutableSet* hostList;
[_profilesButton setAction:@selector(profilesButtonTapped)];
if (@available(iOS 13.0, *)) {
[_profilesButton setTitle:nil];
- UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:GenericUtils.liquidGlassEnabled ? 20.5 : 23 weight:UIImageSymbolWeightRegular ];
- UIImage *image = [[UIImage systemImageNamed:@"gamecontroller.circle" withConfiguration:config] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
- [_profilesButton setImage:image];
- _profilesButton.imageInsets = GenericUtils.liquidGlassEnabled ? UIEdgeInsetsMake(0, 0, 0, 0.55) : UIEdgeInsetsMake(10, 10, 0, 0);
- if(GenericUtils.liquidGlassEnabled){
- // if(@available(iOS 26.0, *)) _settingsButton.hidesSharedBackground = YES;
+
+ UIImageSymbolConfiguration *config;
+ UIImage *image;
+ if(GenericUtils.iOS18Available){
+ config = [UIImageSymbolConfiguration configurationWithPointSize:GenericUtils.liquidGlassEnabled ? 20.5 : 23 weight:UIImageSymbolWeightRegular ];
+ image = [[UIImage systemImageNamed: @"gamecontroller.circle" withConfiguration:config] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+ [_profilesButton setImage:image];
+ _profilesButton.imageInsets = GenericUtils.liquidGlassEnabled ? UIEdgeInsetsMake(0, 0, 0, 0.55) : UIEdgeInsetsMake(10, 10, 0, 0);
+ if(GenericUtils.liquidGlassEnabled){
+ _profilesButton.tintColor = ThemeManager.appPrimaryColor;
+ }
+ }
+ else{
+ image = [[UIImage imageNamed: @"gamecontroller.circle.regular"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+ [_profilesButton setImage:image];
+ _profilesButton.imageInsets = UIEdgeInsetsMake(-1.5, 0, -1.5, 0);
_profilesButton.tintColor = ThemeManager.appPrimaryColor;
}
+
+
} else {
- [_profilesButton setTitle:[LocalizationHelper localizedStringForKey:@"Settings"]];
+ [_profilesButton setTitle:[LocalizationHelper localizedStringForKey:@"Game Profile"]];
}
if (@available(iOS 26.0, *)) {
diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m
index 37fb98fa..b5bc10a0 100644
--- a/VoidLink/ViewControllers/SettingsViewController.m
+++ b/VoidLink/ViewControllers/SettingsViewController.m
@@ -1507,15 +1507,23 @@ BOOL isCustomResolution(int resolutionSelected) {
button = [UIButton buttonWithType:UIButtonTypeSystem];
if (@available(iOS 13.0, *)) {
if(stack.isGameProfileSetting){
- UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:14.5 weight:UIImageSymbolWeightRegular];
- [button setImage:[UIImage systemImageNamed:@"gamecontroller.circle" withConfiguration:config] forState:UIControlStateNormal];
+ UIImage* image;
+ if(GenericUtils.iOS18Available){
+ UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:14.5 weight:UIImageSymbolWeightRegular];
+ image = [UIImage systemImageNamed:@"gamecontroller.circle" withConfiguration:config];
+ }
+ else{
+ image = [[UIImage imageNamed: @"gamecontroller.circle.tag"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+ }
+
+ [button setImage:image forState:UIControlStateNormal];
}
else{
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:13.5 weight:UIImageSymbolWeightMedium];
[button setImage:[UIImage systemImageNamed:@"info.circle" withConfiguration:config] forState:UIControlStateNormal];
}
} else {
- [button setTitle:@"info" forState:UIControlStateNormal];
+ [button setTitle:stack.isGameProfileSetting ? @"game" : @"info" forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightBold];
button.titleLabel.accessibilityIdentifier = @"infoButton";
}
diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m
index 41b1e928..6fe07200 100644
--- a/VoidLink/ViewControllers/StreamFrameViewController.m
+++ b/VoidLink/ViewControllers/StreamFrameViewController.m
@@ -551,6 +551,11 @@
name:UIKeyboardWillHideNotification
object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(keyboardDidHide)
+ name:UIKeyboardDidHideNotification
+ object:nil];
+
[safeTimer start];
#endif
}
@@ -767,7 +772,12 @@
[_streamView keyboardWillHide];
}
-- (void)handleAbnormalKeyboards:(NSNotification *)notification{
+- (void)keyboardDidHide{
+ _streamView.bounds = _deviceWindow.bounds;
+ _streamView.frame = _deviceWindow.frame;
+}
+
+- (void)handleNonStandardKeyboard:(NSNotification *)notification{
[_streamView handleNonStandardKeyboard:notification];
}
@@ -1757,7 +1767,10 @@
}
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC));
dispatch_after(delayTime, dispatch_get_main_queue(), ^{
- if(widget.autoDockEnabled) [widget restoreFromAutoDockWithAnimated:true];
+ if(widget.autoDockEnabled){
+ OnScreenWidgetView.autoDockRestoreInitByViewResize = true;
+ [widget restoreFromAutoDockWithAnimated:true];
+ }
});
[coordinator animateAlongsideTransition:^(id _Nonnull context) {