diff --git a/VoidLink/HostCardView.m b/VoidLink/HostCardView.m index c394f9e7..735a2b2c 100644 --- a/VoidLink/HostCardView.m +++ b/VoidLink/HostCardView.m @@ -425,7 +425,6 @@ static const float REFRESH_CYCLE = 2.0f; [self.transparentButton.bottomAnchor constraintEqualToAnchor:self.separatorLine.topAnchor], ]]; - _widthConstraint.constant = _cardContentpadding*2 + appButtonWidth + 15*_sizeFactor + launchButtonWidth; _heightConstraint.constant = _cardContentpadding*2 + _iconBackgroundView.frame.size.height + iconAndButtonSpacing + buttonHeight + 1; diff --git a/VoidLink/ViewControllers/HostCollectionViewController.m b/VoidLink/ViewControllers/HostCollectionViewController.m index e7db7cba..e3f3ac31 100644 --- a/VoidLink/ViewControllers/HostCollectionViewController.m +++ b/VoidLink/ViewControllers/HostCollectionViewController.m @@ -56,11 +56,13 @@ static const CGFloat cellOffsetY = 20; if (!self.cardView) { self.cardView = [[HostCardView alloc] initWithHost:host andSizeFactor:[self getHostCardSizeFactor]]; [self assignDelegateForHostCard]; - [self.contentView addSubview:self.cardView]; - [NSLayoutConstraint activateConstraints:@[ - [self.cardView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor], - [self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0], - ]]; + if(!self.cardView.superview){ + [self.contentView addSubview:self.cardView]; + [NSLayoutConstraint activateConstraints:@[ + [self.cardView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor], + [self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0], + ]]; + } } } @@ -69,6 +71,7 @@ static const CGFloat cellOffsetY = 20; @interface HostCollectionViewController () @property (nonatomic, strong, readwrite) NSMutableArray *items; @property (nonatomic, strong) NSLayoutConstraint *collectionViewHeightConstraint; +@property (nonatomic, strong) NSLayoutConstraint *superViewBottomConstraint; @end @implementation HostCollectionViewController{ @@ -129,6 +132,8 @@ static const CGFloat cellOffsetY = 20; - (void)addHost:(TemporaryHost *)host { if(![self.items containsObject:host]){ + [self.items addObject:host]; + [self.items addObject:host]; [self.items addObject:host]; [self.collectionView reloadData]; } @@ -173,9 +178,10 @@ static const CGFloat cellOffsetY = 20; CGFloat contentHeight = self.collectionView.collectionViewLayout.collectionViewContentSize.height; bool contentExceedsView = contentHeight > self.view.superview.bounds.size.height - self.view.frame.origin.y; if(contentExceedsView){ - [NSLayoutConstraint activateConstraints:@[ - [self.view.bottomAnchor constraintEqualToAnchor:self.view.superview.safeAreaLayoutGuide.bottomAnchor constant:0] - ]]; + if(!_superViewBottomConstraint){ + _superViewBottomConstraint = [self.view.bottomAnchor constraintEqualToAnchor:self.view.superview.safeAreaLayoutGuide.bottomAnchor constant:0]; + _superViewBottomConstraint.active = YES; + } } else{ _collectionViewHeightConstraint.constant = contentHeight; diff --git a/VoidLink/ViewControllers/MainFrameViewController.m b/VoidLink/ViewControllers/MainFrameViewController.m index 8e9c17a0..a315876b 100644 --- a/VoidLink/ViewControllers/MainFrameViewController.m +++ b/VoidLink/ViewControllers/MainFrameViewController.m @@ -1134,20 +1134,6 @@ static NSMutableSet* hostList; } } - -- (void)handleOrientationChange { - // UIDeviceOrientation targetOrientation = [[UIDevice currentDevice] orientation]; - // if([self isIPhone] && UIDeviceOrientationIsPortrait(targetOrientation)) [self simulateSettingsButtonPressClose]; // on iphone, force close settings views if target orietation is portrait. - double delayInSeconds = 0.7; - // Convert the delay into a dispatch_time_t value - dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); - // Perform some task after the delay - dispatch_after(delayTime, dispatch_get_main_queue(), ^{// Code to execute after the delay - // [self updateResolutionAccordingly]; - // [self.settingsButton setEnabled:![self isIPhonePortrait]]; //make sure settings button is disabled in iphone portrait mode. - }); -} - // currently obselete: - (void) setNeedsUpdateAllowedOrientation{ if (@available(iOS 16.0, *)) { @@ -1283,7 +1269,7 @@ static NSMutableSet* hostList; // Create and configure the label if (@available(iOS 13.0, *)) return; else { - [self->waterMark removeFromSuperview]; + [self->waterMark removeFromSuperview]; // removed before activate contraint self->waterMark = [[UILabel alloc] init]; self->waterMark.translatesAutoresizingMaskIntoConstraints = NO; self->waterMark.numberOfLines = 1; @@ -1426,31 +1412,6 @@ static NSMutableSet* hostList; return [self isIPhone] ? UINavigationBarHeightIPhone : UINavigationBarHeightIPad; } -- (void)setupHostViewTitle{ - self->hostViewTitleLabel = [[UILabel alloc] init]; - - hostViewTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; - hostViewTitleLabel.numberOfLines = 1; - hostViewTitleLabel.font = [UIFont systemFontOfSize:30 weight:UIFontWeightSemibold]; - hostViewTitleLabel.text = [LocalizationHelper localizedStringForKey:@"Hosts"]; - // CGFloat labelHeight = 60; - - - hostViewTitleLabel.textColor = [ThemeManager textColor]; - hostViewTitleLabel.textAlignment = NSTextAlignmentCenter; - // hostViewTitleLabel.backgroundColor = [UIColor clearColor]; - hostViewTitleLabel.userInteractionEnabled = NO; // Enable user interaction for tap gesture - // Add tap gesture recognizer to handle hyperlink action - [self.view addSubview:hostViewTitleLabel]; - // Set up constraints - [NSLayoutConstraint activateConstraints:@[ - [hostViewTitleLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:0], // Aligns the horizontal center of label to the horizontal center of view - [hostViewTitleLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:25], - [hostViewTitleLabel.heightAnchor constraintEqualToConstant:30], - [hostViewTitleLabel.widthAnchor constraintEqualToConstant:100], - ]]; -} - - (void)applyNavBarAppearance{ if (@available(iOS 13.0, *)) { self.navigationController.navigationBar.standardAppearance.backgroundColor = [UIColor clearColor]; // old ios depend on this, do not remove @@ -1572,11 +1533,6 @@ static NSMutableSet* hostList; TemporarySettings* tempSettings = [dataMan getSettings]; [ThemeManager setUserInterfaceStyle:tempSettings.appTheme.intValue]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(deviceOrientationDidChange) // handle orientation change since i made portrait mode available - name:UIDeviceOrientationDidChangeNotification - object:nil]; - #if !TARGET_OS_TV self.settingsExpandedInStreamView = false; // init this flag self.revealViewController.isStreaming = false; //init this flag for rvlVC @@ -1847,10 +1803,6 @@ static NSMutableSet* hostList; [self attachWaterMark]; #if !TARGET_OS_TV - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleOrientationChange) // //force expand settings view to update resolution table, and all setting includes current fullscreen resolution will be updated. - name:UIDeviceOrientationDidChangeNotification - object:nil]; [[self revealViewController] setPrimaryViewController:self]; self.revealViewController.isStreaming = false; // tell the revealViewController streaming is finished @@ -2036,20 +1988,6 @@ static NSMutableSet* hostList; [_discMan resetDiscoveryState]; } -// This function forces immediate decoding of the UIImage, rather -// than the default lazy decoding that results in janky scrolling. --(void)deviceOrientationDidChange{ - if(self.revealViewController.isStreaming || self.collectionView.superview == nil) return; - [NSLayoutConstraint activateConstraints:@[ - [self.collectionView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor], - [self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor], - [self.collectionView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor], - [self.collectionView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor], - //[self.collectionView.heightAnchor constraintEqualToConstant:_headerViewHeight] - ]]; -} - - + (UIImage*) loadBoxArtForCaching:(TemporaryApp*)app { UIImage* boxArt; @@ -2339,19 +2277,18 @@ static NSMutableSet* hostList; self.hostCollectionVC.minimumLineSpacing = 25; // 添加为子控制器 [self addChildViewController:self.hostCollectionVC]; - [self.view addSubview:self.hostCollectionVC.view]; - - // 设置其布局(Auto Layout 示例) - // CGFloat hostCollectionViewPadding = 75; - CGFloat leftPadding = [self isIPhone] ? 30 : 0; - self.hostCollectionVC.view.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - [self.hostCollectionVC.view.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:0], - [self.hostCollectionVC.view.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:leftPadding], - [self.hostCollectionVC.view.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:0], - // [self.hostCollectionVC.view.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:0] //? - ]]; - + + if(self.hostCollectionVC.view.superview == nil){ + [self.view addSubview:self.hostCollectionVC.view]; + CGFloat leftPadding = [self isIPhone] ? 30 : 0; + self.hostCollectionVC.view.translatesAutoresizingMaskIntoConstraints = NO; + [NSLayoutConstraint activateConstraints:@[ + [self.hostCollectionVC.view.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:0], + [self.hostCollectionVC.view.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:leftPadding], + [self.hostCollectionVC.view.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:0], + ]]; + } + // 通知子控制器已添加完成 [self.hostCollectionVC didMoveToParentViewController:self]; diff --git a/VoidLink/ViewControllers/SWRevealViewController.m b/VoidLink/ViewControllers/SWRevealViewController.m index 5bef7431..d0ad012a 100755 --- a/VoidLink/ViewControllers/SWRevealViewController.m +++ b/VoidLink/ViewControllers/SWRevealViewController.m @@ -157,6 +157,13 @@ static CGFloat scaledValue( CGFloat v1, CGFloat min2, CGFloat max2, CGFloat min1 [self insertSubview:_rearNavView belowSubview:_frontView]; [self insertSubview:_safeAreaPadding belowSubview:_frontView]; + [NSLayoutConstraint activateConstraints:@[ + [_safeAreaPadding.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor constant:0], + [_safeAreaPadding.topAnchor constraintEqualToAnchor:self.topAnchor], + [_safeAreaPadding.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], + [_safeAreaPadding.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], + // reserve height for navigation bar + ]]; CGFloat navBarHeight = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone ? UINavigationBarHeightIPhone : UINavigationBarHeightIPad; @@ -263,14 +270,7 @@ static CGFloat scaledValue( CGFloat v1, CGFloat min2, CGFloat max2, CGFloat min1 _frontView.layer.shadowPath = shadowPath.CGPath; _safeAreaPadding.hidden = self.safeAreaLayoutGuide.topAnchor == 0; - [NSLayoutConstraint activateConstraints:@[ - [_safeAreaPadding.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor constant:0], - [_safeAreaPadding.topAnchor constraintEqualToAnchor:self.topAnchor], - [_safeAreaPadding.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], - [_safeAreaPadding.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], - // reserve height for navigation bar - ]]; - + //NSLog(@"width %f", self.bounds.size.width } @@ -984,7 +984,7 @@ const int FrontViewPositionNone = 0xff; [_dockedNavBar setItems:@[_navItem]]; _dockedNavBar.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor]}; - [_dockedNavBar removeFromSuperview]; + [_dockedNavBar removeFromSuperview]; // removed before activate contraints [_contentView.rearNavView addSubview:_dockedNavBar]; // 设置导航栏约束 @@ -995,7 +995,7 @@ const int FrontViewPositionNone = 0xff; [_dockedNavBar.widthAnchor constraintEqualToConstant:_rearViewRevealWidth], ]]; [self layoutSettingsView]; - + // NSLog(@"leak test %f %lu", CACurrentMediaTime(), _contentView.rearNavView.constraints.count); } diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m index 7f995d40..376c405a 100644 --- a/VoidLink/ViewControllers/SettingsViewController.m +++ b/VoidLink/ViewControllers/SettingsViewController.m @@ -31,7 +31,8 @@ NSLayoutConstraint *parentStackLeadingConstraint; NSLayoutConstraint *parentStackWidthConstraint; - + NSLayoutConstraint *parentStackCenterXConstraint; + NSInteger _bitrate; NSInteger _lastSelectedResolutionIndex; bool settingsViewJustLoaded; @@ -503,28 +504,19 @@ BOOL isCustomResolution(int resolutionSelected) { self.scrollView.alwaysBounceVertical = YES; self.scrollView.showsVerticalScrollIndicator = NO; - /* - self.scrollView.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - // [self.scrollView.topAnchor constraintEqualToAnchor:], - [self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], - [self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], - [self.scrollView.topAnchor constraintEqualToAnchor:self.view.topAnchor], - [self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor], - ]]; - */ - _parentStack = [[UIStackView alloc] init]; _parentStack.axis = UILayoutConstraintAxisVertical; _parentStack.spacing = 0; _parentStack.translatesAutoresizingMaskIntoConstraints = NO; - [self.scrollView addSubview:_parentStack]; - [NSLayoutConstraint activateConstraints:@[ - [_parentStack.topAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.topAnchor constant: currentSettingsMenuMode == AllSettings ? [self getStandardNavBarHeight] : [self getStandardNavBarHeight]+10], - [_parentStack.bottomAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.bottomAnchor constant:-20], - ]]; - + if(!_parentStack.superview){ + [self.scrollView addSubview:_parentStack]; + [NSLayoutConstraint activateConstraints:@[ + [_parentStack.topAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.topAnchor constant: currentSettingsMenuMode == AllSettings ? [self getStandardNavBarHeight] : [self getStandardNavBarHeight]+10], + [_parentStack.bottomAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.bottomAnchor constant:-20], + ]]; + } + [self updateParentStackHorizontalConstraints]; } @@ -534,10 +526,10 @@ BOOL isCustomResolution(int resolutionSelected) { - (void)updateParentStackHorizontalConstraints{ if(![self isIPhone]){ - [NSLayoutConstraint activateConstraints:@[ - [_parentStack.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant: 0], //mark: settingMenuLayout - [_parentStack.widthAnchor constraintEqualToAnchor:self.view.widthAnchor constant:-20] // section width adjusted here - ]]; + if(parentStackCenterXConstraint && parentStackWidthConstraint) [NSLayoutConstraint deactivateConstraints:@[parentStackCenterXConstraint, parentStackWidthConstraint]]; + parentStackCenterXConstraint = [_parentStack.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant: 0]; //mark: settingMenuLayout + parentStackWidthConstraint = [_parentStack.widthAnchor constraintEqualToAnchor:self.view.widthAnchor constant:-20]; // section width adjusted here + [NSLayoutConstraint activateConstraints:@[parentStackCenterXConstraint, parentStackWidthConstraint]]; return; } @@ -552,7 +544,8 @@ BOOL isCustomResolution(int resolutionSelected) { currentOrientation = activeScene.interfaceOrientation; } else currentOrientation = keyWindow.windowScene.interfaceOrientation; - + + if(parentStackLeadingConstraint && parentStackWidthConstraint) [NSLayoutConstraint deactivateConstraints:@[parentStackLeadingConstraint, parentStackWidthConstraint]]; switch (currentOrientation) { case UIInterfaceOrientationLandscapeRight: parentStackLeadingConstraint = [_parentStack.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:0]; @@ -567,8 +560,7 @@ BOOL isCustomResolution(int resolutionSelected) { } else { // Fallback on earlier versions } - - + double delayInSeconds = 0.05; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^{ @@ -677,10 +669,10 @@ BOOL isCustomResolution(int resolutionSelected) { } } -- (void)addSetting:(UIStackView *)stack ofId:(NSString* )identifier withInfoTag:(BOOL)attched withDynamicLabel:(BOOL)added to:(MenuSectionView* )menuSection{ +- (void)addSetting:(UIStackView *)stack ofId:(NSString* )identifier withInfoTag:(BOOL)attached withDynamicLabel:(BOOL)added to:(MenuSectionView* )menuSection{ stack.accessibilityIdentifier = identifier; [_settingStackDict setObject:stack forKey:identifier]; - if(attched) [self attachInfoTagForStack:stack]; + if(attached) [self attachInfoTagForStack:stack]; if(added) [self addDynamicLabelForStack:stack]; [menuSection addSubStackView:stack]; }