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,358 @@
//
// SellyCallControlView.m
// SellyCloudSDK_Example
//
// Created by Caleb on 12/17/25.
// Copyright © 2025 Caleb. All rights reserved.
//
#import "SellyCallControlView.h"
#import <Masonry/Masonry.h>
@interface SellyCallControlView ()
@property (nonatomic, strong) UIButton *speakerButton;
@property (nonatomic, strong) UIButton *videoButton;
@property (nonatomic, strong) UIButton *switchCameraButton;
@property (nonatomic, strong) UIButton *muteButton;
@property (nonatomic, strong) UIButton *pipButton;
@property (nonatomic, strong) UIButton *screenShareButton;
@property (nonatomic, strong) UIButton *hangupButton;
@property (nonatomic, strong) UIStackView *mainStackView; //
@property (nonatomic, strong) UIStackView *topButtonStackView; //
@property (nonatomic, strong) UIStackView *bottomButtonStackView; //
@end
@implementation SellyCallControlView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupUI];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self setupUI];
}
return self;
}
- (void)setupUI {
//
self.backgroundColor = [UIColor clearColor];
//
self.mainStackView = [[UIStackView alloc] init];
self.mainStackView.axis = UILayoutConstraintAxisVertical;
self.mainStackView.distribution = UIStackViewDistributionFillEqually;
self.mainStackView.alignment = UIStackViewAlignmentFill;
self.mainStackView.spacing = 10;
[self addSubview:self.mainStackView];
//
self.topButtonStackView = [[UIStackView alloc] init];
self.topButtonStackView.axis = UILayoutConstraintAxisHorizontal;
self.topButtonStackView.distribution = UIStackViewDistributionEqualSpacing;
self.topButtonStackView.alignment = UIStackViewAlignmentCenter;
self.topButtonStackView.spacing = 0;
//
self.bottomButtonStackView = [[UIStackView alloc] init];
self.bottomButtonStackView.axis = UILayoutConstraintAxisHorizontal;
self.bottomButtonStackView.distribution = UIStackViewDistributionEqualSpacing;
self.bottomButtonStackView.alignment = UIStackViewAlignmentCenter;
self.bottomButtonStackView.spacing = 0;
[self.mainStackView addArrangedSubview:self.topButtonStackView];
[self.mainStackView addArrangedSubview:self.bottomButtonStackView];
//
self.speakerButton = [self createButtonWithImageName:@"speaker" title:@"扬声器" action:@selector(speakerButtonTapped:)];
self.videoButton = [self createButtonWithImageName:@"video" title:@"视频" action:@selector(videoButtonTapped:)];
self.switchCameraButton = [self createButtonWithImageName:@"switch_camera" title:@"切换" action:@selector(switchCameraButtonTapped:)];
self.muteButton = [self createButtonWithImageName:@"microphone" title:@"静音" action:@selector(muteButtonTapped:)];
self.pipButton = [self createButtonWithImageName:@"pip" title:@"画中画" action:@selector(pipButtonTapped:)];
self.screenShareButton = [self createButtonWithImageName:@"screen_share" title:@"共享屏幕" action:@selector(screenShareButtonTapped:)];
self.hangupButton = [self createButtonWithImageName:@"hangup" title:@"挂断" action:@selector(hangupButtonTapped:)];
//
UIView *hangupIconBackground = [self.hangupButton viewWithTag:999];
if (hangupIconBackground) {
hangupIconBackground.backgroundColor = [UIColor colorWithRed:0.9 green:0.2 blue:0.2 alpha:1.0];
}
// 4
[self.topButtonStackView addArrangedSubview:self.speakerButton];
[self.topButtonStackView addArrangedSubview:self.videoButton];
[self.topButtonStackView addArrangedSubview:self.switchCameraButton];
[self.topButtonStackView addArrangedSubview:self.muteButton];
// PiP
// PiP
self.pipButton.hidden = YES;
self.screenShareButton.hidden = YES;
[self.bottomButtonStackView addArrangedSubview:self.pipButton];
[self.bottomButtonStackView addArrangedSubview:self.screenShareButton];
[self.bottomButtonStackView addArrangedSubview:self.hangupButton];
// - 使 Masonry
[self.mainStackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.equalTo(self).offset(15);
make.trailing.equalTo(self).offset(-15);
make.top.equalTo(self).offset(10);
make.bottom.equalTo(self).offset(-10);
}];
//
[self.topButtonStackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.trailing.equalTo(self.mainStackView);
}];
// 2
[self.bottomButtonStackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.mainStackView);
make.width.mas_lessThanOrEqualTo(self.mainStackView);
}];
}
- (UIButton *)createButtonWithImageName:(NSString *)imageName title:(NSString *)title action:(SEL)action {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//
UIView *containerView = [[UIView alloc] init];
containerView.userInteractionEnabled = NO;
[button addSubview:containerView];
//
UIView *iconBackground = [[UIView alloc] init];
iconBackground.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2];
iconBackground.layer.cornerRadius = 26; // 52/2 = 26
iconBackground.clipsToBounds = YES;
iconBackground.userInteractionEnabled = NO;
iconBackground.tag = 999; // tag便
[containerView addSubview:iconBackground];
// 使
UIImage *icon = [self systemImageForButtonName:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:icon];
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.tintColor = [UIColor whiteColor];
imageView.userInteractionEnabled = NO;
[iconBackground addSubview:imageView];
//
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.text = title;
titleLabel.textColor = [UIColor whiteColor];
titleLabel.font = [UIFont systemFontOfSize:12];
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.userInteractionEnabled = NO;
[containerView addSubview:titleLabel];
// 使 Masonry
[containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(button);
make.width.mas_equalTo(70);
make.height.mas_equalTo(90);
}];
[iconBackground mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(containerView);
make.top.equalTo(containerView);
make.width.height.mas_equalTo(52);
}];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(iconBackground);
make.width.height.mas_equalTo(28);
}];
[titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(iconBackground.mas_bottom).offset(8);
make.centerX.equalTo(containerView);
make.leading.trailing.equalTo(containerView);
}];
[button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
//
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(70);
make.height.mas_equalTo(90);
}];
return button;
}
- (UIImage *)systemImageForButtonName:(NSString *)name {
NSString *systemName = @"questionmark.circle";
if ([name isEqualToString:@"speaker"]) {
systemName = @"speaker.wave.2.fill";
} else if ([name isEqualToString:@"video"]) {
systemName = @"video.fill";
} else if ([name isEqualToString:@"switch_camera"]) {
systemName = @"arrow.triangle.2.circlepath.camera.fill";
} else if ([name isEqualToString:@"microphone"]) {
systemName = @"mic.fill";
} else if ([name isEqualToString:@"pip"]) {
systemName = @"pip.fill";
} else if ([name isEqualToString:@"screen_share"]) {
systemName = @"rectangle.on.rectangle";
} else if ([name isEqualToString:@"hangup"]) {
systemName = @"phone.down.fill";
}
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
return [UIImage systemImageNamed:systemName withConfiguration:config];
}
#pragma mark - Button Actions
- (void)speakerButtonTapped:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(callControlView:didTapAction:)]) {
[self.delegate callControlView:self didTapAction:SellyCallControlActionSpeaker];
}
}
- (void)videoButtonTapped:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(callControlView:didTapAction:)]) {
[self.delegate callControlView:self didTapAction:SellyCallControlActionVideo];
}
}
- (void)switchCameraButtonTapped:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(callControlView:didTapAction:)]) {
[self.delegate callControlView:self didTapAction:SellyCallControlActionSwitchCamera];
}
}
- (void)muteButtonTapped:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(callControlView:didTapAction:)]) {
[self.delegate callControlView:self didTapAction:SellyCallControlActionMute];
}
}
- (void)hangupButtonTapped:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(callControlView:didTapAction:)]) {
[self.delegate callControlView:self didTapAction:SellyCallControlActionHangup];
}
}
- (void)pipButtonTapped:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(callControlView:didTapAction:)]) {
[self.delegate callControlView:self didTapAction:SellyCallControlActionPiP];
}
}
- (void)screenShareButtonTapped:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(callControlView:didTapAction:)]) {
[self.delegate callControlView:self didTapAction:SellyCallControlActionScreenShare];
}
}
#pragma mark - Public Methods
- (void)setShowPiPButton:(BOOL)showPiPButton {
_showPiPButton = showPiPButton;
self.pipButton.hidden = !showPiPButton;
}
- (void)setShowScreenShareButton:(BOOL)showScreenShareButton {
_showScreenShareButton = showScreenShareButton;
self.screenShareButton.hidden = !showScreenShareButton;
}
- (void)updateSpeakerEnabled:(BOOL)enabled {
//
UIView *iconBackground = self.speakerButton.subviews.firstObject.subviews.firstObject;
if (enabled) {
iconBackground.backgroundColor = [UIColor colorWithRed:0.2 green:0.5 blue:1.0 alpha:1.0];
NSString *systemName = @"speaker.wave.2.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
} else {
iconBackground.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2];
NSString *systemName = @"speaker.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
}
}
- (void)updateVideoEnabled:(BOOL)enabled {
UIView *iconBackground = self.videoButton.subviews.firstObject.subviews.firstObject;
if (enabled) {
iconBackground.backgroundColor = [UIColor colorWithRed:0.2 green:0.5 blue:1.0 alpha:1.0];
NSString *systemName = @"video.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
} else {
iconBackground.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2];
NSString *systemName = @"video.slash.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
}
}
- (void)updateMuteEnabled:(BOOL)muted {
UIView *iconBackground = self.muteButton.subviews.firstObject.subviews.firstObject;
if (muted) {
iconBackground.backgroundColor = [UIColor colorWithRed:0.9 green:0.2 blue:0.2 alpha:1.0];
NSString *systemName = @"mic.slash.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
} else {
iconBackground.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2];
NSString *systemName = @"mic.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
}
}
- (void)updatePiPEnabled:(BOOL)enabled {
UIView *iconBackground = self.pipButton.subviews.firstObject.subviews.firstObject;
if (enabled) {
iconBackground.backgroundColor = [UIColor colorWithRed:0.2 green:0.5 blue:1.0 alpha:1.0];
NSString *systemName = @"pip.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
} else {
iconBackground.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2];
NSString *systemName = @"pip";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
}
}
- (void)updateScreenShareEnabled:(BOOL)enabled {
UIView *iconBackground = self.screenShareButton.subviews.firstObject.subviews.firstObject;
if (enabled) {
iconBackground.backgroundColor = [UIColor colorWithRed:0.2 green:0.5 blue:1.0 alpha:1.0];
NSString *systemName = @"rectangle.on.rectangle.fill";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
} else {
iconBackground.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.2];
NSString *systemName = @"rectangle.on.rectangle";
UIImageSymbolConfiguration *config = [UIImageSymbolConfiguration configurationWithPointSize:28 weight:UIImageSymbolWeightMedium scale:UIImageSymbolScaleMedium];
UIImageView *imageView = (UIImageView *)iconBackground.subviews.firstObject;
imageView.image = [UIImage systemImageNamed:systemName withConfiguration:config];
}
}
@end