Merge branch 'piptest' into Integration

- PiP & its toolbox special entry
- host update timer

# Conflicts:
#	VoidLink/ViewControllers/MainFrameViewController.m
#	VoidLink/ViewControllers/StreamFrameViewController.m
This commit is contained in:
TrueZhuanjia
2025-07-12 16:41:47 +08:00
36 changed files with 655 additions and 196 deletions
@@ -429,7 +429,7 @@ static NSMutableSet* hostList;
while (host.state == StateUnknown) {
sleep(1);
}
// Don't bother polling if the server is already offline
if (host.state == StateOffline) {
dispatch_async(dispatch_get_main_queue(), ^{
@@ -439,16 +439,16 @@ static NSMutableSet* hostList;
});
return;
}
HttpManager* hMan = [[HttpManager alloc] initWithHost:host];
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
// Exempt this host from discovery while handling the serverinfo request
[self->_discMan pauseDiscoveryForHost:host];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest:false]
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
[self->_discMan resumeDiscoveryForHost:host];
if (![serverInfoResp isStatusOk]) {
Log(LOG_W, @"Failed to get server info: %@", serverInfoResp.statusMessage);
dispatch_async(dispatch_get_main_queue(), ^{
@@ -456,20 +456,20 @@ static NSMutableSet* hostList;
[self hideLoadingFrame:nil];
return;
}
UIAlertController* applistAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Connection Failed"]
message:serverInfoResp.statusMessage
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:applistAlert];
[applistAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
// Only display an alert if this was the result of a real
// user action, not just passively entering the foreground again
[self hideLoadingFrame: ^{
[self switchToHostView];
[[self activeViewController] presentViewController:applistAlert animated:YES completion:nil];
}];
host.state = StateOffline;
});
} else {
@@ -570,7 +570,7 @@ static NSMutableSet* hostList;
}];
}
- (UIViewController*) activeViewController {
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
@@ -615,7 +615,7 @@ 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){
UIAlertController* wolAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Wake-On-LAN"] message:@"" preferredStyle:UIAlertControllerStyleAlert];
@@ -830,7 +830,7 @@ static NSMutableSet* hostList;
physicalOutputChannels = 8;
Log(LOG_I, @"System-provided spatial audio available, pretending device has %d channels", physicalOutputChannels);
}
int numberOfChannels = MIN([streamSettings.audioConfig intValue], physicalOutputChannels);
Log(LOG_I, @"Selected number of audio channels %d", numberOfChannels);
if (numberOfChannels >= 8) {
@@ -1126,9 +1126,9 @@ static NSMutableSet* hostList;
// enable / disable widgets acoordingly: in streamview, disable, outside of streamview, enable.
if(self.settingsExpandedInStreamView) [revealController buttonsInStreaming];
else [revealController buttonsNotInStreaming];
[streamFrameViewController setUserInteractionEnabledForStreamView:!_settingsExpandedInStreamView || position == FrontViewPositionLeft];
[settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.resolutionStack];
[settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.fpsStack];
[settingsViewController widget:settingsViewController.bitrateSlider setEnabled:!self.settingsExpandedInStreamView];
@@ -1142,7 +1142,7 @@ static NSMutableSet* hostList;
[settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.citrixX1MouseStack];
[settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.externalDisplayModeStack];
[settingsViewController setHidden:_settingsExpandedInStreamView forStack:settingsViewController.audioConfigStack];
}
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position {
@@ -1282,7 +1282,7 @@ static NSMutableSet* hostList;
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];
@@ -1354,14 +1354,14 @@ static NSMutableSet* hostList;
- (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];
@@ -1411,13 +1411,13 @@ static NSMutableSet* hostList;
self->_addHostButton = [self createAddHostButton];
self->_helpButton = [self createHelpButton];
//[self setupHostViewTitle];
self.navigationItem.rightBarButtonItems = @[_helpButton, _addHostButton]; // 顺序:右边靠右的是第一个
// 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, *)) {
@@ -1429,7 +1429,7 @@ static NSMutableSet* hostList;
} else {
[_settingsButton setTitle:[LocalizationHelper localizedStringForKey:@"Settings"]];
}
// Set the host name button action. When it's tapped, it'll show the host selection view.
_upButton = [[UIBarButtonItem alloc] init];
[self->_upButton setTitle: [LocalizationHelper localizedStringForKey: @"Select New Host"]];
@@ -1499,20 +1499,6 @@ static NSMutableSet* hostList;
}
_boxArtCache = [[NSCache alloc] init];
//recordedScreenWidth = CGRectGetWidth([[UIScreen mainScreen] bounds]);
CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]);
CGFloat screenHeightInPoints = CGRectGetHeight([[UIScreen mainScreen] bounds]);
// deal with scroll host view reload after device orientation change here:
bool isLandscape = screenWidthInPoints > screenHeightInPoints;
CGFloat realViewFrameWidth = self.view.frame.size.width > self.view.frame.size.height ? self.view.frame.size.width : self.view.frame.size.height;
CGFloat realViewFrameHeight = self.view.frame.size.width < self.view.frame.size.height ? self.view.frame.size.width : self.view.frame.size.height;
if(!isLandscape) {
CGFloat tmpLength = realViewFrameWidth;
realViewFrameWidth = realViewFrameHeight;
realViewFrameHeight = tmpLength;
}
self.collectionView.delaysContentTouches = NO;
@@ -1528,10 +1514,10 @@ static NSMutableSet* hostList;
[self updateTitle];
// [self.view addSubview:hostScrollView];
// if ([hostList count] == 1) [self hostClicked:[hostList anyObject] view:nil]; // auto click for single host
//if([SettingsViewController isLandscapeNow] != _streamConfig.width > _streamConfig.height)
//[self simulateSettingsButtonPress]; //force expand setting view if orientation changed since last quit from app.
//[self simulateSettingsButtonPress]; //force expand setting view if orientation changed since last quit from app.
@@ -1543,7 +1529,7 @@ static NSMutableSet* hostList;
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleMenuResize:)];
[self.view addGestureRecognizer:longPress];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:[self isIPhone]?@"iPhone":@"iPad" bundle:nil];
SettingsViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"settingsViewController"];
// 强制加载视图
@@ -1709,7 +1695,7 @@ static NSMutableSet* hostList;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:NO];
// [self setupHostViewTitle];
// [self reloadScrollHostView]; //remove this for proper test
[self attachWaterMark];
@@ -1761,7 +1747,7 @@ static NSMutableSet* hostList;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:NO];
/* this makes background color works*/
for (UIView *subview in self.view.subviews) {
[subview removeFromSuperview]; // 暂时移除所有子视图
@@ -1786,11 +1772,11 @@ static NSMutableSet* hostList;
[self.view addSubview:self.collectionView];
[self initHostCollection];
if(!_enteredAppView) [self switchToHostView];
[self retrieveSavedHosts];
_discMan = [[DiscoveryManager alloc] initWithHosts:[hostList allObjects] andCallback:self];
[self beginForegroundRefresh];
}
@@ -1880,6 +1866,7 @@ static NSMutableSet* hostList;
// Sort the host list in alphabetical order
NSArray* sortedHostList = [[hostList allObjects] sortedArrayUsingSelector:@selector(compareName:)];
for (TemporaryHost* comp in sortedHostList) {
if(comp.state == StateOnline || comp.pairState == PairStatePaired || comp.pairState == PairStateUnknown) [self.hostCollectionVC addHost:comp];
// new host card test
@@ -1889,18 +1876,18 @@ static NSMutableSet* hostList;
//if([comp.name isEqualToString: @"PianoServer"]) {
//if([comp.name isEqualToString: @"TrueZj"]) {
HostCardView *testCard = [[HostCardView alloc] initWithHost:comp];
[self.view addSubview:testCard];
// [testCard resizeBySizeFactor:3];
[NSLayoutConstraint activateConstraints:@[
[testCard.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant:0],
[testCard.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor constant:150],
]];
}*/
//
// Start jobs to decode the box art in advance
for (TemporaryApp* app in comp.appList) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
@@ -1994,7 +1981,7 @@ static NSMutableSet* hostList;
}
_sortedAppList = visibleAppList;
}
[self.collectionView reloadData];
}
@@ -2076,7 +2063,7 @@ static NSMutableSet* hostList;
menuSeparator = [self findMenuSeparator];
if(menuSeparator.hidden || menuSeparator == nil) return;
if(gesture.state == UIGestureRecognizerStateBegan){
if(locationInView.x < 30) {
snapshot = [[UIView alloc] init];
@@ -2087,9 +2074,9 @@ static NSMutableSet* hostList;
}
return;
}
bool isPortrait = screenHeight>screenWidth;
CGFloat limitedWidth = MIN(MAX(locationInSuperView.x, isPortrait ? 200 : 280),isPortrait ? screenWidth*0.75 : screenWidth/2);
if(gesture.state == UIGestureRecognizerStateChanged){
if(snapshot) snapshot.center = CGPointMake(limitedWidth, snapshot.center.y);
@@ -2104,8 +2091,8 @@ static NSMutableSet* hostList;
Settings* settings = [dataMan retrieveSettings];
settings.settingsMenuWidth = [NSNumber numberWithFloat:self.revealViewController.rearViewRevealWidth];
[dataMan saveData];
double delayInSeconds = 0.02;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^{
@@ -2193,7 +2180,7 @@ static NSMutableSet* hostList;
// 添加为子控制器
[self addChildViewController:self.hostCollectionVC];
[self.view addSubview:self.hostCollectionVC.view];
// 设置其布局(Auto Layout 示例)
// CGFloat hostCollectionViewPadding = 75;
CGFloat leftPadding = [self isIPhone] ? 30 : 0;
@@ -2204,10 +2191,10 @@ static NSMutableSet* hostList;
[self.hostCollectionVC.view.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:0],
// [self.hostCollectionVC.view.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:0] //?
]];
// 通知子控制器已添加完成
[self.hostCollectionVC didMoveToParentViewController:self];
}
@end