// // AVSettingsViewController.m // AVDemo // #import "AVSettingsViewController.h" #import "AVConfigManager.h" #import "AVConstants.h" #import "AVUserManager.h" #import #import "UIView+SellyCloud.h" @interface AVSettingsViewController () @property (nonatomic, strong) UIScrollView *scrollView; @property (nonatomic, strong) UIView *contentView; @property (nonatomic, strong) UITextField *nicknameField; @property (nonatomic, strong) UISegmentedControl *resolutionSegment; @property (nonatomic, strong) UITextField *fpsField; @property (nonatomic, strong) UITextField *maxBitrateField; @property (nonatomic, strong) UITextField *minBitrateField; @end @implementation AVSettingsViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor systemBackgroundColor]; self.title = @"设置"; // 添加右上角提交日志按钮 - 延迟设置以避免约束冲突 dispatch_async(dispatch_get_main_queue(), ^{ UIBarButtonItem *uploadLogButton = [[UIBarButtonItem alloc] initWithTitle:@"提交日志" style:UIBarButtonItemStylePlain target:self action:@selector(uploadLogButtonTapped)]; self.navigationItem.rightBarButtonItem = uploadLogButton; }); [self setupUI]; [self loadConfig]; } - (void)setupUI { _scrollView = [[UIScrollView alloc] init]; [self.view addSubview:_scrollView]; _contentView = [[UIView alloc] init]; [_scrollView addSubview:_contentView]; [_scrollView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop); make.left.right.bottom.equalTo(self.view); }]; [_contentView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(_scrollView); make.width.equalTo(_scrollView); }]; CGFloat topOffset = 20; CGFloat spacing = 30; // Nickname topOffset = [self addLabel:@"用户昵称" atOffset:topOffset]; _nicknameField = [self addTextField:@"请输入昵称" atOffset:topOffset]; topOffset += 40 + spacing; // Resolution topOffset = [self addLabel:@"分辨率" atOffset:topOffset]; _resolutionSegment = [[UISegmentedControl alloc] initWithItems:@[@"360p", @"480p", @"540p", @"720p"]]; [_contentView addSubview:_resolutionSegment]; [_resolutionSegment mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(_contentView).offset(20); make.right.equalTo(_contentView).offset(-20); make.top.equalTo(_contentView).offset(topOffset); make.height.equalTo(@32); }]; topOffset += 32 + spacing; // FPS topOffset = [self addLabel:@"帧率 (FPS)" atOffset:topOffset]; _fpsField = [self addTextField:@"例如: 30" atOffset:topOffset]; _fpsField.keyboardType = UIKeyboardTypeNumberPad; topOffset += 40 + spacing; // Max bitrate topOffset = [self addLabel:@"最大码率 (kbps)" atOffset:topOffset]; _maxBitrateField = [self addTextField:@"例如: 2000" atOffset:topOffset]; _maxBitrateField.keyboardType = UIKeyboardTypeNumberPad; topOffset += 40 + spacing; // Min bitrate topOffset = [self addLabel:@"最小码率 (kbps)" atOffset:topOffset]; _minBitrateField = [self addTextField:@"例如: 500" atOffset:topOffset]; _minBitrateField.keyboardType = UIKeyboardTypeNumberPad; topOffset += 40 + spacing; // Save button UIButton *saveButton = [UIButton buttonWithType:UIButtonTypeSystem]; [saveButton setTitle:@"保存设置" forState:UIControlStateNormal]; saveButton.backgroundColor = [UIColor systemBlueColor]; [saveButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; saveButton.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold]; saveButton.layer.cornerRadius = 10; [saveButton addTarget:self action:@selector(saveConfig) forControlEvents:UIControlEventTouchUpInside]; [_contentView addSubview:saveButton]; [saveButton mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(_contentView).offset(20); make.right.equalTo(_contentView).offset(-20); make.top.equalTo(_contentView).offset(topOffset); make.height.equalTo(@50); }]; topOffset += 50 + 20; // Logout button UIButton *logoutButton = [UIButton buttonWithType:UIButtonTypeSystem]; [logoutButton setTitle:@"退出登录" forState:UIControlStateNormal]; logoutButton.backgroundColor = [UIColor systemRedColor]; [logoutButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; logoutButton.titleLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold]; logoutButton.layer.cornerRadius = 10; [logoutButton addTarget:self action:@selector(logoutButtonTapped) forControlEvents:UIControlEventTouchUpInside]; [_contentView addSubview:logoutButton]; [logoutButton mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(_contentView).offset(20); make.right.equalTo(_contentView).offset(-20); make.top.equalTo(_contentView).offset(topOffset); make.height.equalTo(@50); }]; topOffset += 50 + 20; // 设置 contentView 的高度 [_contentView mas_updateConstraints:^(MASConstraintMaker *make) { make.height.equalTo(@(topOffset)); }]; // Dismiss keyboard on tap UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; [self.view addGestureRecognizer:tap]; } - (CGFloat)addLabel:(NSString *)text atOffset:(CGFloat)offset { UILabel *label = [[UILabel alloc] init]; label.text = text; label.font = [UIFont systemFontOfSize:15 weight:UIFontWeightMedium]; label.textColor = [UIColor labelColor]; [_contentView addSubview:label]; [label mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(_contentView).offset(20); make.top.equalTo(_contentView).offset(offset); }]; return offset + 25; } - (UITextField *)addTextField:(NSString *)placeholder atOffset:(CGFloat)offset { UITextField *textField = [[UITextField alloc] init]; textField.placeholder = placeholder; textField.borderStyle = UITextBorderStyleRoundedRect; textField.delegate = self; [_contentView addSubview:textField]; [textField mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(_contentView).offset(20); make.right.equalTo(_contentView).offset(-20); make.top.equalTo(_contentView).offset(offset); make.height.equalTo(@40); }]; return textField; } - (void)loadConfig { AVVideoConfiguration *config = [AVConfigManager sharedManager].globalConfig; _nicknameField.text = config.nickname; _resolutionSegment.selectedSegmentIndex = [config currentResolution]; _fpsField.text = [NSString stringWithFormat:@"%ld", (long)config.videoFrameRate]; _maxBitrateField.text = [NSString stringWithFormat:@"%ld", (long)(config.videoBitRate / 1000)]; _minBitrateField.text = [NSString stringWithFormat:@"%ld", (long)(config.videoMinBitRate / 1000)]; } - (void)saveConfig { AVVideoConfiguration *config = [AVConfigManager sharedManager].globalConfig; config.nickname = _nicknameField.text.length > 0 ? _nicknameField.text : [AVConfigManager generateRandomNickname]; [config setResolution:_resolutionSegment.selectedSegmentIndex]; NSInteger fps = [_fpsField.text integerValue] > 0 ? [_fpsField.text integerValue] : 30; config.videoFrameRate = fps; config.videoMaxKeyframeInterval = fps * 2; NSInteger maxBitrate = [_maxBitrateField.text integerValue] > 0 ? [_maxBitrateField.text integerValue] : 2000; config.videoBitRate = maxBitrate * 1000; // Convert kbps to bps NSInteger minBitrate = [_minBitrateField.text integerValue] > 0 ? [_minBitrateField.text integerValue] : 500; config.videoMinBitRate = minBitrate * 1000; // Convert kbps to bps [[AVConfigManager sharedManager] saveConfig]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"成功" message:@"设置已保存" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; [self presentViewController:alert animated:YES completion:nil]; } - (void)logoutButtonTapped { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"确认退出" message:@"确定要退出登录吗?" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; [alert addAction:cancelAction]; UIAlertAction *logoutAction = [UIAlertAction actionWithTitle:@"退出" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { // 执行登出 [[AVUserManager sharedManager] logout]; // 返回到登录页面 // 通过 TabBarController 触发登录检查 if ([self.tabBarController respondsToSelector:@selector(checkLoginStatus)]) { [self.tabBarController performSelector:@selector(checkLoginStatus)]; } NSLog(@"✅ 已退出登录"); }]; [alert addAction:logoutAction]; [self presentViewController:alert animated:YES completion:nil]; } - (void)uploadLogButtonTapped { // 调用 SellyCloudManager 的 uploadLog 方法 [SellyCloudManager uploadLog:^(NSString * _Nullable url, NSError * _Nullable error) { UIAlertController *resultAlert; if (error) { // 上传失败 resultAlert = [UIAlertController alertControllerWithTitle:@"上传失败" message:[NSString stringWithFormat:@"日志上传失败: %@", error.localizedDescription] preferredStyle:UIAlertControllerStyleAlert]; [resultAlert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; } else { // 上传成功 NSString *message = url ? [NSString stringWithFormat:@"日志已成功上传\n地址: %@", url] : @"日志已成功上传"; resultAlert = [UIAlertController alertControllerWithTitle:@"上传成功" message:message preferredStyle:UIAlertControllerStyleAlert]; NSLog(@"###日志url == %@",url); // 点击确定后将 URL 复制到粘贴板 UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { if (url.length > 0) { UIPasteboard.generalPasteboard.string = url; [self.view showToast:@"日志 URL 已复制到粘贴板"]; } }]; [resultAlert addAction:confirmAction]; } [self presentViewController:resultAlert animated:YES completion:nil]; }]; } - (void)dismissKeyboard { [self.view endEditing:YES]; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; } @end