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",