initial commit

This commit is contained in:
Caleb
2026-03-01 15:59:27 +08:00
commit a9e97d56cb
1426 changed files with 172367 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
//
// AVSettingsViewController.h
// AVDemo
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface AVSettingsViewController : UIViewController
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,282 @@
//
// 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