283 lines
12 KiB
Objective-C
283 lines
12 KiB
Objective-C
//
|
|
// AVSettingsViewController.m
|
|
// AVDemo
|
|
//
|
|
|
|
#import "AVSettingsViewController.h"
|
|
#import "AVConfigManager.h"
|
|
#import "AVConstants.h"
|
|
#import "AVUserManager.h"
|
|
#import <Masonry/Masonry.h>
|
|
#import "UIView+SellyCloud.h"
|
|
|
|
@interface AVSettingsViewController () <UITextFieldDelegate>
|
|
@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
|