This commit is contained in:
2026-01-23 21:51:37 +08:00
parent 6ad9783bcb
commit 77fd46aa34
26 changed files with 3681 additions and 199 deletions

View File

@@ -0,0 +1,68 @@
//
// KBAiChatMessage.h
// keyBoard
//
// Created by Kiro on 2026/1/23.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// 消息类型
typedef NS_ENUM(NSInteger, KBAiChatMessageType) {
KBAiChatMessageTypeUser, // 用户消息
KBAiChatMessageTypeAssistant, // AI 回复
KBAiChatMessageTypeTime // 时间戳
};
/// AI 聊天消息模型
@interface KBAiChatMessage : NSObject
/// 消息类型
@property (nonatomic, assign) KBAiChatMessageType type;
/// 文本内容
@property (nonatomic, copy) NSString *text;
/// 消息时间戳
@property (nonatomic, strong) NSDate *timestamp;
/// 语音时长(秒)- 仅 AI 消息使用
@property (nonatomic, assign) NSTimeInterval audioDuration;
/// 语音数据 - 仅 AI 消息使用
@property (nonatomic, strong, nullable) NSData *audioData;
/// 音频 ID - 用于异步加载音频
@property (nonatomic, copy, nullable) NSString *audioId;
/// 是否完成(用于打字机效果)
@property (nonatomic, assign) BOOL isComplete;
/// 是否需要打字机效果(只有当前正在输入的消息才需要)
@property (nonatomic, assign) BOOL needsTypewriterEffect;
#pragma mark - 便捷构造方法
/// 创建用户消息
+ (instancetype)userMessageWithText:(NSString *)text;
/// 创建 AI 消息(带语音)
+ (instancetype)assistantMessageWithText:(NSString *)text
audioDuration:(NSTimeInterval)duration
audioData:(nullable NSData *)audioData;
/// 创建 AI 消息(带 audioId异步加载音频
+ (instancetype)assistantMessageWithText:(NSString *)text
audioId:(nullable NSString *)audioId;
/// 创建 AI 消息(仅文本,无音频)
+ (instancetype)assistantMessageWithText:(NSString *)text;
/// 创建时间戳消息
+ (instancetype)timeMessageWithTimestamp:(NSDate *)timestamp;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,67 @@
//
// KBAiChatMessage.m
// keyBoard
//
// Created by Kiro on 2026/1/23.
//
#import "KBAiChatMessage.h"
@implementation KBAiChatMessage
+ (instancetype)userMessageWithText:(NSString *)text {
KBAiChatMessage *message = [[KBAiChatMessage alloc] init];
message.type = KBAiChatMessageTypeUser;
message.text = text;
message.timestamp = [NSDate date];
message.isComplete = YES;
return message;
}
+ (instancetype)assistantMessageWithText:(NSString *)text
audioDuration:(NSTimeInterval)duration
audioData:(NSData *)audioData {
KBAiChatMessage *message = [[KBAiChatMessage alloc] init];
message.type = KBAiChatMessageTypeAssistant;
message.text = text;
message.timestamp = [NSDate date];
message.audioDuration = duration;
message.audioData = audioData;
message.isComplete = NO;
return message;
}
+ (instancetype)assistantMessageWithText:(NSString *)text
audioId:(NSString *)audioId {
KBAiChatMessage *message = [[KBAiChatMessage alloc] init];
message.type = KBAiChatMessageTypeAssistant;
message.text = text;
message.timestamp = [NSDate date];
message.audioId = audioId;
message.audioDuration = 0;
message.audioData = nil;
message.isComplete = NO;
return message;
}
+ (instancetype)assistantMessageWithText:(NSString *)text {
KBAiChatMessage *message = [[KBAiChatMessage alloc] init];
message.type = KBAiChatMessageTypeAssistant;
message.text = text;
message.timestamp = [NSDate date];
message.audioId = nil;
message.audioDuration = 0;
message.audioData = nil;
message.isComplete = NO;
return message;
}
+ (instancetype)timeMessageWithTimestamp:(NSDate *)timestamp {
KBAiChatMessage *message = [[KBAiChatMessage alloc] init];
message.type = KBAiChatMessageTypeTime;
message.timestamp = timestamp;
message.isComplete = YES;
return message;
}
@end