From 049034e5a9094bb5c20dceb8f59b621e84e48dbe Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Sun, 1 Jun 2025 04:06:06 +0800 Subject: [PATCH] - theme - host card actions including long press - add host button --- Limelight/Base.lproj/iPad.storyboard | 17 +- Limelight/FixedTintImageView.h | 14 + Limelight/FixedTintImageView.m | 61 +++ Limelight/HostCardView.h | 13 +- Limelight/HostCardView.m | 432 +++++++++--------- Limelight/ThemeManager.m | 141 +++--- Limelight/UIComputerView.h | 4 +- Limelight/UIComputerView.m | 6 +- .../HostCollectionViewController.h | 1 + .../HostCollectionViewController.m | 53 ++- .../ViewControllers/MainFrameViewController.h | 3 +- .../ViewControllers/MainFrameViewController.m | 258 +++++++++-- .../ViewControllers/SettingsViewController.m | 2 +- Moonlight.xcodeproj/project.pbxproj | 6 + 14 files changed, 628 insertions(+), 383 deletions(-) create mode 100644 Limelight/FixedTintImageView.h create mode 100644 Limelight/FixedTintImageView.m diff --git a/Limelight/Base.lproj/iPad.storyboard b/Limelight/Base.lproj/iPad.storyboard index 3b96e1da..42081400 100644 --- a/Limelight/Base.lproj/iPad.storyboard +++ b/Limelight/Base.lproj/iPad.storyboard @@ -1,9 +1,9 @@ - + - + @@ -12,7 +12,7 @@ - + @@ -41,6 +41,7 @@ + @@ -868,7 +869,7 @@ ICAgICAgICAgICAgICA - + @@ -908,7 +909,7 @@ ICAgICAgICAgICAgICA - + @@ -930,7 +931,7 @@ ICAgICAgICAgICAgICA - + @@ -1270,13 +1271,13 @@ ICAgICAgICAgICAgICA - + - + diff --git a/Limelight/FixedTintImageView.h b/Limelight/FixedTintImageView.h new file mode 100644 index 00000000..b3f746b0 --- /dev/null +++ b/Limelight/FixedTintImageView.h @@ -0,0 +1,14 @@ +// +// FixedTintImageView.h +// Moonlight-ZWM +// +// Created by True砖家 on 2025.6.1. +// Copyright © 2025 True砖家 @ Bilibili. All rights reserved. +// +// MenuSectionView.m + +@interface FixedTintImageView : UIImageView +@end + +@interface FixedTintButton : UIButton +@end diff --git a/Limelight/FixedTintImageView.m b/Limelight/FixedTintImageView.m new file mode 100644 index 00000000..ce7dda00 --- /dev/null +++ b/Limelight/FixedTintImageView.m @@ -0,0 +1,61 @@ +// +// FixedTintImageView.m +// Moonlight-ZWM +// +// Created by Weimin on 2025/6/1. +// Copyright © 2025 Moonlight Game Streaming Project. All rights reserved. +// + +#import "FixedTintImageView.h" + + +@interface FixedTintButton() +@property (nonatomic, strong) UIColor *fixedTintColor; +@end + +@implementation FixedTintButton + +- (void)tintColorDidChange { + [super tintColorDidChange]; + // 强制 tint 保持固定颜色 + if (self.fixedTintColor) { + [self setImage:[self.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; + self.tintColor = self.fixedTintColor; + } +} + +- (void)setTintColor:(UIColor *)tintColor { + _fixedTintColor = tintColor; + [super setTintColor:tintColor]; +} + +@end + + + +@interface FixedTintImageView () +@property (nonatomic, strong) UIColor *fixedTintColor; +@end + +@implementation FixedTintImageView + +- (instancetype)initWithImage:(UIImage *)image { + self = [super initWithImage:[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]]; + if (self) { + // _fixedTintColor = [UIColor systemBlueColor]; // 默认颜色 + if(_fixedTintColor != nil) [super setTintColor:_fixedTintColor]; + } + return self; +} + +- (void)setTintColor:(UIColor *)tintColor { + if(_fixedTintColor == nil && tintColor != nil) _fixedTintColor = tintColor; + if(tintColor != nil) [super setTintColor:tintColor]; +} + +- (void)tintColorDidChange { + // 保持你固定的颜色,忽略系统的暗淡变更 + if(_fixedTintColor != nil) [super setTintColor:_fixedTintColor]; +} + +@end diff --git a/Limelight/HostCardView.h b/Limelight/HostCardView.h index 396dbf7b..a1cc8e87 100644 --- a/Limelight/HostCardView.h +++ b/Limelight/HostCardView.h @@ -10,18 +10,19 @@ #import #import "TemporaryHost.h" - -@protocol HostCardButtonActionDelegate -- (void)leftButtonTappedForHost:(TemporaryHost *)host; -- (void)rightButtonTappedForHost:(TemporaryHost *)host; +@protocol HostCardActionDelegate +- (void)appButtonTappedForHost:(TemporaryHost *)host; +- (void)launchButtonTappedForHost:(TemporaryHost *)host; +- (void)wakeupButtonTappedForHost:(TemporaryHost *)host; - (void)pairButtonTappedForHost:(TemporaryHost *)host; +- (void)hostCardLongPressed:(TemporaryHost *)host view:(UIView *)view; @end -@interface HostCardView : UIView +@interface HostCardView : UIView @property (nonatomic, assign) CGFloat sizeFactor; @property (nonatomic, readonly) CGSize size; -@property (nonatomic, weak) id delegate; // Delegate property +@property (nonatomic, weak) id delegate; // Delegate property - (void)resizeBySizeFactor:(CGFloat)factor; - (id) initWithHost:(TemporaryHost*)host; diff --git a/Limelight/HostCardView.m b/Limelight/HostCardView.m index 93d28370..0a8242a6 100644 --- a/Limelight/HostCardView.m +++ b/Limelight/HostCardView.m @@ -9,6 +9,8 @@ #import "HostCardView.h" #import "LocalizationHelper.h" #import "ThemeManager.h" +#import "FixedTintImageView.h" + @interface HostCardView () @@ -17,10 +19,11 @@ @property (nonatomic, strong) UILabel *hostNameLabel; @property (nonatomic, strong) UIImageView *statusIcon; @property (nonatomic, strong) UILabel *statusLabel; -@property (nonatomic, strong) UIButton *leftButton; -@property (nonatomic, strong) UIButton *rightButton; +@property (nonatomic, strong) UIButton *appButton; +@property (nonatomic, strong) UIButton *launchButton; @property (nonatomic, strong) UIButton *pairButton; -@property (nonatomic, strong) UIButton *settingsButton; +@property (nonatomic, strong) UIButton *wakeupButton; +@property (nonatomic, strong) UIButton *transparentButton; @property (nonatomic, strong) NSLayoutConstraint *widthConstraint; @property (nonatomic, strong) NSLayoutConstraint *heightConstraint; @property (nonatomic, strong) UIView *separatorLine; @@ -41,7 +44,7 @@ UIColor *defaultBlue; UIColor *defaultGreen; CAGradientLayer *backgroundLayer; - + bool longPressFired; } static const float REFRESH_CYCLE = 2.0f; @@ -50,12 +53,25 @@ static const float REFRESH_CYCLE = 2.0f; - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { + longPressFired = false; computerIconMonitorCenterYOffset = -3.3*_sizeFactor; iconAndButtonSpacing = 37*_sizeFactor; buttonHeight = 40*_sizeFactor; defaultBlue = [ThemeManager appPrimaryColor]; defaultGreen = [UIColor colorWithRed:52.0/255.0 green:199.0/255.0 blue:89.0/255.0 alpha:1.0]; - // self.userIterfaceStyle = UIUserInterfaceStyleLight; + // self.userIterfaceStyle = UIUserInterfaceStyleLight + if (@available(iOS 13.0, *)) { + NSLog(@"ttesttttt"); + UIContextMenuInteraction* longPressInteraction = [[UIContextMenuInteraction alloc] initWithDelegate:self]; + [self addInteraction:longPressInteraction]; + self.userInteractionEnabled = YES; + } + else + { + UILongPressGestureRecognizer* longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(hostLongClicked:)]; + [self addGestureRecognizer:longPressRecognizer]; + } + [self createBackgroundLayer]; [self setupUI]; } @@ -69,6 +85,7 @@ static const float REFRESH_CYCLE = 2.0f; // Use UIContextMenuInteraction on iOS 13.0+ and a standard UILongPressGestureRecognizer // for tvOS devices and iOS prior to 13.0. + return self; } @@ -91,28 +108,62 @@ static const float REFRESH_CYCLE = 2.0f; return self; } -- (void)leftButtonTapped{ +- (void)appButtonTapped{ + if(longPressFired){ + longPressFired = false; + return; + } NSLog(@"self.delegate: %lu", (uintptr_t)self.delegate); - if ([self.delegate respondsToSelector:@selector(leftButtonTappedForHost:)]) { - [self.delegate leftButtonTappedForHost:_host]; - } else NSLog(@"Delegate not set or does not respond to leftButtonTappedForHost:"); + if ([self.delegate respondsToSelector:@selector(appButtonTappedForHost:)]) { + [self.delegate appButtonTappedForHost:_host]; + } else NSLog(@"Delegate not set or does not respond to appButtonTappedForHost:"); } -- (void)rightButtonTapped{ - if ([self.delegate respondsToSelector:@selector(rightButtonTappedForHost:)]) { - [self.delegate rightButtonTappedForHost:_host]; - } else NSLog(@"Delegate not set or does not respond to rightButtonTappedForHost:"); +- (void)launchButtonTapped{ + if(longPressFired){ + longPressFired = false; + return; + } + if ([self.delegate respondsToSelector:@selector(launchButtonTappedForHost:)]) { + [self.delegate launchButtonTappedForHost:_host]; + } else NSLog(@"Delegate not set or does not respond to launchButtonTappedForHost:"); } +- (void)wakeupButtonTapped{ + if(longPressFired){ + longPressFired = false; + return; + } + if ([self.delegate respondsToSelector:@selector(wakeupButtonTappedForHost:)]) { + [self.delegate wakeupButtonTappedForHost:_host]; + } else NSLog(@"Delegate not set or does not respond to launchButtonTappedForHost:"); +} + + -(void)pairButtonTapped{ - NSLog(@"pairButtonTapped testtestttttt"); - + if(longPressFired){ + longPressFired = false; + return; + } if ([self.delegate respondsToSelector:@selector(pairButtonTappedForHost:)]) { [self.delegate pairButtonTappedForHost:_host]; - } else NSLog(@"Delegate not set or does not respond to rightButtonTappedForHost:"); - + } else NSLog(@"Delegate not set or does not respond to pairButtonTappedForHost:"); + } + +- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction + configurationForMenuAtLocation:(CGPoint)location API_AVAILABLE(ios(13.0)){ + NSLog(@"long tap test"); + longPressFired = true; + if ([self.delegate respondsToSelector:@selector(hostCardLongPressed:view:)]) { + [self.delegate hostCardLongPressed:_host view:self]; + } else NSLog(@"Delegate not set or does not respond to pairButtonTappedForHost:"); + return nil; +} + + + - (void)resizeBySizeFactor:(CGFloat)factor{ [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; self.sizeFactor = factor; @@ -120,6 +171,7 @@ static const float REFRESH_CYCLE = 2.0f; } - (void)setupUI { + self.userInteractionEnabled = YES; self.backgroundColor = [ThemeManager widgetBackgroundColor]; // theme self.layer.cornerRadius = 16; self.cardContentpadding = 13 * _sizeFactor; @@ -128,22 +180,22 @@ static const float REFRESH_CYCLE = 2.0f; CGFloat appButtonWidth = 100*_sizeFactor; CGFloat launchButtonWidth = 120*_sizeFactor; /* - NSLayoutConstraint *topAnchorConstraint; - topAnchorConstraint = [self.topAnchor constraintEqualToAnchor:self.superview.topAnchor constant:500]; - topAnchorConstraint.active = YES; -*/ + NSLayoutConstraint *topAnchorConstraint; + topAnchorConstraint = [self.topAnchor constraintEqualToAnchor:self.superview.topAnchor constant:500]; + topAnchorConstraint.active = YES; + */ _heightConstraint = [self.heightAnchor constraintEqualToConstant:300]; _heightConstraint.active = YES; _widthConstraint = [self.widthAnchor constraintEqualToConstant:300]; _widthConstraint.active = YES; - - + + // 图标背景 self.iconBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(_cardContentpadding, _cardContentpadding, 80*_sizeFactor, 80*_sizeFactor)]; self.iconBackgroundView.backgroundColor = defaultBlue; self.iconBackgroundView.layer.cornerRadius = 20*_sizeFactor; [self addSubview:self.iconBackgroundView]; - + // 图标图片 self.hostIconView = [[UIImageView alloc] init]; self.hostIconView.translatesAutoresizingMaskIntoConstraints = NO; @@ -167,7 +219,7 @@ static const float REFRESH_CYCLE = 2.0f; ]]; // [self.iconBackgroundView layoutIfNeeded]; // [self.iconImageView layoutIfNeeded]; - + //spinner _hostSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; _hostSpinner.userInteractionEnabled = NO; @@ -181,7 +233,7 @@ static const float REFRESH_CYCLE = 2.0f; _hostSpinner.transform = CGAffineTransformMakeScale(_sizeFactor, _sizeFactor); [_hostSpinner stopAnimating]; // [_hostSpinner startAnimating]; - + // lockIcon lockIconView =[[UIImageView alloc] init]; @@ -200,22 +252,22 @@ static const float REFRESH_CYCLE = 2.0f; [lockIconView.heightAnchor constraintEqualToConstant:22*_sizeFactor] ]]; lockIconView.hidden = true; - + // 设备名 self.hostNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(_cardContentpadding+_iconBackgroundView.frame.size.width+20*_sizeFactor, _cardContentpadding+_iconBackgroundView.frame.size.height/10, 300*_sizeFactor, 30*_sizeFactor)]; self.hostNameLabel.numberOfLines = 1; self.hostNameLabel.lineBreakMode = NSLineBreakByTruncatingTail; - + self.hostIconView.translatesAutoresizingMaskIntoConstraints = NO; self.hostNameLabel.text = @"RazerBlade 16"; self.hostNameLabel.textColor = [UIColor whiteColor]; //theme self.hostNameLabel.font = [UIFont boldSystemFontOfSize:20*_sizeFactor]; [self addSubview:self.hostNameLabel]; - - + + // 在线状态图标 - self.statusIcon = [[UIImageView alloc] initWithFrame:CGRectMake(180, 70, 20*_sizeFactor, 20*_sizeFactor)]; + self.statusIcon = [[FixedTintImageView alloc] initWithFrame:CGRectMake(180, 70, 20*_sizeFactor, 20*_sizeFactor)]; self.statusIcon.contentMode = UIViewContentModeScaleAspectFit; self.statusIcon.translatesAutoresizingMaskIntoConstraints = NO; if (@available(iOS 13.0, *)) { @@ -224,15 +276,15 @@ static const float REFRESH_CYCLE = 2.0f; // Fallback on earlier versions } self.statusIcon.tintColor = defaultGreen; - + [self addSubview:self.statusIcon]; [NSLayoutConstraint activateConstraints:@[ [self.statusIcon.leadingAnchor constraintEqualToAnchor:self.hostNameLabel.leadingAnchor], [self.statusIcon.topAnchor constraintEqualToAnchor:self.hostNameLabel.bottomAnchor constant:4*_sizeFactor], [self.statusIcon.widthAnchor constraintEqualToConstant:19*_sizeFactor] ]]; - - + + // 在线文字 self.statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(205, 68, 100, 24)]; self.statusLabel.translatesAutoresizingMaskIntoConstraints = NO; @@ -245,65 +297,53 @@ static const float REFRESH_CYCLE = 2.0f; [self.statusLabel.leadingAnchor constraintEqualToAnchor:self.statusIcon.trailingAnchor constant:3*_sizeFactor], [self.statusLabel.centerYAnchor constraintEqualToAnchor:self.statusIcon.centerYAnchor constant:0], ]]; - - - // 设置按钮 - /* - self.settingsButton = [UIButton buttonWithType:UIButtonTypeSystem]; - self.settingsButton.frame = CGRectMake(self.bounds.size.width - 40, 20, 24, 24); - if (@available(iOS 13.0, *)) { - [self.settingsButton setImage:[UIImage systemImageNamed:@"gearshape"] forState:UIControlStateNormal]; - } else { - // Fallback on earlier versions - } - self.settingsButton.tintColor = [UIColor lightGrayColor]; - [self addSubview:self.settingsButton]; - */ - + + + // 启动应用按钮 - self.leftButton = [UIButton buttonWithType:UIButtonTypeSystem]; - self.leftButton.translatesAutoresizingMaskIntoConstraints = NO; - self.leftButton.frame = CGRectMake(20, 200, 150, buttonHeight); - [self.leftButton setTitle:[LocalizationHelper localizedStringForKey:@"Applications"] forState:UIControlStateNormal]; - [self.leftButton setTitleColor:[ThemeManager textColorGray] forState:UIControlStateNormal]; //theme - self.leftButton.titleLabel.font = [UIFont systemFontOfSize:16*_sizeFactor]; - [self.leftButton addTarget:self action:@selector(leftButtonTapped) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:self.leftButton]; + self.appButton = [UIButton buttonWithType:UIButtonTypeSystem]; + self.appButton.translatesAutoresizingMaskIntoConstraints = NO; + self.appButton.frame = CGRectMake(20, 200, 150, buttonHeight); + [self.appButton setTitle:[LocalizationHelper localizedStringForKey:@"Applications"] forState:UIControlStateNormal]; + [self.appButton setTitleColor:[ThemeManager textColorGray] forState:UIControlStateNormal]; //theme + self.appButton.titleLabel.font = [UIFont systemFontOfSize:16*_sizeFactor]; + [self.appButton addTarget:self action:@selector(appButtonTapped) forControlEvents:UIControlEventPrimaryActionTriggered]; + [self addSubview:self.appButton]; [NSLayoutConstraint activateConstraints:@[ - [self.leftButton.leadingAnchor constraintEqualToAnchor:self.iconBackgroundView.leadingAnchor constant:0], - [self.leftButton.topAnchor constraintEqualToAnchor:self.iconBackgroundView.bottomAnchor constant:iconAndButtonSpacing], - [self.leftButton.widthAnchor constraintEqualToConstant:appButtonWidth], - [self.leftButton.heightAnchor constraintEqualToConstant:buttonHeight], + [self.appButton.leadingAnchor constraintEqualToAnchor:self.iconBackgroundView.leadingAnchor constant:0], + [self.appButton.topAnchor constraintEqualToAnchor:self.iconBackgroundView.bottomAnchor constant:iconAndButtonSpacing], + [self.appButton.widthAnchor constraintEqualToConstant:appButtonWidth], + [self.appButton.heightAnchor constraintEqualToConstant:buttonHeight], // [self.launchButton.titleLabel.leadingAnchor constraintEqualToAnchor:self.launchButton.imageView.trailingAnchor constant:3*_sizeFactor] ]]; - + // 开始串流按钮 - self.rightButton = [UIButton buttonWithType:UIButtonTypeSystem]; - self.rightButton.translatesAutoresizingMaskIntoConstraints = NO; - self.rightButton.frame = CGRectMake(0, 0, 150, 50); - self.rightButton.backgroundColor = defaultBlue; - self.rightButton.layer.cornerRadius = 10; - [self.rightButton setTitle:[LocalizationHelper localizedStringForKey:@" Launch"] forState:UIControlStateNormal]; - [self.rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; // theme - self.rightButton.titleLabel.font = [UIFont boldSystemFontOfSize:16*_sizeFactor]; - self.rightButton.tintColor = [UIColor whiteColor]; - [self.rightButton addTarget:self action:@selector(rightButtonTapped) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:self.rightButton]; + self.launchButton = [UIButton buttonWithType:UIButtonTypeSystem]; + self.launchButton.translatesAutoresizingMaskIntoConstraints = NO; + self.launchButton.frame = CGRectMake(0, 0, 150, 50); + self.launchButton.backgroundColor = defaultBlue; + self.launchButton.layer.cornerRadius = 10; + [self.launchButton setTitle:[LocalizationHelper localizedStringForKey:@" Launch"] forState:UIControlStateNormal]; + [self.launchButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; // theme + self.launchButton.titleLabel.font = [UIFont boldSystemFontOfSize:16*_sizeFactor]; + self.launchButton.tintColor = [UIColor whiteColor]; + [self.launchButton addTarget:self action:@selector(launchButtonTapped) forControlEvents:UIControlEventPrimaryActionTriggered]; + [self addSubview:self.launchButton]; if (@available(iOS 13.0, *)) { - UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.rightButton.frame.size.height/4*_sizeFactor]; - [self.rightButton setImage:[UIImage systemImageNamed:@"play.fill" withConfiguration:config] forState:UIControlStateNormal]; - + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.launchButton.frame.size.height*_sizeFactor]; + [self.launchButton setImage:[UIImage systemImageNamed:@"play.fill" withConfiguration:config] forState:UIControlStateNormal]; + } else { // Fallback on earlier versions } - + [NSLayoutConstraint activateConstraints:@[ - [self.rightButton.leadingAnchor constraintEqualToAnchor:self.leftButton.trailingAnchor constant:15*_sizeFactor], - [self.rightButton.centerYAnchor constraintEqualToAnchor:self.leftButton.centerYAnchor constant:0], - [self.rightButton.widthAnchor constraintEqualToConstant:launchButtonWidth], - [self.rightButton.heightAnchor constraintEqualToConstant:buttonHeight], + [self.launchButton.leadingAnchor constraintEqualToAnchor:self.appButton.trailingAnchor constant:15*_sizeFactor], + [self.launchButton.centerYAnchor constraintEqualToAnchor:self.appButton.centerYAnchor constant:0], + [self.launchButton.widthAnchor constraintEqualToConstant:launchButtonWidth], + [self.launchButton.heightAnchor constraintEqualToConstant:buttonHeight], // [self.launchButton.titleLabel.leadingAnchor constraintEqualToAnchor:self.launchButton.imageView.trailingAnchor constant:3*_sizeFactor] ]]; @@ -316,10 +356,6 @@ static const float REFRESH_CYCLE = 2.0f; [self.pairButton setTitle:[LocalizationHelper localizedStringForKey:@" Pair with PIN"] forState:UIControlStateNormal]; [self.pairButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme self.pairButton.titleLabel.font = [UIFont boldSystemFontOfSize:16*_sizeFactor]; - [self.pairButton addTarget:self action:@selector(pairButtonTapped) forControlEvents:UIControlEventTouchUpInside]; - [self addSubview:self.pairButton]; - - // self.launchButton.imageEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 0); if (@available(iOS 13.0, *)) { UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.pairButton.frame.size.height/3.5*_sizeFactor weight:UIImageSymbolWeightBold]; UIImage *templateImage = [UIImage systemImageNamed:@"lock.open.fill" withConfiguration:config]; @@ -328,9 +364,12 @@ static const float REFRESH_CYCLE = 2.0f; } else { // Fallback on earlier versions } - _pairButton.backgroundColor = [ThemeManager appPrimaryColorWithAlpha]; - [_pairButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme - + self.pairButton.backgroundColor = [ThemeManager appPrimaryColorWithAlpha]; + [self.pairButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme + + [self.pairButton addTarget:self action:@selector(pairButtonTapped) forControlEvents:UIControlEventPrimaryActionTriggered]; + [self addSubview:self.pairButton]; + [NSLayoutConstraint activateConstraints:@[ [self.pairButton.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:_cardContentpadding], [self.pairButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-_cardContentpadding], @@ -338,7 +377,31 @@ static const float REFRESH_CYCLE = 2.0f; // [self.pairButton.widthAnchor constraintEqualToConstant:launchButtonWidth], [self.pairButton.heightAnchor constraintEqualToConstant:buttonHeight], ]]; - + + + + + // 唤醒按钮 + self.wakeupButton = [UIButton buttonWithType:UIButtonTypeSystem]; + self.wakeupButton.translatesAutoresizingMaskIntoConstraints = NO; + self.wakeupButton.frame = CGRectMake(0, 0, 150, 50); + self.wakeupButton.backgroundColor = [ThemeManager appPrimaryColorWithAlpha]; + self.wakeupButton.layer.cornerRadius = 10; + [self.wakeupButton setTitle:[LocalizationHelper localizedStringForKey:@" Wake-on-LAN"] forState:UIControlStateNormal]; + [self.wakeupButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme + self.wakeupButton.titleLabel.font = [UIFont boldSystemFontOfSize:16*_sizeFactor]; + [self.wakeupButton addTarget:self action:@selector(wakeupButtonTapped) forControlEvents:UIControlEventPrimaryActionTriggered]; + [self addSubview:self.wakeupButton]; + + [NSLayoutConstraint activateConstraints:@[ + [self.wakeupButton.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:_cardContentpadding], + [self.wakeupButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-_cardContentpadding], + [self.wakeupButton.topAnchor constraintEqualToAnchor:self.iconBackgroundView.bottomAnchor constant:iconAndButtonSpacing], + // [self.pairButton.widthAnchor constraintEqualToConstant:launchButtonWidth], + [self.wakeupButton.heightAnchor constraintEqualToConstant:buttonHeight], + ]]; + + //分隔线 _separatorLine = [[UIView alloc] init]; @@ -350,22 +413,33 @@ static const float REFRESH_CYCLE = 2.0f; [_separatorLine.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-_cardContentpadding], [_separatorLine.centerYAnchor constraintEqualToAnchor:_iconBackgroundView.bottomAnchor constant: iconAndButtonSpacing/2], [_separatorLine.heightAnchor constraintEqualToConstant:1.0/UIScreen.mainScreen.scale] - // [self.launchButton.titleLabel.leadingAnchor constraintEqualToAnchor:self.launchButton.imageView.trailingAnchor constant:3*_sizeFactor] ]]; - - - // [self layoutSubviews]; - // [self layoutIfNeeded]; + + // 透明按钮 + self.transparentButton = [UIButton buttonWithType:UIButtonTypeCustom]; + // self.transparentButton.frame = CGRectMake(50, 100, 100, 100); // 设置点击区域 + self.transparentButton.translatesAutoresizingMaskIntoConstraints = NO; + // 设置透明背景和无内容 + self.transparentButton.backgroundColor = [UIColor clearColor]; + [self.transparentButton setTitle:@"" forState:UIControlStateNormal]; + [self.transparentButton setImage:nil forState:UIControlStateNormal]; + [self.transparentButton addTarget:self action:@selector(appButtonTapped) forControlEvents:UIControlEventPrimaryActionTriggered]; + + [self addSubview:self.transparentButton]; + [NSLayoutConstraint activateConstraints:@[ + [self.transparentButton.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:0], + [self.transparentButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:0], + [self.transparentButton.topAnchor constraintEqualToAnchor:self.topAnchor constant:0], + [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; _size = CGSizeMake(_widthConstraint.constant, _heightConstraint.constant); - // standard size: 261 * 184 [self updateTheme:ThemeManager.userInterfaceStyle]; - // [self updateContentsForHost:_host]; - // [self updateTheme:UIUserInterfaceStyleLight]; } - (void)createBackgroundLayer{ @@ -379,11 +453,11 @@ static const float REFRESH_CYCLE = 2.0f; (__bridge id)[UIColor clearColor].CGColor, (__bridge id)gradientColorRef ]; - + backgroundLayer.locations = @[@0, @0.18, @0.5, @1]; backgroundLayer.startPoint = CGPointMake(0.25, 0.5); backgroundLayer.endPoint = CGPointMake(0.75, 0.5); - + CGAffineTransform transform = CGAffineTransformMake(-1.01, -1, 1, -3.67, 0.5, 2.83); backgroundLayer.transform = CATransform3DMakeAffineTransform(transform); [self.layer insertSublayer:backgroundLayer atIndex:0]; @@ -396,40 +470,22 @@ static const float REFRESH_CYCLE = 2.0f; [self updateContentsForHost:_host]; // quick update before looping } +- (void)tintAdjustmentModeDidChange { + // [super tintAdjustmentModeDidChange]; + NSLog(@"tintChanged........"); + self.tintAdjustmentMode = UIViewTintAdjustmentModeNormal; +} + - (void)updateTheme:(UIUserInterfaceStyle)userIterfaceStyle{ self.backgroundColor = [ThemeManager widgetBackgroundColor]; _hostNameLabel.textColor = [ThemeManager textColor]; - [_leftButton setTitleColor:[ThemeManager appPrimaryColor] forState:UIControlStateNormal]; + [_appButton setTitleColor:[ThemeManager appPrimaryColor] forState:UIControlStateNormal]; _separatorLine.backgroundColor = [ThemeManager separatorColor]; backgroundLayer.hidden = NO; - - /* - switch (userIterfaceStyle) { - case UIUserInterfaceStyleDark: - _hostNameLabel.textColor = [ThemeManager textColorDark]; - [_leftButton setTitleColor:[ThemeManager appPrimaryColor] forState:UIControlStateNormal]; - _separatorLine.backgroundColor = [ThemeManager separatorColorDark]; - // [_rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - //self.backgroundColor = [ThemeManager widgetBackgroundColorDark]; - backgroundLayer.hidden = NO; - break; - case UIUserInterfaceStyleLight: - _hostNameLabel.textColor = [ThemeManager textColorLight]; - [_leftButton setTitleColor:[ThemeManager appPrimaryColor] forState:UIControlStateNormal]; - _separatorLine.backgroundColor = [ThemeManager separatorColorLight]; - // [_rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - // self.backgroundColor = [ThemeManager widgetBackgroundColorLight]; - backgroundLayer.hidden = NO; - break; - default:break; - - } - */ [self updateContentsForHost:_host]; } - - (void)didMoveToSuperview { // Start our update loop when we are added to our cell if (self.superview != nil && _host != nil) { @@ -440,7 +496,7 @@ static const float REFRESH_CYCLE = 2.0f; - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; - + if (@available(iOS 13.0, *)) { if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) { [self updateTheme:self.traitCollection.userInterfaceStyle]; @@ -456,7 +512,7 @@ static const float REFRESH_CYCLE = 2.0f; if (self.superview == nil) { return; } - + [self updateContentsForHost:_host]; // Queue the next refresh cycle @@ -465,12 +521,7 @@ static const float REFRESH_CYCLE = 2.0f; - (void) updateContentsForHost:(TemporaryHost*)host { _hostNameLabel.text = host.name; - // self.hostNameLabel.text = @"RazerBlade 16 testttttettest"; - - backgroundLayer.hidden = !(host.state == StateOnline && host.pairState == PairStatePaired); - - switch (host.state) { case StateOnline: @@ -485,55 +536,38 @@ static const float REFRESH_CYCLE = 2.0f; // Fallback on earlier versions } _hostIconView.tintColor = [UIColor whiteColor]; - - + _appButton.titleLabel.font = [UIFont systemFontOfSize:16*_sizeFactor]; if(host.pairState == PairStatePaired){ _iconBackgroundView.backgroundColor = defaultBlue; lockIconView.hidden = YES; - [_leftButton setTitle:[LocalizationHelper localizedStringForKey:@"Applications"] forState:UIControlStateNormal]; - [_rightButton setTitle:[LocalizationHelper localizedStringForKey:@" Launch"] forState:UIControlStateNormal]; - [_leftButton setEnabled:YES]; - [_rightButton setEnabled:YES]; - _leftButton.hidden = NO; - _rightButton.hidden = NO; + [_appButton setTitle:[LocalizationHelper localizedStringForKey:@"Applications"] forState:UIControlStateNormal]; + [_launchButton setTitle:[LocalizationHelper localizedStringForKey:@" Launch"] forState:UIControlStateNormal]; + [_appButton setEnabled:YES]; + [_launchButton setEnabled:YES]; + _appButton.hidden = NO; + _launchButton.hidden = NO; _pairButton.hidden = YES; - - [_leftButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme + _wakeupButton.hidden = YES; + + [_appButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme if (@available(iOS 13.0, *)) { - UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.rightButton.frame.size.height/4*_sizeFactor]; - [self.rightButton setImage:[UIImage systemImageNamed:@"play.fill" withConfiguration:config] forState:UIControlStateNormal]; + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.launchButton.frame.size.height/4*_sizeFactor]; + [self.launchButton setImage:[UIImage systemImageNamed:@"play.fill" withConfiguration:config] forState:UIControlStateNormal]; } else { // Fallback on earlier versions } - _rightButton.backgroundColor = defaultBlue; - [_rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; // theme + _launchButton.backgroundColor = defaultBlue; + [_launchButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; // theme } else { _iconBackgroundView.backgroundColor = [ThemeManager appPrimaryColorWithAlpha]; lockIconView.hidden = NO; - [_leftButton setTitle:[LocalizationHelper localizedStringForKey:@"Applications"] forState:UIControlStateNormal]; - [_rightButton setTitle:[LocalizationHelper localizedStringForKey:@" Launch"] forState:UIControlStateNormal]; - [_leftButton setEnabled:YES]; - [_rightButton setEnabled:YES]; - _leftButton.hidden = YES; - _rightButton.hidden = YES; + _appButton.hidden = YES; + _launchButton.hidden = YES; _pairButton.hidden = NO; - - - - [_leftButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme - if (@available(iOS 13.0, *)) { - UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.rightButton.frame.size.height/4*_sizeFactor]; - [self.rightButton setImage:[UIImage systemImageNamed:@"play.fill" withConfiguration:config] forState:UIControlStateNormal]; - } else { - // Fallback on earlier versions - } - _rightButton.backgroundColor = [ThemeManager appPrimaryColorWithAlpha]; - [_rightButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; // theme + _wakeupButton.hidden = YES; } - - break; case StateOffline: [_hostSpinner stopAnimating]; @@ -549,27 +583,22 @@ static const float REFRESH_CYCLE = 2.0f; } _hostIconView.tintColor = [ThemeManager lowProfileGray]; lockIconView.hidden = YES; - [_leftButton setTitle:[LocalizationHelper localizedStringForKey:@"Test network"] forState:UIControlStateNormal]; - [_rightButton setTitle:[LocalizationHelper localizedStringForKey:@" Wakeup"] forState:UIControlStateNormal]; - [_leftButton setEnabled:YES]; - [_rightButton setEnabled:YES]; - _leftButton.hidden = NO; - _rightButton.hidden = NO; + _appButton.hidden = YES; + _launchButton.hidden = YES; _pairButton.hidden = YES; - - - [_leftButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme + _wakeupButton.hidden = NO; + if (@available(iOS 13.0, *)) { - UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.rightButton.frame.size.height/3.5*_sizeFactor weight:UIImageSymbolWeightBold]; + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.wakeupButton.frame.size.height/3.2*_sizeFactor weight:UIImageSymbolWeightBold]; UIImage *templateImage = [UIImage systemImageNamed:@"power" withConfiguration:config]; UIImage *coloredImage = [templateImage imageWithTintColor:defaultBlue renderingMode:UIImageRenderingModeAlwaysOriginal]; - [self.rightButton setImage:coloredImage forState:UIControlStateNormal]; + [self.wakeupButton setImage:coloredImage forState:UIControlStateNormal]; } else { // Fallback on earlier versions } - _rightButton.backgroundColor = [ThemeManager appPrimaryColorWithAlpha]; - [_rightButton setTitleColor:defaultBlue forState:UIControlStateNormal]; // theme - + self.wakeupButton.backgroundColor = [ThemeManager appPrimaryColorWithAlpha]; + [self.wakeupButton setTitleColor:defaultBlue forState:UIControlStateNormal]; + break; case StateUnknown: _hostSpinner.color = [UIColor whiteColor]; @@ -587,55 +616,26 @@ static const float REFRESH_CYCLE = 2.0f; // _hostIconView.tintColor = [UIColor lowProfileGray]; _hostIconView.tintColor = defaultBlue; lockIconView.hidden = YES; - [_leftButton setTitle:[LocalizationHelper localizedStringForKey:@"Test network"] forState:UIControlStateNormal]; - [_rightButton setTitle:[LocalizationHelper localizedStringForKey:@" Wakeup"] forState:UIControlStateNormal]; - [_leftButton setEnabled:NO]; - [_rightButton setEnabled:NO]; - _leftButton.hidden = NO; - _rightButton.hidden = NO; + _appButton.hidden = YES; + _launchButton.hidden = YES; _pairButton.hidden = YES; - + _wakeupButton.hidden = NO; - [_leftButton setTitleColor:[ThemeManager textColorGray] forState:UIControlStateNormal]; // theme + [_wakeupButton setTitleColor:[ThemeManager textColorGray] forState:UIControlStateNormal]; // theme if (@available(iOS 13.0, *)) { - UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.rightButton.frame.size.height/3.5*_sizeFactor weight:UIImageSymbolWeightBold]; + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:self.wakeupButton.frame.size.height/3.2*_sizeFactor weight:UIImageSymbolWeightBold]; UIImage *templateImage = [UIImage systemImageNamed:@"power" withConfiguration:config]; UIImage *coloredImage = [templateImage imageWithTintColor:[ThemeManager textColorGray] renderingMode:UIImageRenderingModeAlwaysOriginal]; - [self.rightButton setImage:coloredImage forState:UIControlStateNormal]; + [self.wakeupButton setImage:coloredImage forState:UIControlStateNormal]; } else { // Fallback on earlier versions } - _rightButton.backgroundColor = [[ThemeManager textColorGray] colorWithAlphaComponent:0.2]; - [_rightButton setTitleColor:[ThemeManager textColorGray] forState:UIControlStateNormal]; // theme - - + self.wakeupButton.backgroundColor = [[ThemeManager textColorGray] colorWithAlphaComponent:0.2]; + [self.wakeupButton setTitleColor:[ThemeManager textColorGray] forState:UIControlStateNormal]; break; default:break; } - - /* - if (host.state == StateOnline) { - [_hostSpinner stopAnimating]; - - lockIconView.hidden = ! (host.pairState == PairStateUnpaired); - - - if (host.pairState == PairStateUnpaired) { - - } - else { - } - - } - else if (host.state == StateOffline) { - [_hostSpinner stopAnimating]; - } - else { - [_hostSpinner startAnimating]; - } - */ } - @end diff --git a/Limelight/ThemeManager.m b/Limelight/ThemeManager.m index f0a49e5b..21cb4e6c 100644 --- a/Limelight/ThemeManager.m +++ b/Limelight/ThemeManager.m @@ -10,123 +10,88 @@ @implementation ThemeManager -static UIUserInterfaceStyle _userInterfaceStyle = UIUserInterfaceStyleLight; +static UIUserInterfaceStyle _privateUserInterfaceStyle = UIUserInterfaceStyleUnspecified; +static UIUserInterfaceStyle _userInterfaceStyle; + ++ (UIColor *)getUIStyle{ + if (@available(iOS 13.0, *)) { + UITraitCollection *traitCollection = [UIScreen mainScreen].traitCollection; + if(_privateUserInterfaceStyle == UIUserInterfaceStyleUnspecified) { + _userInterfaceStyle = traitCollection.userInterfaceStyle; + } + else _userInterfaceStyle = _privateUserInterfaceStyle; + return [UIColor clearColor]; + } else { + return [UIColor clearColor]; + } +} + + + (UIUserInterfaceStyle)userInterfaceStyle { + [ThemeManager getUIStyle]; return _userInterfaceStyle; } + (void)setUserInterfaceStyle:(UIUserInterfaceStyle)style { - _userInterfaceStyle = style; + _privateUserInterfaceStyle = style; + [ThemeManager getUIStyle]; } + (UIColor *)appBackgroundColor { - if (@available(iOS 13.0, *)) { - return [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) { - UIUserInterfaceStyle style = self.userInterfaceStyle; - if (style == UIUserInterfaceStyleUnspecified) { - // 跟随系统 - style = traitCollection.userInterfaceStyle; - } - switch (style) { - case UIUserInterfaceStyleLight: - return [UIColor colorWithRed:242.0/255.0 green:242.0/255.0 blue:247.0/255.0 alpha:1.0]; - case UIUserInterfaceStyleDark: - default: - return [UIColor colorWithRed:28.0/255.0 green:28.0/255.0 blue:30.0/255.0 alpha:1.0]; - } - }]; - } else { - switch (self.userInterfaceStyle) { - case UIUserInterfaceStyleLight: - return [UIColor colorWithRed:242.0/255.0 green:242.0/255.0 blue:247.0/255.0 alpha:1.0]; - case UIUserInterfaceStyleDark: - default: - return [UIColor colorWithRed:28.0/255.0 green:28.0/255.0 blue:30.0/255.0 alpha:1.0]; - } + [ThemeManager getUIStyle]; + switch (self.userInterfaceStyle) { + case UIUserInterfaceStyleLight: + return [UIColor colorWithRed:242.0/255.0 green:242.0/255.0 blue:247.0/255.0 alpha:1.0]; + break; + case UIUserInterfaceStyleDark: + default: + return [UIColor colorWithRed:28.0/255.0 green:28.0/255.0 blue:30.0/255.0 alpha:1.0]; + break; } } - + (UIColor *)widgetBackgroundColor { - if (@available(iOS 13.0, *)) { - return [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) { - UIUserInterfaceStyle style = self.userInterfaceStyle; - if (style == UIUserInterfaceStyleUnspecified) { - // 跟随系统 - style = traitCollection.userInterfaceStyle; - } - switch (style) { - case UIUserInterfaceStyleLight: - return [UIColor whiteColor]; - case UIUserInterfaceStyleDark: - default: - return [UIColor colorWithRed:44.0/255.0 green:44.0/255.0 blue:46.0/255.0 alpha:1.0]; - } - }]; - } else { - switch (self.userInterfaceStyle) { - case UIUserInterfaceStyleLight: - return [UIColor whiteColor]; - case UIUserInterfaceStyleDark: - default: - return [UIColor colorWithRed:44.0/255.0 green:44.0/255.0 blue:46.0/255.0 alpha:1.0]; - } + [ThemeManager getUIStyle]; + switch (self.userInterfaceStyle) { + case UIUserInterfaceStyleLight: + return [UIColor whiteColor]; + break; + case UIUserInterfaceStyleDark: + default: + return [UIColor colorWithRed:44.0/255.0 green:44.0/255.0 blue:46.0/255.0 alpha:1.0]; + break; } } + (UIColor *)separatorColor { - if (@available(iOS 13.0, *)) { - return [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) { - UIUserInterfaceStyle style = self.userInterfaceStyle; - if (style == UIUserInterfaceStyleUnspecified) { - // 跟随系统 - style = traitCollection.userInterfaceStyle; - } - switch (style) { - case UIUserInterfaceStyleLight: - return [UIColor colorWithWhite:0.1 alpha:0.28]; - case UIUserInterfaceStyleDark: - default: - return [UIColor colorWithWhite:0.28 alpha:1.0]; - } - }]; - } else { + [ThemeManager getUIStyle]; switch (self.userInterfaceStyle) { case UIUserInterfaceStyleLight: + NSLog(@"themeLightSP"); return [UIColor colorWithWhite:0.1 alpha:0.28]; + break; case UIUserInterfaceStyleDark: default: + NSLog(@"themeDarkSP"); return [UIColor colorWithWhite:0.28 alpha:1.0]; + break; } } -} + (UIColor *)textColor { - if (@available(iOS 13.0, *)) { - return [UIColor colorWithDynamicProvider:^UIColor *(UITraitCollection *traitCollection) { - UIUserInterfaceStyle style = self.userInterfaceStyle; - if (style == UIUserInterfaceStyleUnspecified) { - // 跟随系统 - style = traitCollection.userInterfaceStyle; - } - switch (style) { - case UIUserInterfaceStyleLight: - return [UIColor blackColor]; - case UIUserInterfaceStyleDark: - default: - return [UIColor whiteColor]; - } - }]; - } else { + [ThemeManager getUIStyle]; switch (self.userInterfaceStyle) { - case UIUserInterfaceStyleLight: - return [UIColor blackColor]; - case UIUserInterfaceStyleDark: - default: - return [UIColor whiteColor]; - } + case UIUserInterfaceStyleLight: + NSLog(@"themeLightTX"); + return [UIColor blackColor]; + break; + case UIUserInterfaceStyleDark: + default: + NSLog(@"themeDarkTX"); + return [UIColor whiteColor]; + break; } } diff --git a/Limelight/UIComputerView.h b/Limelight/UIComputerView.h index 911c6995..8d76e5ab 100644 --- a/Limelight/UIComputerView.h +++ b/Limelight/UIComputerView.h @@ -12,8 +12,8 @@ @protocol HostCallback - (void) hostClicked:(TemporaryHost*)host view:(UIView*)view; -- (void) hostLongClicked:(TemporaryHost*)host view:(UIView*)view; -- (void) addHostClicked; +- (void) hostCardLongPressed:(TemporaryHost*)host view:(UIView*)view; +- (void) addHostTapped; @end diff --git a/Limelight/UIComputerView.m b/Limelight/UIComputerView.m index 8bb4940b..77fc37d5 100644 --- a/Limelight/UIComputerView.m +++ b/Limelight/UIComputerView.m @@ -216,7 +216,7 @@ static const int LABEL_DY = 20; - (void) hostLongClicked:(UILongPressGestureRecognizer*)gesture { if (gesture.state == UIGestureRecognizerStateBegan) { - [_callback hostLongClicked:_host view:self]; + [_callback hostCardLongPressed:_host view:self]; } } @@ -228,7 +228,7 @@ static const int LABEL_DY = 20; // effect of removing the touch highlight on this view. [self cancelTrackingWithEvent:nil]; - [_callback hostLongClicked:_host view:self]; + [_callback hostCardLongPressed:_host view:self]; return nil; } #endif @@ -238,7 +238,7 @@ static const int LABEL_DY = 20; } - (void) addClicked { - [_callback addHostClicked]; + [_callback addHostTapped]; } @end diff --git a/Limelight/ViewControllers/HostCollectionViewController.h b/Limelight/ViewControllers/HostCollectionViewController.h index 9725152d..86c42e3f 100644 --- a/Limelight/ViewControllers/HostCollectionViewController.h +++ b/Limelight/ViewControllers/HostCollectionViewController.h @@ -27,6 +27,7 @@ /// 添加一个 item - (void)addHost:(TemporaryHost *)host; +- (void)removeHost:(TemporaryHost *)host; /// 移除最后一个 item(如果有) - (void)removeLastItem; diff --git a/Limelight/ViewControllers/HostCollectionViewController.m b/Limelight/ViewControllers/HostCollectionViewController.m index 620cde00..c7b8fa47 100644 --- a/Limelight/ViewControllers/HostCollectionViewController.m +++ b/Limelight/ViewControllers/HostCollectionViewController.m @@ -11,7 +11,7 @@ #import "TemporaryHost.h" #import "ThemeManager.h" - +static const CGFloat cellOffsetY = 20; @implementation HostCell { UIViewController* parentVC; @@ -43,7 +43,7 @@ - (void)assignDelegateForHostCard{ parentVC = [self viewController].parentViewController; if(parentVC != nil){ - if([parentVC conformsToProtocol:@protocol(HostCardButtonActionDelegate)]) self.cardView.delegate = (id) parentVC; + if([parentVC conformsToProtocol:@protocol(HostCardActionDelegate)]) self.cardView.delegate = (id) parentVC; } } @@ -59,7 +59,7 @@ [self.contentView addSubview:self.cardView]; [NSLayoutConstraint activateConstraints:@[ [self.cardView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor], - [self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor], + [self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0], ]]; } } @@ -71,11 +71,13 @@ @property (nonatomic, strong) NSLayoutConstraint *collectionViewHeightConstraint; @end -@implementation HostCollectionViewController +@implementation HostCollectionViewController{ + UICollectionViewFlowLayout *layout; +} - (instancetype)init { - UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; - layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 13); // 上、左、下、右的间距 + layout = [[UICollectionViewFlowLayout alloc] init]; + layout.sectionInset = UIEdgeInsetsMake(7, 0, 0, 0); // 上、左、下、右的间距 if (self = [super initWithCollectionViewLayout:layout]) { _interItemMinimumSpacing = 10; _minimumLineSpacing = 10; @@ -97,6 +99,7 @@ // Fallback on earlier versions } self.collectionView.alwaysBounceVertical = NO; + self.collectionView.showsVerticalScrollIndicator = NO; self.collectionView.backgroundColor = [ThemeManager appBackgroundColor]; } @@ -121,14 +124,20 @@ [self.items addObject:host]; [self.items addObject:host]; [self.items addObject:host]; - [self.collectionView reloadData]; // [self.view layoutIfNeeded]; } NSLog(@"addhost log"); - } +- (void)removeHost:(TemporaryHost *)host { + if([self.items containsObject:host]){ + [self.items removeObject:host]; + [self.collectionView reloadData]; + } +} + + - (void)removeLastItem { if (self.items.count > 0) { [self.items removeLastObject]; @@ -136,9 +145,27 @@ } } +- (NSInteger)numberOfRowsInCollectionView{ + NSInteger itemCount = [self.collectionView numberOfItemsInSection:0]; + + if (itemCount == 0) return 0; + + NSMutableSet *rowYs = [NSMutableSet set]; + for (NSInteger i = 0; i < itemCount; i++) { + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; + UICollectionViewLayoutAttributes *attr = [layout layoutAttributesForItemAtIndexPath:indexPath]; + if (attr) { + CGFloat y = CGRectGetMinY(attr.frame); + [rowYs addObject:@(round(y))]; // round 防止浮点误差 + } + } + + return rowYs.count; +} + - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - + CGFloat contentHeight = self.collectionView.collectionViewLayout.collectionViewContentSize.height; bool contentExceedsView = contentHeight > self.view.superview.bounds.size.height - self.view.frame.origin.y; if(contentExceedsView){ @@ -146,7 +173,13 @@ [self.view.bottomAnchor constraintEqualToAnchor:self.view.superview.safeAreaLayoutGuide.bottomAnchor constant:0] ]]; } - else _collectionViewHeightConstraint.constant = contentHeight; + else{ + _collectionViewHeightConstraint.constant = contentHeight; + } + + if([self numberOfRowsInCollectionView]<=2 && !contentExceedsView) layout.sectionInset = UIEdgeInsetsMake(50, 0, 0, 0); + if([self numberOfRowsInCollectionView]>2 && !contentExceedsView) layout.sectionInset = UIEdgeInsetsMake(25, 0, 0, 0); + if(contentExceedsView) layout.sectionInset = UIEdgeInsetsMake(7, 0, 0, 0); } #pragma mark - UICollectionView DataSource diff --git a/Limelight/ViewControllers/MainFrameViewController.h b/Limelight/ViewControllers/MainFrameViewController.h index 2691b842..56956aed 100644 --- a/Limelight/ViewControllers/MainFrameViewController.h +++ b/Limelight/ViewControllers/MainFrameViewController.h @@ -21,13 +21,14 @@ #import "HostCollectionViewController.h" -@interface MainFrameViewController : UICollectionViewController +@interface MainFrameViewController : UICollectionViewController @property (weak, nonatomic) IBOutlet UIBarButtonItem *settingsButton; #if !TARGET_OS_TV @property (weak, nonatomic) IBOutlet UIBarButtonItem *upButton; @property (nonatomic, assign) bool settingsExpandedInStreamView; @property (nonatomic, strong) HostCollectionViewController *hostCollectionVC; +@property (weak, nonatomic) IBOutlet UINavigationItem *navigationItem; -(void)simulateSettingsButtonPress; diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index d10e755b..596d2a82 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -33,6 +33,7 @@ #import "CustomEdgeSlideGestureRecognizer.h" #import "DataManager.h" #import "ThemeManager.h" +#import "FixedTintImageView.h" #import "Moonlight-Swift.h" // not used yet. #if !TARGET_OS_TV @@ -47,6 +48,9 @@ @implementation MainFrameViewController { UILabel* waterMark; + UIBarButtonItem* addHostButton; + UIBarButtonItem* helpButton; + UILabel* hostViewTitleLabel; //CGFloat recordedScreenWidth; NSOperationQueue* _opQueue; TemporaryHost* _selectedHost; @@ -126,31 +130,44 @@ static NSMutableSet* hostList; }); } -- (void)disableUpButton { +- (void)switchUIToHostView { #if !TARGET_OS_TV + self.navigationItem.rightBarButtonItems = @[helpButton, addHostButton]; [self->_upButton setTitle:nil]; self.revealViewController.mainFrameIsInHostView = true; // to allow orientation change only in app view, tell top view controller the mainframe is not in host view - [self setNeedsUpdateAllowedOrientation]; + // [self setNeedsUpdateAllowedOrientation]; #endif } -- (void)enableUpButton { +- (void)switchUIToAppView { #if !TARGET_OS_TV [self->_upButton setTitle: [LocalizationHelper localizedStringForKey: @"Select New Host"]]; + self.navigationItem.rightBarButtonItems = @[_upButton]; self.revealViewController.mainFrameIsInHostView = false; // to allow orientation change only in app view, tell top view controller the mainframe is not in host view - [self setNeedsUpdateAllowedOrientation]; + // [self setNeedsUpdateAllowedOrientation]; #endif } - (void)updateTitle { + if (_selectedHost != nil) { - self.title = _selectedHost.name; + // self.title = _selectedHost.name; } else if ([hostList count] == 0) { + self.navigationController.navigationBar.titleTextAttributes = @{ + NSFontAttributeName: [UIFont systemFontOfSize:20 weight:UIFontWeightMedium], + NSForegroundColorAttributeName: [ThemeManager textColor] // 可选,设置标题颜色 + }; + self.title = [LocalizationHelper localizedStringForKey: @"Searching for PCs on your network..."] ; } else { - self.title = [LocalizationHelper localizedStringForKey: @"Select Host" ]; + self.navigationController.navigationBar.titleTextAttributes = @{ + NSFontAttributeName: [UIFont systemFontOfSize:24 weight:UIFontWeightSemibold], + NSForegroundColorAttributeName: [ThemeManager textColor] // 可选,设置标题颜色 + }; + self.title = [LocalizationHelper localizedStringForKey: @"Hosts" ]; + //self.title = nil; } } @@ -313,7 +330,7 @@ static NSMutableSet* hostList; _sortedAppList = nil; [self updateTitle]; - [self disableUpButton]; + [self switchUIToHostView]; [self.collectionView removeFromSuperview]; // necessary for new scroll host view reloading mechanism [self reloadScrollHostView]; // host view must be reloaded here @@ -345,12 +362,12 @@ static NSMutableSet* hostList; [self.collectionView reloadData]; //for new scroll host view reloading mechanism [self.view addSubview:self.collectionView]; //for new scroll host view reloading mechanism [self attachWaterMark]; - [self enableUpButton]; + [self switchUIToAppView]; [self disableNavigation]; [self alreadyPaired]; } -- (void)leftButtonTappedForHost:(TemporaryHost *)host { +- (void)appButtonTappedForHost:(TemporaryHost *)host { if (host.state != StateOnline) return; _selectedHost = host; if (host.state == StateOnline && host.pairState == PairStatePaired && host.appList.count > 0) { @@ -359,8 +376,7 @@ static NSMutableSet* hostList; } -- (void)rightButtonTappedForHost:(TemporaryHost *)host { - +- (void)launchButtonTappedForHost:(TemporaryHost *)host { _selectedHost = host; if (host.state == StateOnline && host.pairState == PairStatePaired && host.appList.count > 0) { [self enterAppView]; @@ -369,10 +385,11 @@ static NSMutableSet* hostList; [self performSegueWithIdentifier:@"createStreamFrame" sender:nil]; return; } - - NSLog(@"wake testtttttt: hostName: %@, states: %d, %d", host.name, host.state, host.pairState); +} - +- (void)wakeupButtonTappedForHost:(TemporaryHost *)host{ + _selectedHost = host; + NSLog(@"wake testtttttt: hostName: %@, states: %d, %d", host.name, host.state, host.pairState); if (host.state == StateOffline && host.pairState == PairStatePaired) { UIAlertController* wolAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Wake-On-LAN"] message:@"" preferredStyle:UIAlertControllerStyleAlert]; [wolAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]]; @@ -386,8 +403,6 @@ static NSMutableSet* hostList; } [[self activeViewController] presentViewController:wolAlert animated:YES completion:nil]; } - - } - (void)pairButtonTappedForHost:(TemporaryHost *)host{ @@ -459,19 +474,15 @@ static NSMutableSet* hostList; } }); }]; - - } - - - (void) hostClicked:(TemporaryHost *)host view:(UIView *)view { // Treat clicks on offline hosts to be long clicks // This shows the context menu with wake, delete, etc. rather // than just hanging for a while and failing as we would in this // code path. if (host.state != StateOnline && view != nil) { - [self hostLongClicked:host view:view]; + [self hostCardLongPressed:host view:view]; return; } @@ -483,7 +494,7 @@ static NSMutableSet* hostList; [self.collectionView reloadData]; //for new scroll host view reloading mechanism [self.view addSubview:self.collectionView]; //for new scroll host view reloading mechanism [self attachWaterMark]; - [self enableUpButton]; + [self switchUIToAppView]; [self disableNavigation]; #if TARGET_OS_TV @@ -592,7 +603,14 @@ static NSMutableSet* hostList; return topController; } -- (void)hostLongClicked:(TemporaryHost *)host view:(UIView *)view { +- (void)restoreTintColorForAllSubViews{ + for(UIView* view in self.view.subviews){ // iterates all on-screen widget views in StreamFrameView + view.tintAdjustmentMode = UIViewTintAdjustmentModeNormal; + } +} + +- (void)hostCardLongPressed:(TemporaryHost *)host view:(UIView *)view { + _selectedHost = host; Log(LOG_D, @"Long clicked host: %@", host.name); NSString* message; @@ -619,8 +637,9 @@ static NSMutableSet* hostList; } UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:message preferredStyle:UIAlertControllerStyleActionSheet]; + if (host.state != StateOnline) { - [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Wake PC"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){ + /*[longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Wake PC"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){ UIAlertController* wolAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Wake-On-LAN"] message:@"" preferredStyle:UIAlertControllerStyleAlert]; [wolAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]]; if (host.mac == nil || [host.mac isEqualToString:@"00:00:00:00:00:00"]) { @@ -632,16 +651,17 @@ static NSMutableSet* hostList; wolAlert.message = [LocalizationHelper localizedStringForKey:@"Successfully sent wake-up request. It may take a few moments for the PC to wake. If it never wakes up, ensure it's properly configured for Wake-on-LAN."]; } [[self activeViewController] presentViewController:wolAlert animated:YES completion:nil]; - }]]; + }]];*/ } else if (host.pairState == PairStatePaired) { + /* [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"View All Apps"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){ self->_showHiddenApps = YES; [self hostClicked:host view:view]; - }]]; + }]]; */ #if !TARGET_OS_TV - if (host.isNvidiaServerSoftware) { + if (false) { [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"NVIDIA GameStream End-of-Service"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){ [Utils launchUrl:@"https://github.com/moonlight-stream/moonlight-docs/wiki/NVIDIA-GameStream-End-Of-Service-Announcement-FAQ"]; }]]; @@ -671,7 +691,10 @@ static NSMutableSet* hostList; UIAlertController* netTestAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Network Test Complete"] message:message preferredStyle:UIAlertControllerStyleAlert]; [netTestAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]]; - [[self activeViewController] presentViewController:netTestAlert animated:YES completion:nil]; + [[self activeViewController] presentViewController:netTestAlert animated:YES completion:^{ + NSLog(@"restore tint"); + [self restoreTintColorForAllSubViews]; + }]; }]; }); }); @@ -689,6 +712,7 @@ static NSMutableSet* hostList; #endif [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Remove Host"] style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action) { // host removed here [self->_discMan removeHostFromDiscovery:host]; + [self.hostCollectionVC removeHost:host]; DataManager* dataMan = [[DataManager alloc] init]; [dataMan removeHost:host]; @synchronized(hostList) { @@ -706,8 +730,8 @@ static NSMutableSet* hostList; [[self activeViewController] presentViewController:longClickAlert animated:YES completion:nil]; } -- (void) addHostClicked { - Log(LOG_D, @"Clicked add host"); +- (void) addHostTapped { + Log(LOG_D, @"Tapped add host"); UIAlertController* alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Add Host Manually"] message:[LocalizationHelper localizedStringForKey:@"If Moonlight doesn't find your local gaming PC automatically, enter the IP address of your PC"] preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel handler:nil]]; [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){ @@ -1069,7 +1093,7 @@ 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. + 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)); @@ -1092,6 +1116,14 @@ static NSMutableSet* hostList; } - (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position { + + if (position == FrontViewPositionLeft) { + self.navigationItem.leftBarButtonItems = @[_settingsButton]; + } + else { + self.navigationItem.leftBarButtonItems = @[]; + } + SettingsViewController* settingsViewController = (SettingsViewController*)[revealController rearViewController]; settingsViewController.mainFrameViewController = self; // enable / disable widgets acoordingly: in streamview, disable, outside of streamview, enable. @@ -1204,7 +1236,7 @@ static NSMutableSet* hostList; - (void)attachWaterMark { // Create and configure the label - if(true){ + if(false){ [self->waterMark removeFromSuperview]; self->waterMark = [[UILabel alloc] init]; self->waterMark.translatesAutoresizingMaskIntoConstraints = NO; @@ -1244,7 +1276,7 @@ static NSMutableSet* hostList; } } -- (bool)isIphone{ +- (bool)isIPhone{ return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone); } @@ -1257,7 +1289,146 @@ static NSMutableSet* hostList; // return isPortrait; } +- (UIBarButtonItem *)createAddHostButton{ + // 创建按钮 + CGFloat buttonHeight = 30; + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; + button.backgroundColor = [ThemeManager appPrimaryColor]; // #0A85FF + button.layer.cornerRadius = buttonHeight/2; + button.clipsToBounds = YES; + + // 设置图标(SF Symbol) + + if (@available(iOS 13.0, *)) { + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:17 weight:UIImageSymbolWeightMedium]; + UIImage *image = [UIImage systemImageNamed:@"plus.circle" withConfiguration:config]; + [button setImage:image forState:UIControlStateNormal]; + [button setTitle:@" Add Host" forState:UIControlStateNormal]; // 注意空格用于间隔 + } else { + [button setTitle:@"Add Host" forState:UIControlStateNormal]; // 注意空格用于间隔 + } + // [button setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + + button.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + // 文字颜色设置为 tintColor 控制 + button.tintColor = UIColor.whiteColor; + [button setTitleColor:button.tintColor forState:UIControlStateNormal]; + + // 设置按下时的 tintColor(变灰或淡) + UIColor *highlightColor = [ThemeManager textColorGray]; + [button setTitleColor:highlightColor forState:UIControlStateHighlighted]; + button.adjustsImageWhenHighlighted = YES; // 图标自动变淡 + + // 手动设定大小(如图中大约宽118高40) + button.frame = CGRectMake(0, 0, 130, buttonHeight); + + // 添加点击事件 + [button addTarget:self action:@selector(addHostTapped) forControlEvents:UIControlEventTouchUpInside]; + + // 创建 UIBarButtonItem + UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:button]; + return barItem; +} + +- (UIBarButtonItem *)createHelpButton{ + // 创建按钮 + CGFloat buttonHeight = 30; + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; + button.backgroundColor = [UIColor clearColor]; // #0A85FF + // button.layer.cornerRadius = buttonHeight/2; + button.clipsToBounds = YES; + + // 设置图标(SF Symbol) + if (@available(iOS 13.0, *)) { + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:buttonHeight*0.85 weight:UIImageSymbolWeightRegular]; + UIImage *image = [UIImage systemImageNamed:@"questionmark.circle" withConfiguration:config]; + [button setImage:image forState:UIControlStateNormal]; + [button setTitle:@"" forState:UIControlStateNormal]; // 注意空格用于间隔 + } else { + [button setTitle:@"Help" forState:UIControlStateNormal]; // 注意空格用于间隔 + } + // [button setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; + + button.titleLabel.font = [UIFont systemFontOfSize:buttonHeight*0.6 weight:UIFontWeightMedium]; + // 文字颜色设置为 tintColor 控制 + button.tintColor = [ThemeManager appPrimaryColor]; + [button setTitleColor:button.tintColor forState:UIControlStateNormal]; + + button.frame = CGRectMake(0, 0, buttonHeight, buttonHeight); + + // 添加点击事件 + // [button addTarget:self action:@selector(addDeviceTapped) forControlEvents:UIControlEventTouchUpInside]; + + // 创建 UIBarButtonItem + UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:button]; + return barItem; +} + +- (CGFloat)getStandardNavBarHeight{ + 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)setupNavBar{ + + self->addHostButton = [self createAddHostButton]; + self->helpButton = [self createHelpButton]; + //[self setupHostViewTitle]; + self.navigationItem.rightBarButtonItems = @[helpButton, addHostButton]; // 顺序:右边靠右的是第一个 + + self.navigationController.navigationBar.backgroundColor = [ThemeManager appBackgroundColor]; + // self.navigationController.navigationBar + self.navigationController.navigationBar.titleTextAttributes = @{ + NSForegroundColorAttributeName: [ThemeManager textColor] + }; + // Set the side bar button action. When it's tapped, it'll show the sidebar. + + [_settingsButton setTarget:self.revealViewController]; + [_settingsButton setAction:@selector(revealToggle:)]; + if (@available(iOS 13.0, *)) { + [_settingsButton setTitle:nil]; + UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:23 weight:UIImageSymbolWeightMedium ]; + UIImage *image = [[UIImage systemImageNamed:@"sidebar.left" withConfiguration:config] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + [_settingsButton setImage:image]; + _settingsButton.imageInsets = UIEdgeInsetsMake(10, 10, 0, 0); + } else { + [_settingsButton setTitle:[LocalizationHelper localizedStringForKey:@"Settings"]]; + } + + // Set the host name button action. When it's tapped, it'll show the host selection view. + [_upButton setTarget:self]; + [_upButton setAction:@selector(showHostSelectionView)]; + [self switchUIToHostView]; + +} + - (void)viewDidLoad{ + [ThemeManager setUserInterfaceStyle:UIUserInterfaceStyleUnspecified]; [super viewDidLoad]; //[OrientationHelper updateOrientationToLandscape]; @@ -1267,14 +1438,7 @@ static NSMutableSet* hostList; self.revealViewController.isStreaming = false; //init this flag for rvlVC self.revealViewController.mainFrameIsInHostView = true; - // Set the side bar button action. When it's tapped, it'll show the sidebar. - [_settingsButton setTarget:self.revealViewController]; - [_settingsButton setAction:@selector(revealToggle:)]; - - // Set the host name button action. When it's tapped, it'll show the host selection view. - [_upButton setTarget:self]; - [_upButton setAction:@selector(showHostSelectionView)]; - [self disableUpButton]; + [self setupNavBar]; // Set the gesture if(![self isIPhonePortrait]) [self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer]; // to prevent buggy settings view in iphone portrait mode; @@ -1369,7 +1533,7 @@ static NSMutableSet* hostList; -(void)viewDidLayoutSubviews{ [super viewDidLayoutSubviews]; - + [self updateHosts]; } @@ -1563,8 +1727,7 @@ static NSMutableSet* hostList; { [super viewDidAppear:NO]; - - + // [self setupHostViewTitle]; // [self reloadScrollHostView]; //remove this for proper test [self attachWaterMark]; @@ -1609,8 +1772,8 @@ static NSMutableSet* hostList; - (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - + [super viewWillAppear:NO]; + /* this makes background color works*/ for (UIView *subview in self.view.subviews) { [subview removeFromSuperview]; // 暂时移除所有子视图 @@ -1643,7 +1806,6 @@ static NSMutableSet* hostList; - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; - // when discovery stops, we must create a new instance because // you cannot restart an NSOperation when it is finished [_discMan stopDiscovery]; @@ -1985,7 +2147,7 @@ static NSMutableSet* hostList; CGFloat hostCollectionViewPadding = 75; self.hostCollectionVC.view.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ - [self.hostCollectionVC.view.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:50], + [self.hostCollectionVC.view.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:0], [self.hostCollectionVC.view.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:hostCollectionViewPadding], [self.hostCollectionVC.view.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-hostCollectionViewPadding], // [self.hostCollectionVC.view.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:0] //? diff --git a/Limelight/ViewControllers/SettingsViewController.m b/Limelight/ViewControllers/SettingsViewController.m index 5a2d959b..156e6b1f 100644 --- a/Limelight/ViewControllers/SettingsViewController.m +++ b/Limelight/ViewControllers/SettingsViewController.m @@ -446,7 +446,7 @@ BOOL isCustomResolution(CGSize res) { } - (void)viewDidLoad { - + // return; BOOL isIPad = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad); if(isIPad) [self layoutWidgetes]; // layout for ipad tmply diff --git a/Moonlight.xcodeproj/project.pbxproj b/Moonlight.xcodeproj/project.pbxproj index 50eb02b9..acfcf881 100644 --- a/Moonlight.xcodeproj/project.pbxproj +++ b/Moonlight.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 18341A042DEB662C0094E5F2 /* FixedTintImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18341A032DEB662C0094E5F2 /* FixedTintImageView.m */; }; 189AD29A2DE7446000E24B88 /* HostCollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 189AD2992DE7446000E24B88 /* HostCollectionViewController.m */; }; 840751B32BF49C050096B657 /* CustomTapGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 840751B22BF49C050096B657 /* CustomTapGestureRecognizer.m */; }; 841BAC922DE35D6B00DA639E /* ThemeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 841BAC912DE35D6B00DA639E /* ThemeManager.m */; }; @@ -128,6 +129,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 18341A022DEB65AB0094E5F2 /* FixedTintImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FixedTintImageView.h; sourceTree = ""; }; + 18341A032DEB662C0094E5F2 /* FixedTintImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FixedTintImageView.m; sourceTree = ""; }; 189AD2962DE743B700E24B88 /* HostCollectionViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HostCollectionViewController.h; sourceTree = ""; }; 189AD2992DE7446000E24B88 /* HostCollectionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HostCollectionViewController.m; sourceTree = ""; }; 566E9D2B2770B23A00EF7BFE /* Moonlight v1.7.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.7.xcdatamodel"; sourceTree = ""; }; @@ -500,6 +503,8 @@ FBD3495F1A004453002D2A60 /* Database */, FB290CFA19B2C406004C83CF /* Supporting Files */, FB290D0219B2C406004C83CF /* AppDelegate.h */, + 18341A022DEB65AB0094E5F2 /* FixedTintImageView.h */, + 18341A032DEB662C0094E5F2 /* FixedTintImageView.m */, FB290D0319B2C406004C83CF /* AppDelegate.m */, 848F45682DDCD0D600581E36 /* HostCardView.h */, 848F45692DDCD12500581E36 /* HostCardView.m */, @@ -928,6 +933,7 @@ FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */, 84351B2B2C29AD6100A77989 /* LayoutOnScreenControlsViewController.m in Sources */, 84351B5C2C29ADBE00A77989 /* ProfileTableViewCell.m in Sources */, + 18341A042DEB662C0094E5F2 /* FixedTintImageView.m in Sources */, FB89463119F646E200339C8A /* StreamManager.m in Sources */, 84351B2D2C29AD6100A77989 /* ToolBarContainerView.m in Sources */, 988FCD41293B091B003050E2 /* KeyboardInputField.m in Sources */,