跨进程 键盘用ai 在主应用里也要显示
This commit is contained in:
@@ -2,7 +2,11 @@
|
|||||||
"permissions": {
|
"permissions": {
|
||||||
"allow": [
|
"allow": [
|
||||||
"WebSearch",
|
"WebSearch",
|
||||||
"Bash(git checkout:*)"
|
"Bash(git checkout:*)",
|
||||||
|
"Bash(xcodebuild:*)",
|
||||||
|
"Bash(plutil:*)",
|
||||||
|
"Bash(find:*)",
|
||||||
|
"Bash(ls:*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,6 +371,9 @@ static const NSUInteger kKBChatMessageLimit = 6;
|
|||||||
audioId:response.data.audioId];
|
audioId:response.data.audioId];
|
||||||
NSLog(@"[KB] AI 消息添加完成");
|
NSLog(@"[KB] AI 消息添加完成");
|
||||||
|
|
||||||
|
// 通知主 App 刷新对应 persona 的聊天记录
|
||||||
|
[self kb_notifyMainAppChatUpdatedWithCompanionId:companionId];
|
||||||
|
|
||||||
// 如果有 audioId,开始预加载音频
|
// 如果有 audioId,开始预加载音频
|
||||||
if (response.data.audioId.length > 0) {
|
if (response.data.audioId.length > 0) {
|
||||||
[self kb_preloadAudioWithAudioId:
|
[self kb_preloadAudioWithAudioId:
|
||||||
@@ -671,6 +674,22 @@ static const NSUInteger kKBChatMessageLimit = 6;
|
|||||||
NSLog(@"[Keyboard] 开始播放音频,时长: %.2f秒", player.duration);
|
NSLog(@"[Keyboard] 开始播放音频,时长: %.2f秒", player.duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Notify Main App
|
||||||
|
|
||||||
|
/// 通知主 App 刷新对应 persona 的聊天记录
|
||||||
|
- (void)kb_notifyMainAppChatUpdatedWithCompanionId:(NSInteger)companionId {
|
||||||
|
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||||
|
[ud setInteger:companionId forKey:AppGroup_ChatUpdatedCompanionId];
|
||||||
|
[ud synchronize];
|
||||||
|
|
||||||
|
CFNotificationCenterPostNotification(
|
||||||
|
CFNotificationCenterGetDarwinNotifyCenter(),
|
||||||
|
(__bridge CFStringRef)kKBDarwinChatUpdated,
|
||||||
|
NULL, NULL, true);
|
||||||
|
|
||||||
|
NSLog(@"[KB] 已通知主 App 刷新 companionId=%ld 的聊天记录", (long)companionId);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - KBChatLimitPopViewDelegate
|
#pragma mark - KBChatLimitPopViewDelegate
|
||||||
|
|
||||||
- (void)chatLimitPopViewDidTapCancel:(KBChatLimitPopView *)view {
|
- (void)chatLimitPopViewDidTapCancel:(KBChatLimitPopView *)view {
|
||||||
|
|||||||
@@ -30,6 +30,12 @@
|
|||||||
/// 用户头像 URL(主 App 写入,键盘扩展读取)
|
/// 用户头像 URL(主 App 写入,键盘扩展读取)
|
||||||
#define AppGroup_UserAvatarURL @"AppGroup_UserAvatarURL"
|
#define AppGroup_UserAvatarURL @"AppGroup_UserAvatarURL"
|
||||||
|
|
||||||
|
/// 键盘扩展聊天更新的 companionId(键盘写入,主 App 读取后刷新对应聊天记录)
|
||||||
|
#define AppGroup_ChatUpdatedCompanionId @"AppGroup_ChatUpdatedCompanionId"
|
||||||
|
|
||||||
|
/// Darwin 跨进程通知:键盘扩展发送聊天消息后通知主 App 刷新
|
||||||
|
#define kKBDarwinChatUpdated @"com.loveKey.nyx.chat.updated"
|
||||||
|
|
||||||
/// 皮肤图标加载模式:
|
/// 皮肤图标加载模式:
|
||||||
/// 0 = 使用本地 Assets 图片名(key_icons 的 value 写成图片名,例如 "kb_q_melon")
|
/// 0 = 使用本地 Assets 图片名(key_icons 的 value 写成图片名,例如 "kb_q_melon")
|
||||||
/// 1 = 使用远程 Zip 皮肤包(skinJSON 中提供 zip_url;key_icons 的 value 写成 Zip 内图标文件名,例如 "key_a")
|
/// 1 = 使用远程 Zip 皮肤包(skinJSON 中提供 zip_url;key_icons 的 value 写成 Zip 内图标文件名,例如 "key_a")
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
/// 当前 Cell 不再是屏幕主显示页
|
/// 当前 Cell 不再是屏幕主显示页
|
||||||
- (void)onResignedCurrentPersonaCell;
|
- (void)onResignedCurrentPersonaCell;
|
||||||
|
|
||||||
|
/// 刷新聊天记录(重置分页状态,从第一页重新加载)
|
||||||
|
- (void)refreshChatHistory;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|||||||
@@ -256,7 +256,20 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
|
|||||||
if (self.hasLoadedData || self.isLoading) {
|
if (self.hasLoadedData || self.isLoading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self loadChatHistory];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)refreshChatHistory {
|
||||||
|
// 重置分页状态
|
||||||
|
self.currentPage = 1;
|
||||||
|
self.hasMoreHistory = YES;
|
||||||
|
self.hasLoadedData = NO;
|
||||||
|
self.isLoading = NO;
|
||||||
|
|
||||||
|
// 清空当前消息并重新加载
|
||||||
|
[self.messages removeAllObjects];
|
||||||
|
[self.chatView clearMessages];
|
||||||
[self loadChatHistory];
|
[self loadChatHistory];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,19 @@
|
|||||||
|
|
||||||
static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||||
|
|
||||||
|
#pragma mark - Darwin Notification Callback (键盘扩展聊天更新)
|
||||||
|
|
||||||
|
static void KBChatUpdatedDarwinCallback(CFNotificationCenterRef center,
|
||||||
|
void *observer,
|
||||||
|
CFStringRef name,
|
||||||
|
const void *object,
|
||||||
|
CFDictionaryRef userInfo) {
|
||||||
|
KBAIHomeVC *self = (__bridge KBAIHomeVC *)observer;
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[self kb_handleChatUpdatedFromExtension];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Keyboard Gate
|
#pragma mark - Keyboard Gate
|
||||||
|
|
||||||
/// 查找当前 view 树里的 firstResponder
|
/// 查找当前 view 树里的 firstResponder
|
||||||
@@ -163,6 +176,15 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
|||||||
[self setupKeyboardNotifications];
|
[self setupKeyboardNotifications];
|
||||||
[self setupKeyboardDismissGesture];
|
[self setupKeyboardDismissGesture];
|
||||||
[self loadPersonas];
|
[self loadPersonas];
|
||||||
|
|
||||||
|
// 监听键盘扩展聊天更新的 Darwin 跨进程通知
|
||||||
|
CFNotificationCenterAddObserver(
|
||||||
|
CFNotificationCenterGetDarwinNotifyCenter(),
|
||||||
|
(__bridge const void *)(self),
|
||||||
|
KBChatUpdatedDarwinCallback,
|
||||||
|
(__bridge CFStringRef)kKBDarwinChatUpdated,
|
||||||
|
NULL,
|
||||||
|
CFNotificationSuspensionBehaviorDeliverImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated {
|
- (void)viewDidAppear:(BOOL)animated {
|
||||||
@@ -763,6 +785,36 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - 键盘扩展聊天更新处理
|
||||||
|
|
||||||
|
/// 收到键盘扩展的聊天更新通知后,刷新对应 persona 的聊天记录
|
||||||
|
- (void)kb_handleChatUpdatedFromExtension {
|
||||||
|
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||||
|
NSInteger companionId = [ud integerForKey:AppGroup_ChatUpdatedCompanionId];
|
||||||
|
if (companionId <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"[KBAIHomeVC] 收到键盘扩展聊天更新通知,companionId=%ld", (long)companionId);
|
||||||
|
|
||||||
|
// 查找对应 persona 的索引
|
||||||
|
NSInteger index = [self indexOfPersonaId:companionId];
|
||||||
|
if (index == NSNotFound) {
|
||||||
|
NSLog(@"[KBAIHomeVC] 未找到 companionId=%ld 对应的 persona", (long)companionId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取对应的 cell 并刷新聊天记录
|
||||||
|
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
|
||||||
|
KBPersonaChatCell *cell = (KBPersonaChatCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
|
||||||
|
if (cell) {
|
||||||
|
[cell refreshChatHistory];
|
||||||
|
NSLog(@"[KBAIHomeVC] 已触发 companionId=%ld 的聊天记录刷新", (long)companionId);
|
||||||
|
} else {
|
||||||
|
NSLog(@"[KBAIHomeVC] companionId=%ld 的 cell 不可见,下次显示时会自动加载", (long)companionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (NSInteger)indexOfPersonaId:(NSInteger)personaId {
|
- (NSInteger)indexOfPersonaId:(NSInteger)personaId {
|
||||||
if (personaId <= 0) {
|
if (personaId <= 0) {
|
||||||
return NSNotFound;
|
return NSNotFound;
|
||||||
@@ -1360,6 +1412,11 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
|||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
CFNotificationCenterRemoveObserver(
|
||||||
|
CFNotificationCenterGetDarwinNotifyCenter(),
|
||||||
|
(__bridge const void *)(self),
|
||||||
|
(__bridge CFStringRef)kKBDarwinChatUpdated,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
Reference in New Issue
Block a user