新增聊天记录

This commit is contained in:
2026-01-26 18:17:02 +08:00
parent f9d7579536
commit 6a177ceebc
14 changed files with 1447 additions and 18 deletions

View File

@@ -0,0 +1,202 @@
//
// KBVoiceInputBar.m
// keyBoard
//
// Created by Kiro on 2026/1/26.
//
#import "KBVoiceInputBar.h"
#import "KBAiRecordButton.h"
#import <Masonry/Masonry.h>
@interface KBVoiceInputBar () <KBAiRecordButtonDelegate>
///
@property (nonatomic, strong) UIView *backgroundView;
///
@property (nonatomic, strong) UIVisualEffectView *blurEffectView;
///
@property (nonatomic, strong) UILabel *statusLabel;
///
@property (nonatomic, strong) KBAiRecordButton *recordButton;
///
@property (nonatomic, assign) BOOL isRecording;
@end
@implementation KBVoiceInputBar
#pragma mark - Lifecycle
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupUI];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
[self setupUI];
}
return self;
}
#pragma mark - 1
- (void)setupUI {
self.backgroundColor = [UIColor clearColor];
self.enabled = YES;
self.isRecording = NO;
//
[self addSubview:self.backgroundView];
[self.backgroundView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
//
[self.backgroundView addSubview:self.blurEffectView];
[self.blurEffectView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.backgroundView);
}];
// blurEffectView mask
CAGradientLayer *maskLayer = [CAGradientLayer layer];
maskLayer.startPoint = CGPointMake(0.5, 1); //
maskLayer.endPoint = CGPointMake(0.5, 0); //
maskLayer.colors = @[
(__bridge id)[UIColor whiteColor].CGColor, //
(__bridge id)[UIColor whiteColor].CGColor, //
(__bridge id)[UIColor clearColor].CGColor //
];
maskLayer.locations = @[@(0.0), @(0.5), @(1.0)];
self.blurEffectView.layer.mask = maskLayer;
//
[self addSubview:self.statusLabel];
[self.statusLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(16);
make.left.equalTo(self).offset(20);
make.right.equalTo(self).offset(-20);
make.height.mas_equalTo(20);
}];
//
[self addSubview:self.recordButton];
[self.recordButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.statusLabel.mas_bottom).offset(12);
make.left.equalTo(self).offset(20);
make.right.equalTo(self).offset(-20);
make.height.mas_equalTo(50);
make.bottom.lessThanOrEqualTo(self).offset(-16);
}];
}
- (void)layoutSubviews {
[super layoutSubviews];
// mask frame
if (self.blurEffectView.layer.mask) {
self.blurEffectView.layer.mask.frame = self.blurEffectView.bounds;
}
}
#pragma mark - Setter
- (void)setStatusText:(NSString *)statusText {
_statusText = [statusText copy];
self.statusLabel.text = statusText;
}
- (void)setEnabled:(BOOL)enabled {
_enabled = enabled;
self.recordButton.userInteractionEnabled = enabled;
self.recordButton.alpha = enabled ? 1.0 : 0.5;
}
- (void)setRecording:(BOOL)recording {
_isRecording = recording;
self.recordButton.state = recording ? KBAiRecordButtonStateRecording : KBAiRecordButtonStateNormal;
}
#pragma mark - Public Methods
- (void)updateVolumeRMS:(float)rms {
[self.recordButton updateVolumeRMS:rms];
}
#pragma mark - KBAiRecordButtonDelegate
- (void)recordButtonDidBeginPress:(KBAiRecordButton *)button {
if (!self.enabled) {
return;
}
self.isRecording = YES;
if ([self.delegate respondsToSelector:@selector(voiceInputBarDidBeginRecording:)]) {
[self.delegate voiceInputBarDidBeginRecording:self];
}
}
- (void)recordButtonDidEndPress:(KBAiRecordButton *)button {
self.isRecording = NO;
if ([self.delegate respondsToSelector:@selector(voiceInputBarDidEndRecording:)]) {
[self.delegate voiceInputBarDidEndRecording:self];
}
}
- (void)recordButtonDidCancelPress:(KBAiRecordButton *)button {
self.isRecording = NO;
if ([self.delegate respondsToSelector:@selector(voiceInputBarDidCancelRecording:)]) {
[self.delegate voiceInputBarDidCancelRecording:self];
}
}
#pragma mark - Lazy Load
- (UIView *)backgroundView {
if (!_backgroundView) {
_backgroundView = [[UIView alloc] init];
_backgroundView.clipsToBounds = YES;
}
return _backgroundView;
}
- (UIVisualEffectView *)blurEffectView {
if (!_blurEffectView) {
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
_blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
}
return _blurEffectView;
}
- (UILabel *)statusLabel {
if (!_statusLabel) {
_statusLabel = [[UILabel alloc] init];
_statusLabel.text = @"按住按钮开始对话";
_statusLabel.font = [UIFont systemFontOfSize:14];
_statusLabel.textColor = [UIColor secondaryLabelColor];
_statusLabel.textAlignment = NSTextAlignmentCenter;
}
return _statusLabel;
}
- (KBAiRecordButton *)recordButton {
if (!_recordButton) {
_recordButton = [[KBAiRecordButton alloc] init];
_recordButton.delegate = self;
_recordButton.normalTitle = @"按住说话";
_recordButton.recordingTitle = @"松开结束";
}
return _recordButton;
}
@end