diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard
index 81041b7f..da9da172 100644
--- a/VoidLink/Base.lproj/iPad.storyboard
+++ b/VoidLink/Base.lproj/iPad.storyboard
@@ -1181,6 +1181,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1251,6 +1271,8 @@
+
+
diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard
index 811d035d..1b57962e 100644
--- a/VoidLink/Base.lproj/iPhone.storyboard
+++ b/VoidLink/Base.lproj/iPhone.storyboard
@@ -1910,6 +1910,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1979,6 +1999,8 @@
+
+
diff --git a/VoidLink/Database/DataManager.h b/VoidLink/Database/DataManager.h
index b9e2e4a0..792b9eef 100644
--- a/VoidLink/Database/DataManager.h
+++ b/VoidLink/Database/DataManager.h
@@ -108,7 +108,8 @@ typedef NS_ENUM(NSInteger, WidgetSizeTransition) {
graphOpacity:(NSInteger)graphOpacity
renderingBackend:(NSInteger)renderingBackend
framePacingMode:(NSInteger)framePacingMode
- sendDummyEvent:(BOOL)sendDummyEvent
+ sendDummyEvent:(BOOL)sendDummyEvent
+ rememberFoldState:(BOOL)rememberFoldState
backgroundSessionTimer:(NSInteger)backgroundSessionTimer;
- (NSArray*) getHosts;
diff --git a/VoidLink/Database/DataManager.m b/VoidLink/Database/DataManager.m
index 9e99ade6..efd68206 100644
--- a/VoidLink/Database/DataManager.m
+++ b/VoidLink/Database/DataManager.m
@@ -103,7 +103,8 @@
graphOpacity:(NSInteger)graphOpacity
renderingBackend:(NSInteger)renderingBackend
framePacingMode:(NSInteger)framePacingMode
- sendDummyEvent:(BOOL)sendDummyEvent
+ sendDummyEvent:(BOOL)sendDummyEvent
+ rememberFoldState:(BOOL)rememberFoldState
backgroundSessionTimer:(NSInteger)backgroundSessionTimer{
[_managedObjectContext performBlockAndWait:^{
@@ -159,6 +160,7 @@
settingsToSave.renderingBackend = [NSNumber numberWithInteger:renderingBackend];
settingsToSave.framePacingMode = [NSNumber numberWithInteger:framePacingMode];
settingsToSave.sendDummyEvent = sendDummyEvent;
+ settingsToSave.rememberFoldState = rememberFoldState;
[self saveData];
}];
}
diff --git a/VoidLink/Database/TemporarySettings.h b/VoidLink/Database/TemporarySettings.h
index 8eddd342..f1709fa8 100644
--- a/VoidLink/Database/TemporarySettings.h
+++ b/VoidLink/Database/TemporarySettings.h
@@ -74,6 +74,7 @@
@property (nonatomic, retain) NSNumber * graphOpacity;
@property (nonatomic, retain) NSNumber * renderingBackend;
@property (nonatomic) BOOL sendDummyEvent;
+@property (nonatomic) BOOL rememberFoldState;
@property (nonatomic, retain) NSNumber * framePacingMode;
- (id) initFromSettings:(Settings*)settings;
diff --git a/VoidLink/Database/TemporarySettings.m b/VoidLink/Database/TemporarySettings.m
index 99688693..535e49d0 100644
--- a/VoidLink/Database/TemporarySettings.m
+++ b/VoidLink/Database/TemporarySettings.m
@@ -129,6 +129,7 @@
self.renderingBackend = settings.renderingBackend;
self.framePacingMode = settings.framePacingMode;
self.sendDummyEvent = settings.sendDummyEvent;
+ self.rememberFoldState = settings.rememberFoldState;
self.backgroundSessionTimer = settings.backroundSessionTimer;
#endif
self.uniqueId = settings.uniqueId;
diff --git a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
index 4fb6afb5..0d3b1607 100644
--- a/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
+++ b/VoidLink/Limelight.xcdatamodeld/VoidLink v1.0.xcdatamodel/contents
@@ -55,6 +55,7 @@
+
diff --git a/VoidLink/MenuSectionView.h b/VoidLink/MenuSectionView.h
index 637caeda..00d7ee20 100644
--- a/VoidLink/MenuSectionView.h
+++ b/VoidLink/MenuSectionView.h
@@ -19,11 +19,14 @@
@interface MenuSectionView : UIView
+@property (class, nonatomic, assign) BOOL overridePersistedFoldState;
+
// 外部可访问属性
@property (nonatomic, assign) CGFloat leadingTrailingPadding;
@property (nonatomic, assign) CGFloat separatorLinePadding;
@property (nonatomic, copy) NSString *sectionTitle;
-@property (nonatomic, assign) BOOL expanded;
+@property (nonatomic, copy) NSString *identifier;
+@property (nonatomic, assign) BOOL isExpanded;
@property (nonatomic, strong) UIColor *backgroundColor;
@property (nonatomic, assign) CGFloat rootStackViewSpacing;
@property (nonatomic, assign) CGFloat headerViewHeight;
@@ -40,6 +43,7 @@
- (void)removeSubStackView:(UIStackView *)stackView;
- (void)updateLayout;
- (void)updateViewForFoldState;
+- (void)setExpanded:(BOOL)overridePersistedState;
@end
diff --git a/VoidLink/MenuSectionView.m b/VoidLink/MenuSectionView.m
index eb345ca0..3edc396f 100644
--- a/VoidLink/MenuSectionView.m
+++ b/VoidLink/MenuSectionView.m
@@ -24,6 +24,17 @@
@implementation MenuSectionView
+static BOOL overridePersistedFoldState = YES;
+
++ (BOOL)overridePersistedFoldState {
+ return overridePersistedFoldState;
+}
+
++ (void)setOverridePersistedFoldState:(BOOL)val {
+ overridePersistedFoldState = val;
+}
+
+
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
@@ -45,7 +56,7 @@
_leadingTrailingPadding = 0;
_separatorLinePadding = 40;
_sectionTitle = @"Section";
- _expanded = YES;
+ _isExpanded = YES;
_backgroundColor = [UIColor clearColor];
_rootStackViewSpacing = [self isIPhone] ? 10 : 13.8;
_subStackViews = [NSMutableArray array];
@@ -224,9 +235,10 @@
}
- (void)setExpanded:(BOOL)isExpanded {
- if (_expanded != isExpanded) {
- _expanded = isExpanded;}
- [self updateViewForFoldState];
+ self.isExpanded = isExpanded;
+ [self updateViewForFoldState];
+ [[NSUserDefaults standardUserDefaults] setBool:self.isExpanded forKey:self.identifier];
+ [[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)setBackgroundColor:(UIColor *)backgroundColor {
@@ -262,6 +274,11 @@
[self.leadingAnchor constraintEqualToAnchor:parentStack.leadingAnchor constant:0],
[self.trailingAnchor constraintEqualToAnchor:parentStack.trailingAnchor constant:0],
]];
+
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ BOOL persistedFoldState = [defaults objectForKey:self.identifier] ? [defaults boolForKey:self.identifier] : YES;
+
+ [self setExpanded: MenuSectionView.overridePersistedFoldState ? YES : persistedFoldState];
}
- (void)removeSubStackView:(UIStackView *)stackView {
@@ -306,8 +323,10 @@
}
- (void)toggleFold {
- self.expanded = !self.expanded;
+ self.isExpanded = !self.isExpanded;
[self updateViewForFoldState];
+ [[NSUserDefaults standardUserDefaults] setBool:self.isExpanded forKey:self.identifier];
+ [[NSUserDefaults standardUserDefaults] synchronize];
}
- (SettingsMenuMode)getSettingsMenuMode {
@@ -326,7 +345,7 @@
}
}
self.hidden = visibleCount == 0;
- if (_expanded) {
+ if (_isExpanded) {
_rootStackView.hidden = NO;
_separatorLine.hidden = NO;
CGSize fittingSize = [self.rootStackView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h
index 17e3b332..9974e5b8 100644
--- a/VoidLink/ViewControllers/SettingsViewController.h
+++ b/VoidLink/ViewControllers/SettingsViewController.h
@@ -144,6 +144,9 @@
@property (strong, nonatomic) IBOutlet UIStackView *micVolumeStack;
@property (strong, nonatomic) IBOutlet UISlider *micVolumeSlider;
+@property (strong, nonatomic) IBOutlet UIStackView *rememberFoldStateStack;
+@property (strong, nonatomic) IBOutlet UISwitch *rememberFoldStateSwitch;
+
@property (nonatomic, strong) MicHandler *micHandler;
diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m
index 379dd4ff..85e20ec8 100644
--- a/VoidLink/ViewControllers/SettingsViewController.m
+++ b/VoidLink/ViewControllers/SettingsViewController.m
@@ -372,6 +372,15 @@ BOOL isCustomResolution(int resolutionSelected) {
}
else dispatch_async(dispatch_get_main_queue(), ^{[self widget:self.bitrateSlider setEnabled:true];});
});
+
+ if(currentSettingsMenuMode == AllSettings && MenuSectionView.overridePersistedFoldState){
+ for(UIView *subview in _parentStack.arrangedSubviews){
+ if([subview isKindOfClass:[MenuSectionView class]]){
+ MenuSectionView* section = (MenuSectionView* )subview;
+ [section setExpanded:YES];
+ }
+ }
+ }
}
- (void)viewDidAppear:(BOOL)animated{
@@ -601,6 +610,7 @@ BOOL isCustomResolution(int resolutionSelected) {
videoSection = [[MenuSectionView alloc] init];
videoSection.delegate = self;
videoSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Video"];
+ videoSection.identifier = @"SettingsSectionVideo";
if (@available(iOS 13.0, *)) {
[videoSection setSectionWithIcon:[UIImage systemImageNamed:@"waveform"] andSize:20];
}
@@ -615,11 +625,12 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.frameQueueSizeStack ofId:@"frameQueueSizeStack" withInfoTag:NO withDynamicLabel:YES to:videoSection];
[videoSection addToParentStack:_parentStack];
- [videoSection setExpanded:YES];
+ // [videoSection setExpanded:NO];
touchAndControlSection = [[MenuSectionView alloc] init];
touchAndControlSection.delegate = self;
touchAndControlSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Touch & Controller"];
+ touchAndControlSection.identifier = @"SettingsSectionTouch&Controller";
if (@available(iOS 13.0, *)) {
[touchAndControlSection setSectionWithIcon:[UIImage imageNamed:@"arcade.stick.console"] andSize:20.5];
}
@@ -634,11 +645,12 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.gyroModeStack ofId:@"gyroModeStack" withInfoTag:YES withDynamicLabel:YES to:touchAndControlSection];
[self addSetting:self.gyroSensitivityStack ofId:@"gyroSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:touchAndControlSection];
[touchAndControlSection addToParentStack:_parentStack];
- [touchAndControlSection setExpanded:YES];
+ // [touchAndControlSection setExpanded:NO];
MenuSectionView *gesturesSection = [[MenuSectionView alloc] init];
gesturesSection.delegate = self;
gesturesSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Gestures"];
+ gesturesSection.identifier = @"SettingsSectionGestures";
if (@available(iOS 13.0, *)) {
[gesturesSection setSectionWithIcon:[UIImage systemImageNamed:@"hand.draw"] andSize:23];
}
@@ -648,11 +660,12 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.slideToToolboxScreenEdgeStack ofId:@"slideToToolboxScreenEdgeStack" withInfoTag:NO withDynamicLabel:NO to:gesturesSection];
[self addSetting:self.slideToSettingsDistanceStack ofId:@"slideToSettingsDistanceStack" withInfoTag:YES withDynamicLabel:YES to:gesturesSection];
[gesturesSection addToParentStack:_parentStack];
- [gesturesSection setExpanded:YES];
+ // [gesturesSection setExpanded:NO];
MenuSectionView *peripheralSection = [[MenuSectionView alloc] init];
peripheralSection.delegate = self;
peripheralSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Peripherals"];
+ peripheralSection.identifier = @"SettingsSectionPeripherals";
if (@available(iOS 13.0, *)) {
[peripheralSection setSectionWithIcon:[UIImage imageNamed:@"cable.connector.video"] andSize:20];
}
@@ -663,13 +676,14 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.reverseMouseWheelDirectionStack ofId:@"reverseMouseWheelDirectionStack" withInfoTag:NO withDynamicLabel:NO to:peripheralSection];
[self addSetting:self.citrixX1MouseStack ofId:@"citrixX1MouseStack" withInfoTag:NO withDynamicLabel:NO to:peripheralSection];
[peripheralSection addToParentStack:_parentStack];
- [peripheralSection setExpanded:YES];
+ // [peripheralSection setExpanded:NO];
MenuSectionView *audioSection = [[MenuSectionView alloc] init];
audioSection.delegate = self;
audioSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Audio"];
+ audioSection.identifier = @"SettingsSectionAudio";
if (@available(iOS 13.0, *)) {
[audioSection setSectionWithIcon:[UIImage imageNamed:@"speaker.wave.2"] andSize:20];
}
@@ -681,12 +695,13 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.micVolumeStack ofId:@"micVolumeStack" withInfoTag:NO withDynamicLabel:YES to:audioSection];
[self addSetting:self.audioConfigStack ofId:@"audioConfigStack" withInfoTag:NO withDynamicLabel:NO to:audioSection];
[audioSection addToParentStack:_parentStack];
- [audioSection setExpanded:YES];
+ // [audioSection setExpanded:NO];
otherSection = [[MenuSectionView alloc] init];
otherSection.delegate = self;
otherSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Others"];
+ otherSection.identifier = @"SettingsSectionOthers";
if (@available(iOS 13.0, *)) {
[otherSection setSectionWithIcon:[UIImage systemImageNamed:@"cube"] andSize:20.5];
}
@@ -696,14 +711,16 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.optimizeGamesStack ofId:@"optimizeGamesStack" withInfoTag:YES withDynamicLabel:NO to:otherSection];
[self addSetting:self.multiControllerStack ofId:@"multiControllerStack" withInfoTag:NO withDynamicLabel:NO to:otherSection];
[self addSetting:self.softKeyboardToolbarStack ofId:@"softKeyboardToolbarStack" withInfoTag:NO withDynamicLabel:NO to:otherSection];
+ [self addSetting:self.rememberFoldStateStack ofId:@"rememberFoldStateStack" withInfoTag:NO withDynamicLabel:NO to:otherSection];
[otherSection addToParentStack:_parentStack];
- [otherSection setExpanded:YES];
+ // [otherSection setExpanded:NO];
- experimentalSection = [[MenuSectionView alloc] init];
+ experimentalSection = [[MenuSectionView alloc] init];
experimentalSection.delegate = self;
experimentalSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Experimental"];
+ experimentalSection.identifier = @"SettingsSectionExperimental";
if (@available(iOS 13.0, *)) {
[experimentalSection setSectionWithIcon:[UIImage imageNamed:@"flask"] andSize:20];
}
@@ -716,7 +733,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.sendDummyEventStack ofId:@"sendDummyEventStack" withInfoTag:YES withDynamicLabel:NO to:experimentalSection];
[experimentalSection addToParentStack:_parentStack];
- [experimentalSection setExpanded:YES];
+ // [experimentalSection setExpanded:NO];
}
@@ -1394,7 +1411,16 @@ BOOL isCustomResolution(int resolutionSelected) {
for(UIView* view in self.view.subviews){
[view removeFromSuperview];
}
+
[self initParentStack];
+
+ // load rememberFoldState before section layout
+ dataMan = [[DataManager alloc] init];
+ tempSettings = [dataMan getSettings];
+ [self.rememberFoldStateSwitch setOn:tempSettings.rememberFoldState];// Load old setting
+ MenuSectionView.overridePersistedFoldState = !tempSettings.rememberFoldState;
+ [self.rememberFoldStateSwitch addTarget:self action:@selector(rememberFoldStateSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
+
[self layoutSections];
@@ -1416,8 +1442,6 @@ BOOL isCustomResolution(int resolutionSelected) {
self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
}
- dataMan = [[DataManager alloc] init];
- tempSettings = [dataMan getSettings];
currentSettingsMenuMode = tempSettings.settingsMenuMode.intValue;
[self loadFavoriteSettingStackIdentifiers];
@@ -1819,11 +1843,9 @@ BOOL isCustomResolution(int resolutionSelected) {
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * _Nonnull action) {
- DataManager* directDataMan = [[DataManager alloc] init];
- Settings* directSettings = [directDataMan retrieveSettings];
+ Settings* directSettings = [self->dataMan retrieveSettings];
directSettings.renderingBackend = [NSNumber numberWithInteger:sender.selectedSegmentIndex];
- [directDataMan saveData];
-
+ [self->dataMan saveData];
[self saveSettings];
exit(0);
@@ -2091,6 +2113,13 @@ BOOL isCustomResolution(int resolutionSelected) {
[self setHidden:!sender.isOn forStack:_micVolumeStack];
}
+- (void)rememberFoldStateSwitchFlipped:(UISwitch* )sender{
+ MenuSectionView.overridePersistedFoldState = !sender.isOn;
+ Settings* currentSettings = [self->dataMan retrieveSettings];
+ currentSettings.rememberFoldState = sender.isOn;
+ [self->dataMan saveData];
+}
+
- (void)enableOswForNativeTouchSwitchFlipped:(UISwitch *)sender{
[self setHidden:!sender.isOn forStack:self.onScreenWidgetStack];
[self setHidden:!sender.isOn forStack:self.buttonVisualFeedbackStack];
@@ -2531,6 +2560,7 @@ BOOL isCustomResolution(int resolutionSelected) {
NSInteger externalDisplayMode = [self.externalDisplayModeSelector selectedSegmentIndex];
NSInteger localMousePointerMode = [self.localMousePointerModeSelector selectedSegmentIndex];
BOOL sendDummyEvent = self.sendDummyEventSwitch.isOn;
+ BOOL rememberFoldState = self.rememberFoldStateSwitch.isOn;
NSInteger backgroundSessionTimer = self.backgroundSessionTimerSlider.value == self.backgroundSessionTimerSlider.maximumValue ? (uint32_t) INT16_MAX : (uint32_t)self.backgroundSessionTimerSlider.value;
[dataMan saveSettingsWithBitrate:_bitrate
@@ -2581,6 +2611,7 @@ BOOL isCustomResolution(int resolutionSelected) {
renderingBackend:renderingBackend
framePacingMode:framePacingMode
sendDummyEvent:sendDummyEvent
+ rememberFoldState:rememberFoldState
backgroundSessionTimer:backgroundSessionTimer];
}
diff --git a/VoidLink/mul.lproj/iPad.xcstrings b/VoidLink/mul.lproj/iPad.xcstrings
index da9c114c..af35a93e 100644
--- a/VoidLink/mul.lproj/iPad.xcstrings
+++ b/VoidLink/mul.lproj/iPad.xcstrings
@@ -3535,6 +3535,36 @@
}
}
},
+ "shy-hG-9wY.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Remember Menu Fold/Expand\"; ObjectID = \"shy-hG-9wY\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Remember Menu Fold/Expand"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "记住菜单折叠状态"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "記住選單摺疊狀態"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "記住選單摺疊狀態"
+ }
+ }
+ }
+ },
"t7a-18-5wz.text" : {
"comment" : "Class = \"UILabel\"; text = \"Performance Graphs \"; ObjectID = \"t7a-18-5wz\";",
"extractionState" : "extracted_with_value",
diff --git a/VoidLink/mul.lproj/iPhone.xcstrings b/VoidLink/mul.lproj/iPhone.xcstrings
index 52a1b9bd..055d39a3 100644
--- a/VoidLink/mul.lproj/iPhone.xcstrings
+++ b/VoidLink/mul.lproj/iPhone.xcstrings
@@ -697,6 +697,36 @@
}
}
},
+ "9Kq-ys-dnF.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Remember Menu Fold/Expand\"; ObjectID = \"9Kq-ys-dnF\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Remember Menu Fold/Expand"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "记住菜单折叠状态"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "記住選單摺疊狀態"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "記住選單摺疊狀態"
+ }
+ }
+ }
+ },
"53H-ST-OtY.segmentTitles[0]" : {
"comment" : "Class = \"UISegmentedControl\"; 53H-ST-OtY.segmentTitles[0] = \"Balanced\"; ObjectID = \"53H-ST-OtY\";",
"extractionState" : "extracted_with_value",