Compare commits
75 Commits
dev_修改键盘UI
...
fa9af5ff1b
| Author | SHA1 | Date | |
|---|---|---|---|
| fa9af5ff1b | |||
| 08628bcd1d | |||
| 19cb29616f | |||
| 6e50cdcd2a | |||
| f1b52151be | |||
| 993ec623af | |||
| 0416a64235 | |||
| 2b75ad90fb | |||
| 0ac9030f80 | |||
| ea9c40f64f | |||
| 48c90fa0be | |||
| fe59a0cb45 | |||
| 81bc50ce17 | |||
| 6ae504823b | |||
| d2f582b7f8 | |||
| cc82396195 | |||
| 2ff8a7a4af | |||
| 3c0b7e754c | |||
| 3705db4aab | |||
| 36774a8a2c | |||
| 36135313d8 | |||
| 23c0d14128 | |||
| d0c5cada35 | |||
| b556e6841d | |||
| 26096abbcc | |||
| 766c62f3c0 | |||
| 07a77149fc | |||
| 32ebc6fb65 | |||
| 25fbe9b64e | |||
| 4392296616 | |||
| ef52cd4872 | |||
| 70a8466d9f | |||
| 66d85f78a0 | |||
| 93a20cd92a | |||
| 9a54a2ae6c | |||
| 1b9ce1622d | |||
| b4db79eba8 | |||
| 22f77d56ea | |||
| d8d5bdc3ae | |||
| 7d583ceb1d | |||
| 51b744ecd7 | |||
| 3fd7d2af2e | |||
| db869552e4 | |||
| b34de116a3 | |||
| e67bc37571 | |||
| 2b749cd2b0 | |||
| ce889e1ed0 | |||
| e8b4b2c58a | |||
| 3a5a6395af | |||
| a22599feda | |||
| 6a177ceebc | |||
| f9d7579536 | |||
| 0fa31418f6 | |||
| 77fd46aa34 | |||
| 6ad9783bcb | |||
| edc25c159d | |||
| 06a572c08a | |||
| 36c0b0b210 | |||
| d1d47336c2 | |||
| 063ceae10f | |||
| 552387293c | |||
| 93489b09d9 | |||
| 663cb8493b | |||
| ac0d9584d8 | |||
| 7fa124d45f | |||
| 3dfb8f31e2 | |||
| 619c02f236 | |||
| 28852a8d4b | |||
| b021fd308f | |||
| 169a1929d7 | |||
| b5da9f35a5 | |||
| 8f4deaac4e | |||
| d479d1903b | |||
| 32c4138ae0 | |||
| da62d4f411 |
@@ -6,6 +6,8 @@
|
||||
<array>
|
||||
<string>kbkeyboardAppExtension</string>
|
||||
</array>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>需要使用麦克风进行语音输入</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
|
||||
22
CustomKeyboard/KeyboardAssets.xcassets/close_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "close_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "close_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
CustomKeyboard/KeyboardAssets.xcassets/close_icon.imageset/close_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
CustomKeyboard/KeyboardAssets.xcassets/close_icon.imageset/close_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
@@ -18,11 +18,17 @@
|
||||
#import "KBKeyboardSubscriptionProduct.h"
|
||||
#import "KBKeyboardSubscriptionView.h"
|
||||
#import "KBSettingView.h"
|
||||
#import "KBChatMessage.h"
|
||||
#import "KBChatPanelView.h"
|
||||
#import "KBSkinInstallBridge.h"
|
||||
#import "KBSkinManager.h"
|
||||
#import "KBSuggestionEngine.h"
|
||||
#import "KBNetworkManager.h"
|
||||
#import "KBVM.h"
|
||||
#import "Masonry.h"
|
||||
#import "UIImage+KBColor.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <SDWebImage/SDWebImage.h>
|
||||
|
||||
// #import "KBLog.h"
|
||||
|
||||
@@ -34,6 +40,8 @@
|
||||
|
||||
// 以 375 宽设计稿为基准的键盘总高度
|
||||
static const CGFloat kKBKeyboardBaseHeight = 250.0f;
|
||||
static const CGFloat kKBChatPanelHeight = 180;
|
||||
static const NSUInteger kKBChatMessageLimit = 6;
|
||||
static NSString *const kKBDefaultSkinIdLight = @"normal_them";
|
||||
static NSString *const kKBDefaultSkinZipNameLight = @"normal_them";
|
||||
static NSString *const kKBDefaultSkinIdDark = @"normal_hei_them";
|
||||
@@ -57,7 +65,8 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
|
||||
@interface KeyboardViewController () <KBKeyBoardMainViewDelegate,
|
||||
KBFunctionViewDelegate,
|
||||
KBKeyboardSubscriptionViewDelegate>
|
||||
KBKeyboardSubscriptionViewDelegate,
|
||||
KBChatPanelViewDelegate>
|
||||
@property(nonatomic, strong)
|
||||
UIButton *nextKeyboardButton; // 系统“下一个键盘”按钮(可选)
|
||||
@property(nonatomic, strong) UIView *contentView;
|
||||
@@ -67,16 +76,25 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
KBFunctionView *functionView; // 功能面板视图(点击工具栏第0个时显示)
|
||||
@property(nonatomic, strong) KBSettingView *settingView; // 设置页
|
||||
@property(nonatomic, strong) UIImageView *bgImageView; // 背景图(在底层)
|
||||
@property(nonatomic, strong) UIImageView *personaAvatarImageView; // 语音模式下显示的 persona 小头像
|
||||
@property(nonatomic, strong) UIImageView *personaGrayImageView; // 语音模式下显示的 persona 小头像
|
||||
|
||||
@property(nonatomic, strong) KBChatPanelView *chatPanelView;
|
||||
@property(nonatomic, strong) KBKeyboardSubscriptionView *subscriptionView;
|
||||
@property(nonatomic, strong) KBSuggestionEngine *suggestionEngine;
|
||||
@property(nonatomic, copy) NSString *currentWord;
|
||||
@property(nonatomic, assign) BOOL suppressSuggestions;
|
||||
@property(nonatomic, strong) MASConstraint *contentWidthConstraint;
|
||||
@property(nonatomic, strong) MASConstraint *contentHeightConstraint;
|
||||
@property(nonatomic, strong) MASConstraint *keyBoardMainHeightConstraint;
|
||||
@property(nonatomic, strong) MASConstraint *chatPanelHeightConstraint;
|
||||
@property(nonatomic, strong) NSLayoutConstraint *kb_heightConstraint;
|
||||
@property(nonatomic, strong) NSLayoutConstraint *kb_widthConstraint;
|
||||
@property(nonatomic, assign) CGFloat kb_lastPortraitWidth;
|
||||
@property(nonatomic, assign) CGFloat kb_lastKeyboardHeight;
|
||||
@property(nonatomic, strong) NSMutableArray<KBChatMessage *> *chatMessages;
|
||||
@property(nonatomic, strong) AVAudioPlayer *chatAudioPlayer;
|
||||
@property(nonatomic, assign) BOOL chatPanelVisible;
|
||||
@end
|
||||
|
||||
@implementation KeyboardViewController
|
||||
@@ -140,6 +158,8 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||
// 清理 persona 头像内存
|
||||
[self kb_hidePersonaAvatar];
|
||||
}
|
||||
|
||||
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
||||
@@ -167,6 +187,8 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
// 按“短边”宽度等比缩放,横屏保持竖屏布局比例
|
||||
CGFloat portraitWidth = [self kb_portraitWidth];
|
||||
CGFloat keyboardHeight = [self kb_keyboardHeightForWidth:portraitWidth];
|
||||
CGFloat keyboardBaseHeight = [self kb_keyboardBaseHeightForWidth:portraitWidth];
|
||||
CGFloat chatPanelHeight = [self kb_chatPanelHeightForWidth:portraitWidth];
|
||||
CGFloat screenWidth = CGRectGetWidth([UIScreen mainScreen].bounds);
|
||||
CGFloat outerVerticalInset = KBFit(4.0f);
|
||||
|
||||
@@ -210,8 +232,20 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
|
||||
[self.contentView addSubview:self.keyBoardMainView];
|
||||
[self.keyBoardMainView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.contentView);
|
||||
make.left.right.equalTo(self.contentView);
|
||||
make.bottom.equalTo(self.contentView);
|
||||
self.keyBoardMainHeightConstraint =
|
||||
make.height.mas_equalTo(keyboardBaseHeight);
|
||||
}];
|
||||
|
||||
[self.contentView addSubview:self.chatPanelView];
|
||||
[self.chatPanelView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self.contentView);
|
||||
make.bottom.equalTo(self.keyBoardMainView.mas_top);
|
||||
self.chatPanelHeightConstraint =
|
||||
make.height.mas_equalTo(chatPanelHeight);
|
||||
}];
|
||||
self.chatPanelView.hidden = YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
@@ -349,6 +383,9 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
/// 切换显示功能面板/键盘主视图
|
||||
- (void)showFunctionPanel:(BOOL)show {
|
||||
// 简单显隐切换,复用相同的布局区域
|
||||
if (show) {
|
||||
[self showChatPanel:NO];
|
||||
}
|
||||
self.functionView.hidden = !show;
|
||||
self.keyBoardMainView.hidden = show;
|
||||
|
||||
@@ -378,6 +415,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
/// 显示/隐藏设置页(高度与 keyBoardMainView 一致),右侧滑入/滑出
|
||||
- (void)showSettingView:(BOOL)show {
|
||||
if (show) {
|
||||
[self showChatPanel:NO];
|
||||
[[KBMaiPointReporter sharedReporter]
|
||||
reportPageExposureWithEventName:@"enter_keyboard_settings"
|
||||
pageId:@"keyboard_settings"
|
||||
@@ -436,6 +474,40 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
}
|
||||
}
|
||||
|
||||
/// 显示/隐藏聊天面板(覆盖整个键盘区域)
|
||||
- (void)showChatPanel:(BOOL)show {
|
||||
if (show == self.chatPanelVisible) {
|
||||
return;
|
||||
}
|
||||
self.chatPanelVisible = show;
|
||||
if (show) {
|
||||
self.chatPanelView.hidden = NO;
|
||||
self.chatPanelView.alpha = 0.0;
|
||||
[self.contentView bringSubviewToFront:self.chatPanelView];
|
||||
self.functionView.hidden = YES;
|
||||
[self hideSubscriptionPanel];
|
||||
[self showSettingView:NO];
|
||||
[UIView animateWithDuration:0.2
|
||||
delay:0
|
||||
options:UIViewAnimationOptionCurveEaseOut
|
||||
animations:^{
|
||||
self.chatPanelView.alpha = 1.0;
|
||||
}
|
||||
completion:nil];
|
||||
} else {
|
||||
[UIView animateWithDuration:0.18
|
||||
delay:0
|
||||
options:UIViewAnimationOptionCurveEaseIn
|
||||
animations:^{
|
||||
self.chatPanelView.alpha = 0.0;
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
self.chatPanelView.hidden = YES;
|
||||
}];
|
||||
}
|
||||
[self kb_updateKeyboardLayoutIfNeeded];
|
||||
}
|
||||
|
||||
- (void)showSubscriptionPanel {
|
||||
// 1) 先判断权限:未开启“完全访问”则走引导逻辑
|
||||
if (![[KBFullAccessManager shared] hasFullAccess]) {
|
||||
@@ -544,6 +616,10 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
[[KBInputBufferManager shared] appendText:@" "];
|
||||
break;
|
||||
case KBKeyTypeReturn:
|
||||
if (self.chatPanelVisible) {
|
||||
[self kb_handleChatSendAction];
|
||||
break;
|
||||
}
|
||||
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||
[self.textDocumentProxy insertText:@"\n"];
|
||||
[self kb_clearCurrentWord];
|
||||
@@ -575,11 +651,20 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
extra:extra
|
||||
completion:nil];
|
||||
if (index == 0) {
|
||||
[self showChatPanel:NO];
|
||||
[self showFunctionPanel:YES];
|
||||
[self kb_clearCurrentWord];
|
||||
return;
|
||||
}
|
||||
if (index == 1) {
|
||||
[self showFunctionPanel:NO];
|
||||
[self showChatPanel:YES];
|
||||
// 显示 persona 头像
|
||||
[self kb_showPersonaAvatarOnBgImageView];
|
||||
return;
|
||||
}
|
||||
[self showFunctionPanel:NO];
|
||||
[self showChatPanel:NO];
|
||||
}
|
||||
|
||||
- (void)keyBoardMainViewDidTapSettings:(KBKeyBoardMainView *)keyBoardMainView {
|
||||
@@ -697,6 +782,546 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
[self showSubscriptionPanel];
|
||||
}
|
||||
|
||||
#pragma mark - KBChatPanelViewDelegate
|
||||
|
||||
- (void)chatPanelView:(KBChatPanelView *)view didSendText:(NSString *)text {
|
||||
NSString *trim =
|
||||
[text stringByTrimmingCharactersInSet:
|
||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if (trim.length == 0) {
|
||||
return;
|
||||
}
|
||||
[self kb_sendChatText:trim];
|
||||
}
|
||||
|
||||
- (void)chatPanelView:(KBChatPanelView *)view
|
||||
didTapMessage:(KBChatMessage *)message {
|
||||
if (message.audioFilePath.length == 0) {
|
||||
return;
|
||||
}
|
||||
[self kb_playChatAudioAtPath:message.audioFilePath];
|
||||
}
|
||||
|
||||
- (void)chatPanelView:(KBChatPanelView *)view didTapVoiceButtonForMessage:(KBChatMessage *)message {
|
||||
if (!message) return;
|
||||
|
||||
// 如果有 audioData,直接播放
|
||||
if (message.audioData && message.audioData.length > 0) {
|
||||
[self kb_playChatAudioData:message.audioData];
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果有 audioFilePath,播放文件
|
||||
if (message.audioFilePath.length > 0) {
|
||||
[self kb_playChatAudioAtPath:message.audioFilePath];
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[Keyboard] 没有音频数据可播放");
|
||||
}
|
||||
|
||||
- (void)chatPanelViewDidTapClose:(KBChatPanelView *)view {
|
||||
// 清空 chatPanelView 内部的消息
|
||||
[self.chatPanelView kb_reloadWithMessages:@[]];
|
||||
if (self.chatAudioPlayer.isPlaying) {
|
||||
[self.chatAudioPlayer stop];
|
||||
}
|
||||
self.chatAudioPlayer = nil;
|
||||
[self showChatPanel:NO];
|
||||
// 隐藏 persona 头像
|
||||
[self kb_hidePersonaAvatar];
|
||||
}
|
||||
|
||||
#pragma mark - Chat Helpers
|
||||
|
||||
- (void)kb_handleChatSendAction {
|
||||
if (!self.chatPanelVisible) {
|
||||
return;
|
||||
}
|
||||
[[KBInputBufferManager shared] refreshFromProxyIfPossible:self.textDocumentProxy];
|
||||
NSString *rawText = [KBInputBufferManager shared].liveText ?: @"";
|
||||
NSString *trim =
|
||||
[rawText stringByTrimmingCharactersInSet:
|
||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if (trim.length == 0) {
|
||||
[KBHUD showInfo:KBLocalized(@"请输入内容")];
|
||||
return;
|
||||
}
|
||||
[self kb_sendChatText:trim];
|
||||
[self kb_clearHostInputForText:rawText];
|
||||
}
|
||||
|
||||
- (void)kb_sendChatText:(NSString *)text {
|
||||
if (text.length == 0) {
|
||||
return;
|
||||
}
|
||||
NSLog(@"[KB] 发送消息: %@", text);
|
||||
|
||||
KBChatMessage *outgoing = [KBChatMessage userMessageWithText:text];
|
||||
outgoing.avatarURL = [self kb_sharedUserAvatarURL];
|
||||
[self.chatPanelView kb_addUserMessage:text];
|
||||
[self kb_prefetchAvatarForMessage:outgoing];
|
||||
|
||||
if (![[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self.view]) {
|
||||
[KBHUD showInfo:KBLocalized(@"请开启完全访问后使用")];
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加 loading 消息
|
||||
[self.chatPanelView kb_addLoadingAssistantMessage];
|
||||
|
||||
// 调用新的聊天接口
|
||||
[self kb_requestChatMessageWithContent:text];
|
||||
}
|
||||
|
||||
- (void)kb_clearHostInputForText:(NSString *)text {
|
||||
if (text.length == 0) {
|
||||
return;
|
||||
}
|
||||
NSUInteger count = [self kb_composedCharacterCountForString:text];
|
||||
for (NSUInteger i = 0; i < count; i++) {
|
||||
[self.textDocumentProxy deleteBackward];
|
||||
}
|
||||
[[KBInputBufferManager shared] clearAllLiveText];
|
||||
[self kb_clearCurrentWord];
|
||||
}
|
||||
|
||||
- (NSUInteger)kb_composedCharacterCountForString:(NSString *)text {
|
||||
if (text.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
__block NSUInteger count = 0;
|
||||
[text enumerateSubstringsInRange:NSMakeRange(0, text.length)
|
||||
options:NSStringEnumerationByComposedCharacterSequences
|
||||
usingBlock:^(__unused NSString *substring,
|
||||
__unused NSRange substringRange,
|
||||
__unused NSRange enclosingRange,
|
||||
__unused BOOL *stop) {
|
||||
count += 1;
|
||||
}];
|
||||
return count;
|
||||
}
|
||||
|
||||
- (NSString *)kb_sharedUserAvatarURL {
|
||||
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||
NSString *url = [ud stringForKey:AppGroup_UserAvatarURL];
|
||||
return url ?: @"";
|
||||
}
|
||||
|
||||
- (void)kb_prefetchAvatarForMessage:(KBChatMessage *)message {
|
||||
if (!message || message.avatarImage) {
|
||||
return;
|
||||
}
|
||||
NSString *urlString = message.avatarURL ?: @"";
|
||||
if (urlString.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (![[KBFullAccessManager shared] hasFullAccess]) {
|
||||
return;
|
||||
}
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[KBVM shared] downloadAvatarFromURL:urlString completion:^(UIImage *image, NSError *error) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self || !image) return;
|
||||
|
||||
message.avatarImage = image;
|
||||
[self kb_reloadChatRowForMessage:message];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)kb_reloadChatRowForMessage:(KBChatMessage *)message {
|
||||
// 头像预加载完成后不需要刷新表格
|
||||
// 因为键盘扩展的聊天面板不显示头像,所以这里直接返回
|
||||
// 如果将来需要显示头像,可以只刷新特定行而不是整个表格
|
||||
}
|
||||
|
||||
- (void)kb_requestChatAudioForText:(NSString *)text {
|
||||
NSString *mockPath = [self kb_mockChatAudioPath];
|
||||
if (mockPath.length > 0) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.35 * NSEC_PER_SEC)),
|
||||
dispatch_get_main_queue(), ^{
|
||||
NSString *displayText = KBLocalized(@"语音回复");
|
||||
KBChatMessage *incoming =
|
||||
[KBChatMessage messageWithText:displayText
|
||||
outgoing:NO
|
||||
audioFilePath:mockPath];
|
||||
incoming.displayName = KBLocalized(@"AI助手");
|
||||
[self kb_appendChatMessage:incoming];
|
||||
[self kb_playChatAudioAtPath:mockPath];
|
||||
});
|
||||
return;
|
||||
}
|
||||
NSDictionary *payload = @{@"message" : text ?: @""};
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[KBNetworkManager shared] POST:API_AI_TALK
|
||||
jsonBody:payload
|
||||
headers:nil
|
||||
completion:^(NSDictionary *json, NSURLResponse *response,
|
||||
NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
NSString *tip = error.localizedDescription
|
||||
?: KBLocalized(@"请求失败");
|
||||
[KBHUD showInfo:tip];
|
||||
return;
|
||||
}
|
||||
NSString *displayText =
|
||||
[self kb_chatTextFromJSON:json];
|
||||
NSString *audioURL =
|
||||
[self kb_chatAudioURLFromJSON:json];
|
||||
NSString *audioBase64 =
|
||||
[self kb_chatAudioBase64FromJSON:json];
|
||||
if (audioURL.length > 0) {
|
||||
[self kb_downloadChatAudioFromURL:audioURL
|
||||
displayText:displayText];
|
||||
return;
|
||||
}
|
||||
if (audioBase64.length > 0) {
|
||||
NSData *data = [[NSData alloc]
|
||||
initWithBase64EncodedString:audioBase64
|
||||
options:0];
|
||||
if (data.length == 0) {
|
||||
[KBHUD showInfo:KBLocalized(@"音频数据解析失败")];
|
||||
return;
|
||||
}
|
||||
[self kb_handleChatAudioData:data
|
||||
fileExtension:@"m4a"
|
||||
displayText:displayText];
|
||||
return;
|
||||
}
|
||||
[KBHUD showInfo:KBLocalized(@"未获取到音频文件")];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - New Chat API (with typewriter effect and audio preload)
|
||||
|
||||
/// 调用新的聊天接口(返回文本和 audioId)
|
||||
- (void)kb_requestChatMessageWithContent:(NSString *)content {
|
||||
if (content.length == 0) {
|
||||
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||
return;
|
||||
}
|
||||
|
||||
NSInteger companionId = [[KBVM shared] selectedCompanionIdFromAppGroup];
|
||||
NSLog(@"[KB] 请求聊天: companionId=%ld", (long)companionId);
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[KBVM shared] sendChatMessageWithContent:content
|
||||
companionId:companionId
|
||||
completion:^(KBChatResponse *response) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) return;
|
||||
|
||||
if (!response.success) {
|
||||
NSLog(@"[KB] ❌ 请求失败: %@", response.errorMessage);
|
||||
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||
[KBHUD showInfo:response.errorMessage ?: KBLocalized(@"请求失败")];
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[KB] ✅ 收到回复: %@", response.text);
|
||||
|
||||
if (response.text.length == 0) {
|
||||
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||
[KBHUD showInfo:KBLocalized(@"未获取到回复内容")];
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加 AI 消息(带打字机效果)
|
||||
NSLog(@"[KB] 准备添加 AI 消息");
|
||||
[self.chatPanelView kb_addAssistantMessage:response.text audioId:response.audioId];
|
||||
NSLog(@"[KB] AI 消息添加完成");
|
||||
|
||||
// 如果有 audioId,开始预加载音频
|
||||
if (response.audioId.length > 0) {
|
||||
[self kb_preloadAudioWithAudioId:response.audioId];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
/// 从 AppGroup 获取选中的 persona companionId
|
||||
- (NSInteger)kb_selectedCompanionId {
|
||||
return [[KBVM shared] selectedCompanionIdFromAppGroup];
|
||||
}
|
||||
|
||||
#pragma mark - Audio Preload
|
||||
|
||||
/// 预加载音频(轮询获取 audioURL)
|
||||
- (void)kb_preloadAudioWithAudioId:(NSString *)audioId {
|
||||
if (audioId.length == 0) return;
|
||||
|
||||
NSLog(@"[Keyboard] 开始预加载音频,audioId: %@", audioId);
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[KBVM shared] pollAudioURLWithAudioId:audioId
|
||||
maxRetries:10
|
||||
interval:1.0
|
||||
completion:^(KBAudioResponse *response) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) return;
|
||||
|
||||
if (!response.success || response.audioURL.length == 0) {
|
||||
NSLog(@"[Keyboard] ❌ 预加载音频 URL 获取失败: %@", response.errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[Keyboard] ✅ 预加载音频 URL 获取成功");
|
||||
|
||||
// 下载音频
|
||||
[[KBVM shared] downloadAudioFromURL:response.audioURL
|
||||
completion:^(KBAudioResponse *audioResponse) {
|
||||
if (!audioResponse.success) {
|
||||
NSLog(@"[Keyboard] ❌ 预加载音频下载失败: %@", audioResponse.errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新最后一条 AI 消息的音频数据
|
||||
[self.chatPanelView kb_updateLastAssistantMessageWithAudioData:audioResponse.audioData
|
||||
duration:audioResponse.duration];
|
||||
NSLog(@"[Keyboard] ✅ 预加载音频完成,音频时长: %.2f秒", audioResponse.duration);
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)kb_downloadChatAudioFromURL:(NSString *)audioURL
|
||||
displayText:(NSString *)displayText {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[[KBVM shared] downloadAudioFromURL:audioURL completion:^(KBAudioResponse *response) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) return;
|
||||
|
||||
if (!response.success) {
|
||||
[KBHUD showInfo:response.errorMessage ?: KBLocalized(@"下载失败")];
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.audioData || response.audioData.length == 0) {
|
||||
[KBHUD showInfo:KBLocalized(@"未获取到音频数据")];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *ext = @"m4a";
|
||||
NSURL *url = [NSURL URLWithString:audioURL];
|
||||
if (url.pathExtension.length > 0) {
|
||||
ext = url.pathExtension;
|
||||
}
|
||||
[self kb_handleChatAudioData:response.audioData
|
||||
fileExtension:ext
|
||||
displayText:displayText];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)kb_handleChatAudioData:(NSData *)data
|
||||
fileExtension:(NSString *)extension
|
||||
displayText:(NSString *)displayText {
|
||||
if (data.length == 0) {
|
||||
[KBHUD showInfo:KBLocalized(@"音频数据为空")];
|
||||
return;
|
||||
}
|
||||
NSString *ext = extension.length > 0 ? extension : @"m4a";
|
||||
NSString *fileName = [NSString
|
||||
stringWithFormat:@"kb_chat_%@.%@",
|
||||
@((long long)([NSDate date].timeIntervalSince1970 *
|
||||
1000)),
|
||||
ext];
|
||||
NSString *filePath =
|
||||
[NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
|
||||
if (![data writeToFile:filePath atomically:YES]) {
|
||||
[KBHUD showInfo:KBLocalized(@"音频保存失败")];
|
||||
return;
|
||||
}
|
||||
NSString *text = displayText.length > 0 ? displayText : KBLocalized(@"语音消息");
|
||||
KBChatMessage *incoming =
|
||||
[KBChatMessage messageWithText:text
|
||||
outgoing:NO
|
||||
audioFilePath:filePath];
|
||||
incoming.displayName = KBLocalized(@"AI助手");
|
||||
[self kb_appendChatMessage:incoming];
|
||||
}
|
||||
|
||||
- (void)kb_appendChatMessage:(KBChatMessage *)message {
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
[self.chatMessages addObject:message];
|
||||
if (self.chatMessages.count > kKBChatMessageLimit) {
|
||||
NSUInteger overflow = self.chatMessages.count - kKBChatMessageLimit;
|
||||
NSArray<KBChatMessage *> *removed =
|
||||
[self.chatMessages subarrayWithRange:NSMakeRange(0, overflow)];
|
||||
[self.chatMessages removeObjectsInRange:NSMakeRange(0, overflow)];
|
||||
for (KBChatMessage *msg in removed) {
|
||||
if (msg.audioFilePath.length > 0) {
|
||||
NSString *tmpRoot = NSTemporaryDirectory();
|
||||
if (tmpRoot.length > 0 &&
|
||||
[msg.audioFilePath hasPrefix:tmpRoot]) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:msg.audioFilePath
|
||||
error:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[self.chatPanelView kb_reloadWithMessages:self.chatMessages];
|
||||
}
|
||||
|
||||
- (NSString *)kb_mockChatAudioPath {
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"ai_test"
|
||||
ofType:@"m4a"];
|
||||
return path ?: @"";
|
||||
}
|
||||
|
||||
- (NSString *)kb_chatTextFromJSON:(NSDictionary *)json {
|
||||
NSDictionary *data = [self kb_chatDataDictionaryFromJSON:json];
|
||||
NSString *text =
|
||||
[self kb_stringValueInDict:data
|
||||
keys:@[ @"text", @"message", @"content" ]];
|
||||
if (text.length == 0) {
|
||||
text = [self kb_stringValueInDict:json
|
||||
keys:@[ @"text", @"message", @"content" ]];
|
||||
}
|
||||
return text ?: @"";
|
||||
}
|
||||
|
||||
- (NSString *)kb_chatAudioURLFromJSON:(NSDictionary *)json {
|
||||
NSDictionary *data = [self kb_chatDataDictionaryFromJSON:json];
|
||||
NSArray<NSString *> *keys =
|
||||
@[ @"audioUrl", @"audioURL", @"audio_url", @"url", @"fileUrl",
|
||||
@"file_url", @"audioFileUrl", @"audio_file_url" ];
|
||||
NSString *url = [self kb_stringValueInDict:data keys:keys];
|
||||
if (url.length == 0) {
|
||||
url = [self kb_stringValueInDict:json keys:keys];
|
||||
}
|
||||
return url ?: @"";
|
||||
}
|
||||
|
||||
- (NSString *)kb_chatAudioBase64FromJSON:(NSDictionary *)json {
|
||||
NSDictionary *data = [self kb_chatDataDictionaryFromJSON:json];
|
||||
NSArray<NSString *> *keys =
|
||||
@[ @"audioBase64", @"audio_base64", @"audioData", @"audio_data",
|
||||
@"base64" ];
|
||||
NSString *b64 = [self kb_stringValueInDict:data keys:keys];
|
||||
if (b64.length == 0) {
|
||||
b64 = [self kb_stringValueInDict:json keys:keys];
|
||||
}
|
||||
return b64 ?: @"";
|
||||
}
|
||||
|
||||
- (NSDictionary *)kb_chatDataDictionaryFromJSON:(NSDictionary *)json {
|
||||
if (![json isKindOfClass:[NSDictionary class]]) {
|
||||
return @{};
|
||||
}
|
||||
id dataObj = json[@"data"] ?: json[@"result"] ?: json[@"response"];
|
||||
if ([dataObj isKindOfClass:[NSDictionary class]]) {
|
||||
return (NSDictionary *)dataObj;
|
||||
}
|
||||
return @{};
|
||||
}
|
||||
|
||||
- (NSString *)kb_stringValueInDict:(NSDictionary *)dict
|
||||
keys:(NSArray<NSString *> *)keys {
|
||||
if (![dict isKindOfClass:[NSDictionary class]]) {
|
||||
return @"";
|
||||
}
|
||||
for (NSString *key in keys) {
|
||||
id value = dict[key];
|
||||
if ([value isKindOfClass:[NSString class]] &&
|
||||
((NSString *)value).length > 0) {
|
||||
return (NSString *)value;
|
||||
}
|
||||
}
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (void)kb_playChatAudioAtPath:(NSString *)path {
|
||||
if (path.length == 0) {
|
||||
return;
|
||||
}
|
||||
NSURL *url = [NSURL fileURLWithPath:path];
|
||||
if (![NSFileManager.defaultManager fileExistsAtPath:path]) {
|
||||
[KBHUD showInfo:KBLocalized(@"音频文件不存在")];
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.chatAudioPlayer && self.chatAudioPlayer.isPlaying) {
|
||||
NSURL *currentURL = self.chatAudioPlayer.url;
|
||||
if ([currentURL isEqual:url]) {
|
||||
[self.chatAudioPlayer stop];
|
||||
self.chatAudioPlayer = nil;
|
||||
return;
|
||||
}
|
||||
[self.chatAudioPlayer stop];
|
||||
self.chatAudioPlayer = nil;
|
||||
}
|
||||
|
||||
NSError *sessionError = nil;
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
if ([session respondsToSelector:@selector(setCategory:options:error:)]) {
|
||||
[session setCategory:AVAudioSessionCategoryPlayback
|
||||
withOptions:AVAudioSessionCategoryOptionDuckOthers
|
||||
error:&sessionError];
|
||||
} else {
|
||||
[session setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
|
||||
}
|
||||
[session setActive:YES error:nil];
|
||||
|
||||
NSError *playerError = nil;
|
||||
AVAudioPlayer *player =
|
||||
[[AVAudioPlayer alloc] initWithContentsOfURL:url error:&playerError];
|
||||
if (playerError || !player) {
|
||||
[KBHUD showInfo:KBLocalized(@"音频播放失败")];
|
||||
return;
|
||||
}
|
||||
self.chatAudioPlayer = player;
|
||||
[player prepareToPlay];
|
||||
[player play];
|
||||
}
|
||||
|
||||
/// 播放音频数据
|
||||
- (void)kb_playChatAudioData:(NSData *)audioData {
|
||||
if (!audioData || audioData.length == 0) {
|
||||
NSLog(@"[Keyboard] 音频数据为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果正在播放,先停止
|
||||
if (self.chatAudioPlayer && self.chatAudioPlayer.isPlaying) {
|
||||
[self.chatAudioPlayer stop];
|
||||
self.chatAudioPlayer = nil;
|
||||
}
|
||||
|
||||
// 配置音频会话
|
||||
NSError *sessionError = nil;
|
||||
AVAudioSession *session = [AVAudioSession sharedInstance];
|
||||
if ([session respondsToSelector:@selector(setCategory:options:error:)]) {
|
||||
[session setCategory:AVAudioSessionCategoryPlayback
|
||||
withOptions:AVAudioSessionCategoryOptionDuckOthers
|
||||
error:&sessionError];
|
||||
} else {
|
||||
[session setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
|
||||
}
|
||||
[session setActive:YES error:nil];
|
||||
|
||||
// 创建播放器
|
||||
NSError *playerError = nil;
|
||||
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:audioData error:&playerError];
|
||||
if (playerError || !player) {
|
||||
NSLog(@"[Keyboard] 音频播放器初始化失败: %@", playerError.localizedDescription);
|
||||
[KBHUD showInfo:KBLocalized(@"音频播放失败")];
|
||||
return;
|
||||
}
|
||||
|
||||
self.chatAudioPlayer = player;
|
||||
player.volume = 1.0;
|
||||
[player prepareToPlay];
|
||||
[player play];
|
||||
|
||||
NSLog(@"[Keyboard] 开始播放音频,时长: %.2f秒", player.duration);
|
||||
}
|
||||
|
||||
#pragma mark - KBKeyboardSubscriptionViewDelegate
|
||||
|
||||
- (void)subscriptionViewDidTapClose:(KBKeyboardSubscriptionView *)view {
|
||||
@@ -750,6 +1375,22 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
return _settingView;
|
||||
}
|
||||
|
||||
- (KBChatPanelView *)chatPanelView {
|
||||
if (!_chatPanelView) {
|
||||
NSLog(@"[Keyboard] ⚠️ chatPanelView 被创建!");
|
||||
_chatPanelView = [[KBChatPanelView alloc] init];
|
||||
_chatPanelView.delegate = self;
|
||||
}
|
||||
return _chatPanelView;
|
||||
}
|
||||
|
||||
- (NSMutableArray<KBChatMessage *> *)chatMessages {
|
||||
if (!_chatMessages) {
|
||||
_chatMessages = [NSMutableArray array];
|
||||
}
|
||||
return _chatMessages;
|
||||
}
|
||||
|
||||
- (KBKeyboardSubscriptionView *)subscriptionView {
|
||||
if (!_subscriptionView) {
|
||||
_subscriptionView = [[KBKeyboardSubscriptionView alloc] init];
|
||||
@@ -760,6 +1401,92 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
return _subscriptionView;
|
||||
}
|
||||
|
||||
- (UIImageView *)personaAvatarImageView {
|
||||
if (!_personaAvatarImageView) {
|
||||
_personaAvatarImageView = [[UIImageView alloc] init];
|
||||
_personaAvatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_personaAvatarImageView.clipsToBounds = YES;
|
||||
_personaAvatarImageView.hidden = YES;
|
||||
}
|
||||
return _personaAvatarImageView;
|
||||
}
|
||||
- (UIImageView *)personaGrayImageView{
|
||||
if (!_personaGrayImageView) {
|
||||
_personaGrayImageView = [[UIImageView alloc] init];
|
||||
_personaAvatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
|
||||
}
|
||||
return _personaGrayImageView;
|
||||
}
|
||||
|
||||
#pragma mark - Persona Avatar
|
||||
|
||||
/// 从 AppGroup 读取选中的 persona 信息
|
||||
- (NSDictionary *)kb_selectedPersonaFromAppGroup {
|
||||
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||
NSDictionary *personaDict = [ud objectForKey:@"AppGroup_SelectedPersona"];
|
||||
if ([personaDict isKindOfClass:[NSDictionary class]]) {
|
||||
return personaDict;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/// 在 bgImageView 上显示 persona 头像
|
||||
- (void)kb_showPersonaAvatarOnBgImageView {
|
||||
// 检查是否有完全访问权限
|
||||
if (![[KBFullAccessManager shared] hasFullAccess]) {
|
||||
NSLog(@"[Keyboard] 未开启完全访问,无法显示 persona 头像");
|
||||
return;
|
||||
}
|
||||
|
||||
// 从 AppGroup 共享目录读取预处理好的小图片
|
||||
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:AppGroup];
|
||||
if (!containerURL) {
|
||||
NSLog(@"[Keyboard] 无法获取 AppGroup 容器目录");
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *imagePath = [[containerURL path] stringByAppendingPathComponent:@"persona_cover.jpg"];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
|
||||
NSLog(@"[Keyboard] persona 封面图文件不存在: %@", imagePath);
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[Keyboard] 准备从本地加载 persona 封面图: %@", imagePath);
|
||||
|
||||
// 添加视图到 contentView,与 bgImageView 尺寸一致
|
||||
if (!self.personaAvatarImageView.superview) {
|
||||
[self.contentView insertSubview:self.personaAvatarImageView aboveSubview:self.bgImageView];
|
||||
[self.personaAvatarImageView addSubview:self.personaGrayImageView];
|
||||
[self.personaAvatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.bgImageView);
|
||||
}];
|
||||
[self.personaGrayImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.bottom.equalTo(self.personaAvatarImageView);
|
||||
make.height.mas_equalTo(self.keyBoardMainView);
|
||||
}];
|
||||
}
|
||||
|
||||
// 先清理旧图片
|
||||
self.personaAvatarImageView.image = nil;
|
||||
|
||||
// 从本地文件加载图片(已经是缩小后的小图片,内存占用很小)
|
||||
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
|
||||
if (image) {
|
||||
self.personaAvatarImageView.image = image;
|
||||
self.personaAvatarImageView.hidden = NO;
|
||||
NSLog(@"[Keyboard] persona 封面图加载成功");
|
||||
} else {
|
||||
NSLog(@"[Keyboard] persona 封面图加载失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// 隐藏 persona 头像
|
||||
- (void)kb_hidePersonaAvatar {
|
||||
self.personaAvatarImageView.hidden = YES;
|
||||
self.personaAvatarImageView.image = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)kb_openRechargeForProduct:(KBKeyboardSubscriptionProduct *)product {
|
||||
@@ -940,6 +1667,9 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
NSLog(@"⌨️[Keyboard] apply theme id=%@ hasBg=%d", t.skinId, (img != nil));
|
||||
[self kb_logSkinDiagnosticsWithTheme:t backgroundImage:img];
|
||||
self.bgImageView.image = img;
|
||||
self.personaGrayImageView.image = img;
|
||||
|
||||
// [self.chatPanelView kb_setBackgroundImage:img];
|
||||
BOOL hasImg = (img != nil);
|
||||
// 触发键区按主题重绘
|
||||
if ([self.keyBoardMainView respondsToSelector:@selector(kb_applyTheme)]) {
|
||||
@@ -1150,12 +1880,36 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
if (width <= 0) {
|
||||
width = KB_DESIGN_WIDTH;
|
||||
}
|
||||
return kKBKeyboardBaseHeight * (width / KB_DESIGN_WIDTH);
|
||||
CGFloat scale = width / KB_DESIGN_WIDTH;
|
||||
CGFloat baseHeight = kKBKeyboardBaseHeight * scale;
|
||||
CGFloat chatHeight = kKBChatPanelHeight * scale;
|
||||
if (self.chatPanelVisible) {
|
||||
return baseHeight + chatHeight;
|
||||
}
|
||||
return baseHeight;
|
||||
}
|
||||
|
||||
- (CGFloat)kb_keyboardBaseHeightForWidth:(CGFloat)width {
|
||||
if (width <= 0) {
|
||||
width = KB_DESIGN_WIDTH;
|
||||
}
|
||||
CGFloat scale = width / KB_DESIGN_WIDTH;
|
||||
return kKBKeyboardBaseHeight * scale;
|
||||
}
|
||||
|
||||
- (CGFloat)kb_chatPanelHeightForWidth:(CGFloat)width {
|
||||
if (width <= 0) {
|
||||
width = KB_DESIGN_WIDTH;
|
||||
}
|
||||
CGFloat scale = width / KB_DESIGN_WIDTH;
|
||||
return kKBChatPanelHeight * scale;
|
||||
}
|
||||
|
||||
- (void)kb_updateKeyboardLayoutIfNeeded {
|
||||
CGFloat portraitWidth = [self kb_portraitWidth];
|
||||
CGFloat keyboardHeight = [self kb_keyboardHeightForWidth:portraitWidth];
|
||||
CGFloat keyboardBaseHeight = [self kb_keyboardBaseHeightForWidth:portraitWidth];
|
||||
CGFloat chatPanelHeight = [self kb_chatPanelHeightForWidth:portraitWidth];
|
||||
CGFloat containerWidth = CGRectGetWidth(self.view.superview.bounds);
|
||||
if (containerWidth <= 0) {
|
||||
containerWidth = CGRectGetWidth(self.view.window.bounds);
|
||||
@@ -1186,6 +1940,12 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
if (self.contentHeightConstraint) {
|
||||
[self.contentHeightConstraint setOffset:keyboardHeight];
|
||||
}
|
||||
if (self.keyBoardMainHeightConstraint) {
|
||||
[self.keyBoardMainHeightConstraint setOffset:keyboardBaseHeight];
|
||||
}
|
||||
if (self.chatPanelHeightConstraint) {
|
||||
[self.chatPanelHeightConstraint setOffset:chatPanelHeight];
|
||||
}
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
|
||||
|
||||
49
CustomKeyboard/Model/KBChatMessage.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// KBChatMessage.h
|
||||
// CustomKeyboard
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBChatMessage : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSString *text;
|
||||
@property (nonatomic, assign) BOOL outgoing;
|
||||
@property (nonatomic, copy, nullable) NSString *audioFilePath;
|
||||
@property (nonatomic, copy, nullable) NSString *avatarURL;
|
||||
@property (nonatomic, copy, nullable) NSString *displayName;
|
||||
@property (nonatomic, strong, nullable) UIImage *avatarImage;
|
||||
|
||||
/// 是否处于加载状态
|
||||
@property (nonatomic, assign) BOOL isLoading;
|
||||
/// 是否完成(用于打字机效果)
|
||||
@property (nonatomic, assign) BOOL isComplete;
|
||||
/// 是否需要打字机效果
|
||||
@property (nonatomic, assign) BOOL needsTypewriterEffect;
|
||||
/// 音频 ID(用于异步加载音频)
|
||||
@property (nonatomic, copy, nullable) NSString *audioId;
|
||||
/// 音频数据(缓存)
|
||||
@property (nonatomic, strong, nullable) NSData *audioData;
|
||||
/// 音频时长(秒)
|
||||
@property (nonatomic, assign) NSTimeInterval audioDuration;
|
||||
|
||||
+ (instancetype)messageWithText:(NSString *)text
|
||||
outgoing:(BOOL)outgoing
|
||||
audioFilePath:(nullable NSString *)audioFilePath;
|
||||
|
||||
/// 创建用户消息
|
||||
+ (instancetype)userMessageWithText:(NSString *)text;
|
||||
|
||||
/// 创建 AI 消息(带 audioId)
|
||||
+ (instancetype)assistantMessageWithText:(NSString *)text
|
||||
audioId:(nullable NSString *)audioId;
|
||||
|
||||
/// 创建加载中的 AI 消息
|
||||
+ (instancetype)loadingAssistantMessage;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
55
CustomKeyboard/Model/KBChatMessage.m
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// KBChatMessage.m
|
||||
// CustomKeyboard
|
||||
//
|
||||
|
||||
#import "KBChatMessage.h"
|
||||
|
||||
@implementation KBChatMessage
|
||||
|
||||
+ (instancetype)messageWithText:(NSString *)text
|
||||
outgoing:(BOOL)outgoing
|
||||
audioFilePath:(NSString *)audioFilePath {
|
||||
KBChatMessage *msg = [[KBChatMessage alloc] init];
|
||||
msg.text = text ?: @"";
|
||||
msg.outgoing = outgoing;
|
||||
msg.audioFilePath = audioFilePath;
|
||||
msg.isComplete = YES;
|
||||
msg.isLoading = NO;
|
||||
msg.needsTypewriterEffect = NO;
|
||||
return msg;
|
||||
}
|
||||
|
||||
+ (instancetype)userMessageWithText:(NSString *)text {
|
||||
KBChatMessage *msg = [[KBChatMessage alloc] init];
|
||||
msg.text = text ?: @"";
|
||||
msg.outgoing = YES;
|
||||
msg.isComplete = YES;
|
||||
msg.isLoading = NO;
|
||||
msg.needsTypewriterEffect = NO;
|
||||
return msg;
|
||||
}
|
||||
|
||||
+ (instancetype)assistantMessageWithText:(NSString *)text
|
||||
audioId:(NSString *)audioId {
|
||||
KBChatMessage *msg = [[KBChatMessage alloc] init];
|
||||
msg.text = text ?: @"";
|
||||
msg.outgoing = NO;
|
||||
msg.audioId = audioId;
|
||||
msg.isComplete = NO;
|
||||
msg.isLoading = NO;
|
||||
msg.needsTypewriterEffect = YES;
|
||||
return msg;
|
||||
}
|
||||
|
||||
+ (instancetype)loadingAssistantMessage {
|
||||
KBChatMessage *msg = [[KBChatMessage alloc] init];
|
||||
msg.text = @"";
|
||||
msg.outgoing = NO;
|
||||
msg.isComplete = NO;
|
||||
msg.isLoading = YES;
|
||||
msg.needsTypewriterEffect = NO;
|
||||
return msg;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -64,6 +64,15 @@ typedef void(^KBNetworkDataCompletion)(NSData *_Nullable data,
|
||||
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||
completion:(KBNetworkCompletion)completion;
|
||||
|
||||
/// POST multipart 上传文件(常用于语音/图片等文件)
|
||||
- (nullable NSURLSessionDataTask *)uploadFile:(NSString *)path
|
||||
fileURL:(NSURL *)fileURL
|
||||
name:(NSString *)name
|
||||
mimeType:(NSString *)mimeType
|
||||
parameters:(nullable NSDictionary *)parameters
|
||||
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||
completion:(KBNetworkCompletion)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -124,6 +124,84 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
return [self startAFJSONTaskWithRequest:req completion:completion];
|
||||
}
|
||||
|
||||
- (NSURLSessionDataTask *)uploadFile:(NSString *)path
|
||||
fileURL:(NSURL *)fileURL
|
||||
name:(NSString *)name
|
||||
mimeType:(NSString *)mimeType
|
||||
parameters:(NSDictionary *)parameters
|
||||
headers:(NSDictionary<NSString *, NSString *> *)headers
|
||||
completion:(KBNetworkCompletion)completion {
|
||||
[self getSignWithParare:parameters];
|
||||
if (![self ensureEnabled:completion]) return nil;
|
||||
NSString *urlString = [self buildURLStringWithPath:path];
|
||||
if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; }
|
||||
if (!fileURL) {
|
||||
if (completion) completion(nil, nil, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey: KBLocalized(@"Invalid file")}]);
|
||||
return nil;
|
||||
}
|
||||
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
|
||||
serializer.timeoutInterval = self.timeout;
|
||||
NSError *error = nil;
|
||||
NSMutableURLRequest *req = [serializer multipartFormRequestWithMethod:@"POST"
|
||||
URLString:urlString
|
||||
parameters:parameters
|
||||
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
|
||||
NSString *safeName = (name.length > 0) ? name : @"file";
|
||||
NSString *fileName = fileURL.lastPathComponent ?: @"upload.bin";
|
||||
NSString *type = (mimeType.length > 0) ? mimeType : @"application/octet-stream";
|
||||
[formData appendPartWithFileURL:fileURL name:safeName fileName:fileName mimeType:type error:nil];
|
||||
} error:&error];
|
||||
if (error || !req) {
|
||||
if (completion) completion(nil, nil, error ?: [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidURL userInfo:@{NSLocalizedDescriptionKey: KBLocalized(@"Invalid URL")}]);
|
||||
return nil;
|
||||
}
|
||||
[self applyHeaders:headers toMutableRequest:req contentType:nil];
|
||||
self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||
NSURLSessionUploadTask *task = [self.manager uploadTaskWithStreamedRequest:req progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
|
||||
if (error) {
|
||||
if (completion) completion(nil, response, error);
|
||||
return;
|
||||
}
|
||||
NSData *data = (NSData *)responseObject;
|
||||
if (![data isKindOfClass:[NSData class]]) {
|
||||
if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey:KBLocalized(@"No data")}]);
|
||||
return;
|
||||
}
|
||||
NSString *ct = nil;
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
ct = ((NSHTTPURLResponse *)response).allHeaderFields[@"Content-Type"];
|
||||
}
|
||||
BOOL looksJSON = (ct && [[ct lowercaseString] containsString:@"json"]);
|
||||
if (!looksJSON) {
|
||||
const unsigned char *bytes = data.bytes;
|
||||
NSUInteger len = data.length;
|
||||
for (NSUInteger i = 0; !looksJSON && i < len; i++) {
|
||||
unsigned char c = bytes[i];
|
||||
if (c == ' ' || c == '\n' || c == '\r' || c == '\t') continue;
|
||||
looksJSON = (c == '{' || c == '[');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (looksJSON) {
|
||||
NSError *jsonErr = nil;
|
||||
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonErr];
|
||||
if (jsonErr) {
|
||||
if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorDecodeFailed userInfo:@{NSLocalizedDescriptionKey:KBLocalized(@"Failed to parse JSON")}]);
|
||||
return;
|
||||
}
|
||||
if (![json isKindOfClass:[NSDictionary class]]) {
|
||||
if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey:KBLocalized(@"Invalid response")}]);
|
||||
return;
|
||||
}
|
||||
if (completion) completion((NSDictionary *)json, response, nil);
|
||||
} else {
|
||||
if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey:KBLocalized(@"Invalid response")}]);
|
||||
}
|
||||
}];
|
||||
[task resume];
|
||||
return task;
|
||||
}
|
||||
|
||||
- (NSURLSessionDataTask *)GETData:(NSString *)path
|
||||
parameters:(NSDictionary *)parameters
|
||||
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||
|
||||
BIN
CustomKeyboard/Resource/ai_test.m4a
Normal file
95
CustomKeyboard/VM/KBVM.h
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// KBVM.h
|
||||
// CustomKeyboard
|
||||
//
|
||||
// 键盘扩展的 ViewModel,封装网络请求逻辑
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// 聊天响应模型
|
||||
@interface KBChatResponse : NSObject
|
||||
@property (nonatomic, copy, nullable) NSString *text;
|
||||
@property (nonatomic, copy, nullable) NSString *audioId;
|
||||
@property (nonatomic, copy, nullable) NSString *errorMessage;
|
||||
@property (nonatomic, assign) BOOL success;
|
||||
@end
|
||||
|
||||
/// 音频响应模型
|
||||
@interface KBAudioResponse : NSObject
|
||||
@property (nonatomic, copy, nullable) NSString *audioURL;
|
||||
@property (nonatomic, strong, nullable) NSData *audioData;
|
||||
@property (nonatomic, assign) NSTimeInterval duration;
|
||||
@property (nonatomic, copy, nullable) NSString *errorMessage;
|
||||
@property (nonatomic, assign) BOOL success;
|
||||
@end
|
||||
|
||||
/// 聊天请求回调
|
||||
typedef void(^KBChatCompletion)(KBChatResponse *response);
|
||||
/// 音频 URL 回调
|
||||
typedef void(^KBAudioURLCompletion)(KBAudioResponse *response);
|
||||
/// 音频数据回调
|
||||
typedef void(^KBAudioDataCompletion)(KBAudioResponse *response);
|
||||
/// 头像回调
|
||||
typedef void(^KBAvatarCompletion)(UIImage * _Nullable image, NSError * _Nullable error);
|
||||
|
||||
@interface KBVM : NSObject
|
||||
|
||||
+ (instancetype)shared;
|
||||
|
||||
#pragma mark - Chat API
|
||||
|
||||
/// 发送聊天消息
|
||||
/// @param content 消息内容
|
||||
/// @param companionId 人设 ID
|
||||
/// @param completion 回调
|
||||
- (void)sendChatMessageWithContent:(NSString *)content
|
||||
companionId:(NSInteger)companionId
|
||||
completion:(KBChatCompletion)completion;
|
||||
|
||||
#pragma mark - Audio API
|
||||
|
||||
/// 获取音频 URL(单次请求)
|
||||
/// @param audioId 音频 ID
|
||||
/// @param completion 回调
|
||||
- (void)fetchAudioURLWithAudioId:(NSString *)audioId
|
||||
completion:(KBAudioURLCompletion)completion;
|
||||
|
||||
/// 轮询获取音频 URL(自动重试)
|
||||
/// @param audioId 音频 ID
|
||||
/// @param maxRetries 最大重试次数
|
||||
/// @param interval 重试间隔(秒)
|
||||
/// @param completion 回调
|
||||
- (void)pollAudioURLWithAudioId:(NSString *)audioId
|
||||
maxRetries:(NSInteger)maxRetries
|
||||
interval:(NSTimeInterval)interval
|
||||
completion:(KBAudioURLCompletion)completion;
|
||||
|
||||
/// 下载音频数据
|
||||
/// @param urlString 音频 URL
|
||||
/// @param completion 回调
|
||||
- (void)downloadAudioFromURL:(NSString *)urlString
|
||||
completion:(KBAudioDataCompletion)completion;
|
||||
|
||||
#pragma mark - Avatar API
|
||||
|
||||
/// 下载头像图片
|
||||
/// @param urlString 头像 URL
|
||||
/// @param completion 回调
|
||||
- (void)downloadAvatarFromURL:(NSString *)urlString
|
||||
completion:(KBAvatarCompletion)completion;
|
||||
|
||||
#pragma mark - Helper
|
||||
|
||||
/// 从 AppGroup 获取选中的 persona companionId
|
||||
- (NSInteger)selectedCompanionIdFromAppGroup;
|
||||
|
||||
/// 从 AppGroup 获取选中的 persona 信息
|
||||
- (nullable NSDictionary *)selectedPersonaFromAppGroup;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
334
CustomKeyboard/VM/KBVM.m
Normal file
@@ -0,0 +1,334 @@
|
||||
//
|
||||
// KBVM.m
|
||||
// CustomKeyboard
|
||||
//
|
||||
|
||||
#import "KBVM.h"
|
||||
#import "KBNetworkManager.h"
|
||||
#import "KBConfig.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
@implementation KBChatResponse
|
||||
@end
|
||||
|
||||
@implementation KBAudioResponse
|
||||
@end
|
||||
|
||||
@interface KBVM ()
|
||||
@property (nonatomic, strong) NSCache<NSString *, UIImage *> *avatarCache;
|
||||
@end
|
||||
|
||||
@implementation KBVM
|
||||
|
||||
+ (instancetype)shared {
|
||||
static KBVM *instance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
instance = [[KBVM alloc] init];
|
||||
});
|
||||
return instance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_avatarCache = [[NSCache alloc] init];
|
||||
_avatarCache.countLimit = 20;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Chat API
|
||||
|
||||
- (void)sendChatMessageWithContent:(NSString *)content
|
||||
companionId:(NSInteger)companionId
|
||||
completion:(KBChatCompletion)completion {
|
||||
if (content.length == 0) {
|
||||
if (completion) {
|
||||
KBChatResponse *response = [[KBChatResponse alloc] init];
|
||||
response.success = NO;
|
||||
response.errorMessage = @"内容为空";
|
||||
completion(response);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *encodedContent = [content stringByAddingPercentEncodingWithAllowedCharacters:
|
||||
[NSCharacterSet URLQueryAllowedCharacterSet]];
|
||||
NSString *path = [NSString stringWithFormat:@"%@?content=%@&companionId=%ld",
|
||||
API_AI_CHAT_MESSAGE, encodedContent ?: @"", (long)companionId];
|
||||
NSDictionary *params = @{
|
||||
@"content": content ?: @"",
|
||||
@"companionId": @(companionId)
|
||||
};
|
||||
|
||||
[[KBNetworkManager shared] POST:path
|
||||
jsonBody:params
|
||||
headers:nil
|
||||
completion:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
KBChatResponse *chatResponse = [[KBChatResponse alloc] init];
|
||||
|
||||
if (error) {
|
||||
chatResponse.success = NO;
|
||||
chatResponse.errorMessage = error.localizedDescription ?: @"请求失败";
|
||||
if (completion) completion(chatResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析文本
|
||||
chatResponse.text = [self p_parseTextFromJSON:json];
|
||||
// 解析 audioId
|
||||
chatResponse.audioId = [self p_parseAudioIdFromJSON:json];
|
||||
|
||||
chatResponse.success = (chatResponse.text.length > 0);
|
||||
if (!chatResponse.success) {
|
||||
chatResponse.errorMessage = @"未获取到回复内容";
|
||||
}
|
||||
|
||||
if (completion) completion(chatResponse);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Audio API
|
||||
|
||||
- (void)fetchAudioURLWithAudioId:(NSString *)audioId
|
||||
completion:(KBAudioURLCompletion)completion {
|
||||
if (audioId.length == 0) {
|
||||
if (completion) {
|
||||
KBAudioResponse *response = [[KBAudioResponse alloc] init];
|
||||
response.success = NO;
|
||||
response.errorMessage = @"audioId 为空";
|
||||
completion(response);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *path = [NSString stringWithFormat:@"/chat/audio/%@", audioId];
|
||||
|
||||
[[KBNetworkManager shared] GET:path
|
||||
parameters:nil
|
||||
headers:nil
|
||||
completion:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
KBAudioResponse *audioResponse = [[KBAudioResponse alloc] init];
|
||||
|
||||
if (error) {
|
||||
audioResponse.success = NO;
|
||||
audioResponse.errorMessage = error.localizedDescription;
|
||||
if (completion) completion(audioResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析 audioURL
|
||||
NSString *audioURL = [self p_parseAudioURLFromJSON:json];
|
||||
audioResponse.audioURL = audioURL;
|
||||
audioResponse.success = (audioURL.length > 0);
|
||||
|
||||
if (completion) completion(audioResponse);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)pollAudioURLWithAudioId:(NSString *)audioId
|
||||
maxRetries:(NSInteger)maxRetries
|
||||
interval:(NSTimeInterval)interval
|
||||
completion:(KBAudioURLCompletion)completion {
|
||||
[self p_pollAudioURLWithAudioId:audioId
|
||||
retryCount:0
|
||||
maxRetries:maxRetries
|
||||
interval:interval
|
||||
completion:completion];
|
||||
}
|
||||
|
||||
- (void)p_pollAudioURLWithAudioId:(NSString *)audioId
|
||||
retryCount:(NSInteger)retryCount
|
||||
maxRetries:(NSInteger)maxRetries
|
||||
interval:(NSTimeInterval)interval
|
||||
completion:(KBAudioURLCompletion)completion {
|
||||
|
||||
[self fetchAudioURLWithAudioId:audioId completion:^(KBAudioResponse *response) {
|
||||
if (response.success && response.audioURL.length > 0) {
|
||||
// 成功获取到 URL
|
||||
if (completion) completion(response);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果还没达到最大重试次数,继续轮询
|
||||
if (retryCount < maxRetries - 1) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)),
|
||||
dispatch_get_main_queue(), ^{
|
||||
[self p_pollAudioURLWithAudioId:audioId
|
||||
retryCount:retryCount + 1
|
||||
maxRetries:maxRetries
|
||||
interval:interval
|
||||
completion:completion];
|
||||
});
|
||||
} else {
|
||||
// 达到最大重试次数
|
||||
KBAudioResponse *failResponse = [[KBAudioResponse alloc] init];
|
||||
failResponse.success = NO;
|
||||
failResponse.errorMessage = [NSString stringWithFormat:@"轮询失败,已重试 %ld 次", (long)maxRetries];
|
||||
if (completion) completion(failResponse);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)downloadAudioFromURL:(NSString *)urlString
|
||||
completion:(KBAudioDataCompletion)completion {
|
||||
if (urlString.length == 0) {
|
||||
if (completion) {
|
||||
KBAudioResponse *response = [[KBAudioResponse alloc] init];
|
||||
response.success = NO;
|
||||
response.errorMessage = @"URL 为空";
|
||||
completion(response);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
[[KBNetworkManager shared] GETData:urlString
|
||||
parameters:nil
|
||||
headers:nil
|
||||
completion:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
KBAudioResponse *audioResponse = [[KBAudioResponse alloc] init];
|
||||
|
||||
if (error || !data || data.length == 0) {
|
||||
audioResponse.success = NO;
|
||||
audioResponse.errorMessage = error.localizedDescription ?: @"下载失败";
|
||||
if (completion) completion(audioResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
audioResponse.audioData = data;
|
||||
|
||||
// 计算音频时长
|
||||
NSError *playerError = nil;
|
||||
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:data error:&playerError];
|
||||
if (!playerError && player) {
|
||||
audioResponse.duration = player.duration;
|
||||
}
|
||||
|
||||
audioResponse.success = YES;
|
||||
if (completion) completion(audioResponse);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Avatar API
|
||||
|
||||
- (void)downloadAvatarFromURL:(NSString *)urlString
|
||||
completion:(KBAvatarCompletion)completion {
|
||||
if (urlString.length == 0) {
|
||||
if (completion) completion(nil, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查缓存
|
||||
UIImage *cached = [self.avatarCache objectForKey:urlString];
|
||||
if (cached) {
|
||||
if (completion) completion(cached, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
[[KBNetworkManager shared] GETData:urlString
|
||||
parameters:nil
|
||||
headers:nil
|
||||
completion:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error || data.length == 0) {
|
||||
if (completion) completion(nil, error);
|
||||
return;
|
||||
}
|
||||
|
||||
UIImage *image = [UIImage imageWithData:data];
|
||||
if (image) {
|
||||
[self.avatarCache setObject:image forKey:urlString];
|
||||
}
|
||||
if (completion) completion(image, nil);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Helper
|
||||
|
||||
- (NSInteger)selectedCompanionIdFromAppGroup {
|
||||
NSDictionary *persona = [self selectedPersonaFromAppGroup];
|
||||
if (persona) {
|
||||
id companionIdObj = persona[@"personaId"] ?: persona[@"companionId"] ?: persona[@"id"];
|
||||
if ([companionIdObj respondsToSelector:@selector(integerValue)]) {
|
||||
return [companionIdObj integerValue];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (nullable NSDictionary *)selectedPersonaFromAppGroup {
|
||||
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||
return [shared objectForKey:@"AppGroup_SelectedPersona"];
|
||||
}
|
||||
|
||||
#pragma mark - Private Parse Methods
|
||||
|
||||
/// 解析聊天文本
|
||||
- (NSString *)p_parseTextFromJSON:(NSDictionary *)json {
|
||||
if (![json isKindOfClass:[NSDictionary class]]) return @"";
|
||||
|
||||
id dataObj = json[@"data"];
|
||||
if ([dataObj isKindOfClass:[NSDictionary class]]) {
|
||||
NSDictionary *data = (NSDictionary *)dataObj;
|
||||
// 优先读取 aiResponse 字段
|
||||
NSArray *keys = @[@"aiResponse", @"content", @"text", @"message"];
|
||||
for (NSString *key in keys) {
|
||||
id value = data[key];
|
||||
if ([value isKindOfClass:[NSString class]] && ((NSString *)value).length > 0) {
|
||||
return (NSString *)value;
|
||||
}
|
||||
}
|
||||
} else if ([dataObj isKindOfClass:[NSString class]]) {
|
||||
return (NSString *)dataObj;
|
||||
}
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
/// 解析 audioId
|
||||
- (NSString *)p_parseAudioIdFromJSON:(NSDictionary *)json {
|
||||
if (![json isKindOfClass:[NSDictionary class]]) return nil;
|
||||
|
||||
id dataObj = json[@"data"];
|
||||
if ([dataObj isKindOfClass:[NSDictionary class]]) {
|
||||
NSDictionary *data = (NSDictionary *)dataObj;
|
||||
NSString *audioId = data[@"audioId"];
|
||||
if ([audioId isKindOfClass:[NSString class]] && audioId.length > 0) {
|
||||
return audioId;
|
||||
}
|
||||
}
|
||||
|
||||
// 兼容其他字段名
|
||||
NSArray *keys = @[@"audioId", @"audio_id"];
|
||||
for (NSString *key in keys) {
|
||||
id value = json[key];
|
||||
if ([value isKindOfClass:[NSString class]] && ((NSString *)value).length > 0) {
|
||||
return (NSString *)value;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/// 解析 audioURL
|
||||
- (NSString *)p_parseAudioURLFromJSON:(NSDictionary *)json {
|
||||
if (![json isKindOfClass:[NSDictionary class]]) return nil;
|
||||
|
||||
id dataObj = json[@"data"];
|
||||
if ([dataObj isKindOfClass:[NSDictionary class]]) {
|
||||
NSDictionary *data = (NSDictionary *)dataObj;
|
||||
id audioUrlObj = data[@"audioUrl"] ?: data[@"url"];
|
||||
if (audioUrlObj && ![audioUrlObj isKindOfClass:[NSNull class]] && [audioUrlObj isKindOfClass:[NSString class]]) {
|
||||
return (NSString *)audioUrlObj;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
40
CustomKeyboard/View/Chat/KBChatAssistantCell.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// KBChatAssistantCell.h
|
||||
// CustomKeyboard
|
||||
//
|
||||
// AI 消息 Cell(左侧显示,带语音按钮和打字机效果)
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@class KBChatMessage;
|
||||
@class KBChatAssistantCell;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol KBChatAssistantCellDelegate <NSObject>
|
||||
@optional
|
||||
/// 点击语音播放按钮
|
||||
- (void)assistantCell:(KBChatAssistantCell *)cell didTapVoiceButtonForMessage:(KBChatMessage *)message;
|
||||
@end
|
||||
|
||||
@interface KBChatAssistantCell : UITableViewCell
|
||||
|
||||
@property (nonatomic, weak) id<KBChatAssistantCellDelegate> delegate;
|
||||
|
||||
- (void)configureWithMessage:(KBChatMessage *)message;
|
||||
|
||||
/// 更新语音播放状态
|
||||
- (void)updateVoicePlayingState:(BOOL)isPlaying;
|
||||
|
||||
/// 显示语音加载动画
|
||||
- (void)showVoiceLoadingAnimation;
|
||||
|
||||
/// 隐藏语音加载动画
|
||||
- (void)hideVoiceLoadingAnimation;
|
||||
|
||||
/// 停止打字机效果
|
||||
- (void)stopTypewriterEffect;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
346
CustomKeyboard/View/Chat/KBChatAssistantCell.m
Normal file
@@ -0,0 +1,346 @@
|
||||
//
|
||||
// KBChatAssistantCell.m
|
||||
// CustomKeyboard
|
||||
//
|
||||
// AI 消息 Cell(左侧显示,带语音按钮和打字机效果)
|
||||
//
|
||||
|
||||
#import "KBChatAssistantCell.h"
|
||||
#import "KBChatMessage.h"
|
||||
#import "Masonry.h"
|
||||
|
||||
@interface KBChatAssistantCell ()
|
||||
|
||||
@property (nonatomic, strong) UIButton *voiceButton;
|
||||
@property (nonatomic, strong) UILabel *durationLabel;
|
||||
@property (nonatomic, strong) UIView *bubbleView;
|
||||
@property (nonatomic, strong) UILabel *messageLabel;
|
||||
@property (nonatomic, strong) UIActivityIndicatorView *voiceLoadingIndicator;
|
||||
@property (nonatomic, strong) UIActivityIndicatorView *messageLoadingIndicator;
|
||||
@property (nonatomic, strong) KBChatMessage *currentMessage;
|
||||
|
||||
/// 打字机效果
|
||||
@property (nonatomic, strong) NSTimer *typewriterTimer;
|
||||
@property (nonatomic, copy) NSString *fullText;
|
||||
@property (nonatomic, assign) NSInteger currentCharIndex;
|
||||
|
||||
@end
|
||||
|
||||
@implementation KBChatAssistantCell
|
||||
|
||||
- (instancetype)initWithStyle:(UITableViewCellStyle)style
|
||||
reuseIdentifier:(NSString *)reuseIdentifier {
|
||||
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
|
||||
if (self) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.contentView.backgroundColor = [UIColor clearColor];
|
||||
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
[self setupUI];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupUI {
|
||||
[self.contentView addSubview:self.voiceButton];
|
||||
[self.contentView addSubview:self.durationLabel];
|
||||
[self.contentView addSubview:self.voiceLoadingIndicator];
|
||||
[self.contentView addSubview:self.messageLoadingIndicator];
|
||||
[self.contentView addSubview:self.bubbleView];
|
||||
[self.bubbleView addSubview:self.messageLabel];
|
||||
|
||||
// 语音按钮
|
||||
[self.voiceButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.contentView).offset(12);
|
||||
make.top.equalTo(self.contentView).offset(6);
|
||||
make.width.height.mas_equalTo(20);
|
||||
}];
|
||||
|
||||
// 语音时长
|
||||
[self.durationLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.voiceButton.mas_right).offset(4);
|
||||
make.centerY.equalTo(self.voiceButton);
|
||||
}];
|
||||
|
||||
// 语音加载指示器
|
||||
[self.voiceLoadingIndicator mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.center.equalTo(self.voiceButton);
|
||||
}];
|
||||
|
||||
// 消息加载指示器
|
||||
[self.messageLoadingIndicator mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.contentView).offset(12);
|
||||
make.top.equalTo(self.voiceButton);
|
||||
}];
|
||||
|
||||
// 气泡
|
||||
[self.bubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.voiceButton.mas_bottom).offset(4);
|
||||
make.bottom.equalTo(self.contentView).offset(-4);
|
||||
make.left.equalTo(self.contentView).offset(12);
|
||||
make.width.lessThanOrEqualTo(self.contentView).multipliedBy(0.7);
|
||||
}];
|
||||
|
||||
// 消息文本
|
||||
[self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.bubbleView).offset(8);
|
||||
make.bottom.equalTo(self.bubbleView).offset(-8);
|
||||
make.left.equalTo(self.bubbleView).offset(12);
|
||||
make.right.equalTo(self.bubbleView).offset(-12);
|
||||
make.height.greaterThanOrEqualTo(@18);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)configureWithMessage:(KBChatMessage *)message {
|
||||
NSLog(@"[KBChatAssistantCell] ========== configureWithMessage ==========");
|
||||
NSLog(@"[KBChatAssistantCell] text: %@", message.text);
|
||||
NSLog(@"[KBChatAssistantCell] outgoing: %d, isLoading: %d, isComplete: %d, needsTypewriter: %d",
|
||||
message.outgoing, message.isLoading, message.isComplete, message.needsTypewriterEffect);
|
||||
|
||||
// 先停止之前的打字机效果
|
||||
[self stopTypewriterEffect];
|
||||
|
||||
self.currentMessage = message;
|
||||
|
||||
// 处理 loading 状态
|
||||
if (message.isLoading) {
|
||||
NSLog(@"[KBChatAssistantCell] 显示 loading 状态");
|
||||
self.messageLabel.attributedText = nil;
|
||||
self.messageLabel.text = @"";
|
||||
self.bubbleView.hidden = YES;
|
||||
self.voiceButton.hidden = YES;
|
||||
self.durationLabel.hidden = YES;
|
||||
[self.messageLoadingIndicator startAnimating];
|
||||
return;
|
||||
}
|
||||
|
||||
// 非 loading 状态
|
||||
[self.messageLoadingIndicator stopAnimating];
|
||||
self.bubbleView.hidden = NO;
|
||||
|
||||
// 语音按钮显示逻辑
|
||||
BOOL hasAudio = (message.audioId.length > 0) || (message.audioData.length > 0);
|
||||
self.voiceButton.hidden = !hasAudio;
|
||||
self.durationLabel.hidden = !hasAudio;
|
||||
NSLog(@"[KBChatAssistantCell] hasAudio: %d, audioId: %@", hasAudio, message.audioId);
|
||||
|
||||
// 语音时长
|
||||
if (message.audioDuration > 0) {
|
||||
NSInteger seconds = (NSInteger)ceil(message.audioDuration);
|
||||
self.durationLabel.text = [NSString stringWithFormat:@"%ld\"", (long)seconds];
|
||||
} else {
|
||||
self.durationLabel.text = @"";
|
||||
}
|
||||
|
||||
// 打字机效果
|
||||
if (message.needsTypewriterEffect && !message.isComplete && message.text.length > 0) {
|
||||
NSLog(@"[KBChatAssistantCell] ✅ 启动打字机效果");
|
||||
[self startTypewriterEffectWithText:message.text];
|
||||
} else {
|
||||
NSLog(@"[KBChatAssistantCell] 直接显示文本(不使用打字机)");
|
||||
self.messageLabel.attributedText = nil;
|
||||
self.messageLabel.text = message.text ?: @"";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Typewriter Effect
|
||||
|
||||
- (void)startTypewriterEffectWithText:(NSString *)text {
|
||||
if (text.length == 0) return;
|
||||
|
||||
self.fullText = text;
|
||||
self.currentCharIndex = 0;
|
||||
|
||||
// 先设置完整文本让布局计算正确高度
|
||||
self.messageLabel.text = text;
|
||||
[self.contentView setNeedsLayout];
|
||||
[self.contentView layoutIfNeeded];
|
||||
|
||||
// 应用打字机效果
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:[UIColor clearColor]
|
||||
range:NSMakeRange(0, text.length)];
|
||||
[attributedText addAttribute:NSFontAttributeName
|
||||
value:self.messageLabel.font
|
||||
range:NSMakeRange(0, text.length)];
|
||||
self.messageLabel.attributedText = attributedText;
|
||||
|
||||
self.typewriterTimer = [NSTimer scheduledTimerWithTimeInterval:0.03
|
||||
target:self
|
||||
selector:@selector(typewriterTick)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
[[NSRunLoop currentRunLoop] addTimer:self.typewriterTimer forMode:NSRunLoopCommonModes];
|
||||
[self typewriterTick];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)typewriterTick {
|
||||
NSString *text = self.fullText;
|
||||
if (!text || text.length == 0) {
|
||||
[self stopTypewriterEffect];
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.currentCharIndex < text.length) {
|
||||
self.currentCharIndex++;
|
||||
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
|
||||
UIColor *textColor = [UIColor whiteColor];
|
||||
|
||||
if (self.currentCharIndex > 0) {
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:textColor
|
||||
range:NSMakeRange(0, self.currentCharIndex)];
|
||||
}
|
||||
if (self.currentCharIndex < text.length) {
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:[UIColor clearColor]
|
||||
range:NSMakeRange(self.currentCharIndex, text.length - self.currentCharIndex)];
|
||||
}
|
||||
[attributedText addAttribute:NSFontAttributeName
|
||||
value:self.messageLabel.font
|
||||
range:NSMakeRange(0, text.length)];
|
||||
|
||||
self.messageLabel.attributedText = attributedText;
|
||||
} else {
|
||||
[self stopTypewriterEffect];
|
||||
|
||||
// 显示完整文本
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:[UIColor whiteColor]
|
||||
range:NSMakeRange(0, text.length)];
|
||||
[attributedText addAttribute:NSFontAttributeName
|
||||
value:self.messageLabel.font
|
||||
range:NSMakeRange(0, text.length)];
|
||||
self.messageLabel.attributedText = attributedText;
|
||||
|
||||
// 标记完成
|
||||
if (self.currentMessage) {
|
||||
self.currentMessage.isComplete = YES;
|
||||
self.currentMessage.needsTypewriterEffect = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopTypewriterEffect {
|
||||
if (self.typewriterTimer && self.typewriterTimer.isValid) {
|
||||
[self.typewriterTimer invalidate];
|
||||
}
|
||||
self.typewriterTimer = nil;
|
||||
self.currentCharIndex = 0;
|
||||
self.fullText = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Voice Button
|
||||
|
||||
- (void)updateVoicePlayingState:(BOOL)isPlaying {
|
||||
UIImage *icon = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
icon = isPlaying ? [UIImage systemImageNamed:@"pause.circle.fill"] : [UIImage systemImageNamed:@"play.circle.fill"];
|
||||
}
|
||||
[self.voiceButton setImage:icon forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)showVoiceLoadingAnimation {
|
||||
[self.voiceButton setImage:nil forState:UIControlStateNormal];
|
||||
[self.voiceLoadingIndicator startAnimating];
|
||||
}
|
||||
|
||||
- (void)hideVoiceLoadingAnimation {
|
||||
[self.voiceLoadingIndicator stopAnimating];
|
||||
UIImage *icon = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
icon = [UIImage systemImageNamed:@"play.circle.fill"];
|
||||
}
|
||||
[self.voiceButton setImage:icon forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)voiceButtonTapped {
|
||||
if ([self.delegate respondsToSelector:@selector(assistantCell:didTapVoiceButtonForMessage:)]) {
|
||||
[self.delegate assistantCell:self didTapVoiceButtonForMessage:self.currentMessage];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Reuse
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
[self stopTypewriterEffect];
|
||||
self.messageLabel.text = @"";
|
||||
self.messageLabel.attributedText = nil;
|
||||
[self.messageLoadingIndicator stopAnimating];
|
||||
[self.voiceLoadingIndicator stopAnimating];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self stopTypewriterEffect];
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIButton *)voiceButton {
|
||||
if (!_voiceButton) {
|
||||
_voiceButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage *icon = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
icon = [UIImage systemImageNamed:@"play.circle.fill"];
|
||||
}
|
||||
[_voiceButton setImage:icon forState:UIControlStateNormal];
|
||||
_voiceButton.tintColor = [UIColor whiteColor];
|
||||
[_voiceButton addTarget:self action:@selector(voiceButtonTapped) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _voiceButton;
|
||||
}
|
||||
|
||||
- (UILabel *)durationLabel {
|
||||
if (!_durationLabel) {
|
||||
_durationLabel = [[UILabel alloc] init];
|
||||
_durationLabel.font = [UIFont systemFontOfSize:11];
|
||||
_durationLabel.textColor = [UIColor whiteColor];
|
||||
}
|
||||
return _durationLabel;
|
||||
}
|
||||
|
||||
- (UIActivityIndicatorView *)voiceLoadingIndicator {
|
||||
if (!_voiceLoadingIndicator) {
|
||||
_voiceLoadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium];
|
||||
_voiceLoadingIndicator.color = [UIColor whiteColor];
|
||||
_voiceLoadingIndicator.hidesWhenStopped = YES;
|
||||
}
|
||||
return _voiceLoadingIndicator;
|
||||
}
|
||||
|
||||
- (UIActivityIndicatorView *)messageLoadingIndicator {
|
||||
if (!_messageLoadingIndicator) {
|
||||
_messageLoadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium];
|
||||
_messageLoadingIndicator.color = [UIColor whiteColor];
|
||||
_messageLoadingIndicator.hidesWhenStopped = YES;
|
||||
}
|
||||
return _messageLoadingIndicator;
|
||||
}
|
||||
|
||||
- (UIView *)bubbleView {
|
||||
if (!_bubbleView) {
|
||||
_bubbleView = [[UIView alloc] init];
|
||||
_bubbleView.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.7];
|
||||
_bubbleView.layer.cornerRadius = 12;
|
||||
_bubbleView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _bubbleView;
|
||||
}
|
||||
|
||||
- (UILabel *)messageLabel {
|
||||
if (!_messageLabel) {
|
||||
_messageLabel = [[UILabel alloc] init];
|
||||
_messageLabel.numberOfLines = 0;
|
||||
_messageLabel.font = [UIFont systemFontOfSize:14];
|
||||
_messageLabel.textColor = [UIColor whiteColor];
|
||||
_messageLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
}
|
||||
return _messageLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
49
CustomKeyboard/View/Chat/KBChatPanelView.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// KBChatPanelView.h
|
||||
// CustomKeyboard
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@class KBChatPanelView, KBChatMessage;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol KBChatPanelViewDelegate <NSObject>
|
||||
@optional
|
||||
- (void)chatPanelView:(KBChatPanelView *)view didSendText:(NSString *)text;
|
||||
- (void)chatPanelView:(KBChatPanelView *)view didTapMessage:(KBChatMessage *)message;
|
||||
- (void)chatPanelViewDidTapClose:(KBChatPanelView *)view;
|
||||
/// 点击语音播放按钮
|
||||
- (void)chatPanelView:(KBChatPanelView *)view didTapVoiceButtonForMessage:(KBChatMessage *)message;
|
||||
@end
|
||||
|
||||
@interface KBChatPanelView : UIView
|
||||
|
||||
@property (nonatomic, weak) id<KBChatPanelViewDelegate> delegate;
|
||||
|
||||
@property (nonatomic, strong, readonly) UITableView *tableView;
|
||||
|
||||
//- (void)kb_setBackgroundImage:(nullable UIImage *)image;
|
||||
- (void)kb_reloadWithMessages:(NSArray<KBChatMessage *> *)messages;
|
||||
|
||||
/// 添加用户消息
|
||||
- (void)kb_addUserMessage:(NSString *)text;
|
||||
|
||||
/// 添加 loading 状态的 AI 消息
|
||||
- (void)kb_addLoadingAssistantMessage;
|
||||
|
||||
/// 移除 loading 状态的 AI 消息
|
||||
- (void)kb_removeLoadingAssistantMessage;
|
||||
|
||||
/// 添加 AI 消息(带打字机效果)
|
||||
- (void)kb_addAssistantMessage:(NSString *)text audioId:(nullable NSString *)audioId;
|
||||
|
||||
/// 更新最后一条 AI 消息的音频数据
|
||||
- (void)kb_updateLastAssistantMessageWithAudioData:(NSData *)audioData duration:(NSTimeInterval)duration;
|
||||
|
||||
/// 滚动到底部
|
||||
- (void)kb_scrollToBottom;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
347
CustomKeyboard/View/Chat/KBChatPanelView.m
Normal file
@@ -0,0 +1,347 @@
|
||||
//
|
||||
// KBChatPanelView.m
|
||||
// CustomKeyboard
|
||||
//
|
||||
|
||||
#import "KBChatPanelView.h"
|
||||
#import "KBChatMessage.h"
|
||||
#import "KBChatUserCell.h"
|
||||
#import "KBChatAssistantCell.h"
|
||||
#import "Masonry.h"
|
||||
|
||||
static NSString * const kUserCellIdentifier = @"KBChatUserCell";
|
||||
static NSString * const kAssistantCellIdentifier = @"KBChatAssistantCell";
|
||||
static const NSUInteger kKBChatMessageLimit = 10;
|
||||
|
||||
@interface KBChatPanelView () <UITableViewDataSource, UITableViewDelegate, KBChatAssistantCellDelegate>
|
||||
@property (nonatomic, strong) UIView *headerView;
|
||||
@property (nonatomic, strong) UILabel *titleLabel;
|
||||
@property (nonatomic, strong) UIButton *closeButton;
|
||||
@property (nonatomic, strong) UITableView *tableViewInternal;
|
||||
@property (nonatomic, strong) NSMutableArray<KBChatMessage *> *messages;
|
||||
@end
|
||||
|
||||
@implementation KBChatPanelView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.messages = [NSMutableArray array];
|
||||
|
||||
[self addSubview:self.headerView];
|
||||
[self addSubview:self.tableViewInternal];
|
||||
|
||||
[self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self);
|
||||
make.top.equalTo(self.mas_top);
|
||||
make.height.mas_equalTo(KBFit(36.0f));
|
||||
}];
|
||||
|
||||
[self.tableViewInternal mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self);
|
||||
make.top.equalTo(self.headerView.mas_bottom).offset(4);
|
||||
make.bottom.equalTo(self.mas_bottom).offset(-8);
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (void)kb_reloadWithMessages:(NSArray<KBChatMessage *> *)messages {
|
||||
NSLog(@"[Panel] ⚠️ kb_reloadWithMessages 被调用,传入 %lu 条消息", (unsigned long)messages.count);
|
||||
|
||||
[self.messages removeAllObjects];
|
||||
if (messages.count > 0) {
|
||||
[self.messages addObjectsFromArray:messages];
|
||||
}
|
||||
[self.tableViewInternal reloadData];
|
||||
[self kb_scrollToBottom];
|
||||
}
|
||||
|
||||
- (void)kb_addUserMessage:(NSString *)text {
|
||||
if (text.length == 0) return;
|
||||
|
||||
NSLog(@"[Panel] 添加用户消息: %@,当前消息数: %lu", text, (unsigned long)self.messages.count);
|
||||
|
||||
KBChatMessage *msg = [KBChatMessage userMessageWithText:text];
|
||||
[self kb_appendMessage:msg];
|
||||
|
||||
NSLog(@"[Panel] 添加后消息数: %lu", (unsigned long)self.messages.count);
|
||||
}
|
||||
|
||||
- (void)kb_addLoadingAssistantMessage {
|
||||
NSLog(@"[Panel] 添加 loading 消息,当前消息数: %lu", (unsigned long)self.messages.count);
|
||||
|
||||
KBChatMessage *msg = [KBChatMessage loadingAssistantMessage];
|
||||
[self kb_appendMessage:msg];
|
||||
|
||||
NSLog(@"[Panel] 添加后消息数: %lu", (unsigned long)self.messages.count);
|
||||
}
|
||||
|
||||
- (void)kb_removeLoadingAssistantMessage {
|
||||
NSLog(@"[Panel] 移除 loading 消息,当前消息数: %lu", (unsigned long)self.messages.count);
|
||||
|
||||
for (NSInteger i = self.messages.count - 1; i >= 0; i--) {
|
||||
KBChatMessage *msg = self.messages[i];
|
||||
// 只移除 AI 消息(outgoing == NO)且是 loading 状态的
|
||||
if (!msg.outgoing && msg.isLoading) {
|
||||
NSLog(@"[Panel] ✅ 找到 loading 消息,移除索引: %ld", (long)i);
|
||||
[self.messages removeObjectAtIndex:i];
|
||||
|
||||
// 使用 beginUpdates/endUpdates 包裹删除操作
|
||||
[self.tableViewInternal beginUpdates];
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
|
||||
[self.tableViewInternal deleteRowsAtIndexPaths:@[indexPath]
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
[self.tableViewInternal endUpdates];
|
||||
|
||||
NSLog(@"[Panel] 移除后消息数: %lu", (unsigned long)self.messages.count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_addAssistantMessage:(NSString *)text audioId:(NSString *)audioId {
|
||||
NSLog(@"[Panel] ========== kb_addAssistantMessage ==========");
|
||||
NSLog(@"[Panel] 当前消息数: %lu", (unsigned long)self.messages.count);
|
||||
|
||||
// 查找 loading 消息的索引
|
||||
NSInteger loadingIndex = -1;
|
||||
for (NSInteger i = self.messages.count - 1; i >= 0; i--) {
|
||||
KBChatMessage *msg = self.messages[i];
|
||||
if (!msg.outgoing && msg.isLoading) {
|
||||
loadingIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建 AI 消息
|
||||
KBChatMessage *msg = [KBChatMessage assistantMessageWithText:text audioId:audioId];
|
||||
msg.displayName = KBLocalized(@"AI助手");
|
||||
NSLog(@"[Panel] 创建 AI 消息,needsTypewriter: %d", msg.needsTypewriterEffect);
|
||||
|
||||
// 使用批量更新,避免界面跳动
|
||||
[self.tableViewInternal beginUpdates];
|
||||
|
||||
if (loadingIndex >= 0) {
|
||||
// 移除 loading 消息
|
||||
NSLog(@"[Panel] 移除 loading 索引: %ld", (long)loadingIndex);
|
||||
[self.messages removeObjectAtIndex:loadingIndex];
|
||||
NSIndexPath *deleteIndexPath = [NSIndexPath indexPathForRow:loadingIndex inSection:0];
|
||||
[self.tableViewInternal deleteRowsAtIndexPaths:@[deleteIndexPath]
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
}
|
||||
|
||||
// 添加 AI 消息
|
||||
NSInteger insertIndex = self.messages.count;
|
||||
[self.messages addObject:msg];
|
||||
NSLog(@"[Panel] 插入 AI 消息索引: %ld", (long)insertIndex);
|
||||
NSIndexPath *insertIndexPath = [NSIndexPath indexPathForRow:insertIndex inSection:0];
|
||||
[self.tableViewInternal insertRowsAtIndexPaths:@[insertIndexPath]
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
|
||||
[self.tableViewInternal endUpdates];
|
||||
|
||||
// 滚动到底部
|
||||
[self kb_scrollToBottom];
|
||||
|
||||
NSLog(@"[Panel] 添加后消息数: %lu", (unsigned long)self.messages.count);
|
||||
}
|
||||
|
||||
- (void)kb_updateLastAssistantMessageWithAudioData:(NSData *)audioData duration:(NSTimeInterval)duration {
|
||||
NSLog(@"[Panel] 更新音频数据,duration: %.2f", duration);
|
||||
for (NSInteger i = self.messages.count - 1; i >= 0; i--) {
|
||||
KBChatMessage *msg = self.messages[i];
|
||||
// 只更新 AI 消息(outgoing == NO)且非 loading 状态的
|
||||
if (!msg.outgoing && !msg.isLoading) {
|
||||
msg.audioData = audioData;
|
||||
msg.audioDuration = duration;
|
||||
|
||||
// 不刷新 Cell,避免打断打字机效果
|
||||
if (duration > 0) {
|
||||
msg.needsTypewriterEffect = NO;
|
||||
msg.isComplete = YES;
|
||||
}
|
||||
NSLog(@"[Panel] ✅ 音频数据已更新");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_scrollToBottom {
|
||||
if (self.messages.count == 0) return;
|
||||
|
||||
NSLog(@"[Panel] 滚动到底部,消息数: %lu", (unsigned long)self.messages.count);
|
||||
|
||||
[self.tableViewInternal layoutIfNeeded];
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.messages.count - 1 inSection:0];
|
||||
[self.tableViewInternal scrollToRowAtIndexPath:indexPath
|
||||
atScrollPosition:UITableViewScrollPositionBottom
|
||||
animated:NO]; // 改为 NO,避免动画导致跳动
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)kb_appendMessage:(KBChatMessage *)message {
|
||||
if (!message) return;
|
||||
|
||||
NSInteger oldCount = self.messages.count;
|
||||
[self.messages addObject:message];
|
||||
NSLog(@"[Panel] kb_appendMessage: oldCount=%ld, newCount=%lu", (long)oldCount, (unsigned long)self.messages.count);
|
||||
|
||||
// 限制消息数量
|
||||
if (self.messages.count > kKBChatMessageLimit) {
|
||||
NSUInteger overflow = self.messages.count - kKBChatMessageLimit;
|
||||
[self.messages removeObjectsInRange:NSMakeRange(0, overflow)];
|
||||
NSLog(@"[Panel] 消息超限,reloadData");
|
||||
[self.tableViewInternal reloadData];
|
||||
} else {
|
||||
NSLog(@"[Panel] 插入新行: %ld", (long)oldCount);
|
||||
[self.tableViewInternal beginUpdates];
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:oldCount inSection:0];
|
||||
[self.tableViewInternal insertRowsAtIndexPaths:@[indexPath]
|
||||
withRowAnimation:UITableViewRowAnimationNone];
|
||||
[self.tableViewInternal endUpdates];
|
||||
}
|
||||
|
||||
// 直接滚动,不用 dispatch_async
|
||||
[self kb_scrollToBottom];
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)kb_onTapClose {
|
||||
if ([self.delegate respondsToSelector:@selector(chatPanelViewDidTapClose:)]) {
|
||||
[self.delegate chatPanelViewDidTapClose:self];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return self.messages.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.row >= self.messages.count) {
|
||||
NSLog(@"[Panel] ❌ cellForRow 索引越界: %ld >= %lu", (long)indexPath.row, (unsigned long)self.messages.count);
|
||||
return [[UITableViewCell alloc] init];
|
||||
}
|
||||
|
||||
KBChatMessage *msg = self.messages[indexPath.row];
|
||||
NSLog(@"[Panel] cellForRow[%ld]: outgoing=%d, isLoading=%d", (long)indexPath.row, msg.outgoing, msg.isLoading);
|
||||
|
||||
if (msg.outgoing) {
|
||||
// 用户消息(右侧)
|
||||
KBChatUserCell *cell = [tableView dequeueReusableCellWithIdentifier:kUserCellIdentifier forIndexPath:indexPath];
|
||||
[cell configureWithMessage:msg];
|
||||
return cell;
|
||||
} else {
|
||||
// AI 消息(左侧)
|
||||
KBChatAssistantCell *cell = [tableView dequeueReusableCellWithIdentifier:kAssistantCellIdentifier forIndexPath:indexPath];
|
||||
cell.delegate = self;
|
||||
[cell configureWithMessage:msg];
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return UITableViewAutomaticDimension;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return 60.0;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.row >= self.messages.count) { return; }
|
||||
KBChatMessage *msg = self.messages[indexPath.row];
|
||||
if ([self.delegate respondsToSelector:@selector(chatPanelView:didTapMessage:)]) {
|
||||
[self.delegate chatPanelView:self didTapMessage:msg];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - KBChatAssistantCellDelegate
|
||||
|
||||
- (void)assistantCell:(KBChatAssistantCell *)cell didTapVoiceButtonForMessage:(KBChatMessage *)message {
|
||||
if ([self.delegate respondsToSelector:@selector(chatPanelView:didTapVoiceButtonForMessage:)]) {
|
||||
[self.delegate chatPanelView:self didTapVoiceButtonForMessage:message];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UITableView *)tableViewInternal {
|
||||
if (!_tableViewInternal) {
|
||||
_tableViewInternal = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
||||
_tableViewInternal.backgroundColor = [UIColor clearColor];
|
||||
_tableViewInternal.backgroundView = nil;
|
||||
_tableViewInternal.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||
_tableViewInternal.dataSource = self;
|
||||
_tableViewInternal.delegate = self;
|
||||
_tableViewInternal.estimatedRowHeight = 60.0;
|
||||
_tableViewInternal.rowHeight = UITableViewAutomaticDimension;
|
||||
// 注册两种 Cell
|
||||
[_tableViewInternal registerClass:KBChatUserCell.class forCellReuseIdentifier:kUserCellIdentifier];
|
||||
[_tableViewInternal registerClass:KBChatAssistantCell.class forCellReuseIdentifier:kAssistantCellIdentifier];
|
||||
if (@available(iOS 11.0, *)) {
|
||||
_tableViewInternal.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
||||
}
|
||||
}
|
||||
return _tableViewInternal;
|
||||
}
|
||||
|
||||
- (UIView *)headerView {
|
||||
if (!_headerView) {
|
||||
_headerView = [[UIView alloc] init];
|
||||
_headerView.backgroundColor = [UIColor clearColor];
|
||||
[_headerView addSubview:self.titleLabel];
|
||||
[_headerView addSubview:self.closeButton];
|
||||
|
||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(_headerView.mas_left).offset(12);
|
||||
make.centerY.equalTo(_headerView);
|
||||
}];
|
||||
|
||||
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.equalTo(_headerView.mas_right).offset(-12);
|
||||
make.centerY.equalTo(_headerView);
|
||||
make.width.height.mas_equalTo(KBFit(24.0f));
|
||||
}];
|
||||
}
|
||||
return _headerView;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [[UILabel alloc] init];
|
||||
_titleLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightMedium];
|
||||
_titleLabel.textColor =
|
||||
[UIColor kb_dynamicColorWithLightColor:[UIColor colorWithHex:0x1B1F1A]
|
||||
darkColor:[UIColor whiteColor]];
|
||||
_titleLabel.text = KBLocalized(@"AI对话");
|
||||
}
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)closeButton {
|
||||
if (!_closeButton) {
|
||||
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage *icon = [UIImage imageNamed:@"close_icon"];
|
||||
[_closeButton setImage:icon forState:UIControlStateNormal];
|
||||
_closeButton.backgroundColor = [UIColor clearColor];
|
||||
[_closeButton addTarget:self
|
||||
action:@selector(kb_onTapClose)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _closeButton;
|
||||
}
|
||||
|
||||
#pragma mark - Expose
|
||||
|
||||
- (UITableView *)tableView { return self.tableViewInternal; }
|
||||
|
||||
@end
|
||||
19
CustomKeyboard/View/Chat/KBChatUserCell.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// KBChatUserCell.h
|
||||
// CustomKeyboard
|
||||
//
|
||||
// 用户消息 Cell(右侧显示)
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@class KBChatMessage;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBChatUserCell : UITableViewCell
|
||||
|
||||
- (void)configureWithMessage:(KBChatMessage *)message;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
85
CustomKeyboard/View/Chat/KBChatUserCell.m
Normal file
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// KBChatUserCell.m
|
||||
// CustomKeyboard
|
||||
//
|
||||
// 用户消息 Cell(右侧显示)
|
||||
//
|
||||
|
||||
#import "KBChatUserCell.h"
|
||||
#import "KBChatMessage.h"
|
||||
#import "Masonry.h"
|
||||
|
||||
@interface KBChatUserCell ()
|
||||
|
||||
@property (nonatomic, strong) UIView *bubbleView;
|
||||
@property (nonatomic, strong) UILabel *messageLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation KBChatUserCell
|
||||
|
||||
- (instancetype)initWithStyle:(UITableViewCellStyle)style
|
||||
reuseIdentifier:(NSString *)reuseIdentifier {
|
||||
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
|
||||
if (self) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.contentView.backgroundColor = [UIColor clearColor];
|
||||
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
[self setupUI];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupUI {
|
||||
[self.contentView addSubview:self.bubbleView];
|
||||
[self.bubbleView addSubview:self.messageLabel];
|
||||
|
||||
[self.bubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.contentView).offset(4);
|
||||
make.bottom.equalTo(self.contentView).offset(-4);
|
||||
make.right.equalTo(self.contentView).offset(-12);
|
||||
make.width.lessThanOrEqualTo(self.contentView).multipliedBy(0.7);
|
||||
make.height.greaterThanOrEqualTo(@36);
|
||||
}];
|
||||
|
||||
[self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.bubbleView).offset(8);
|
||||
make.bottom.equalTo(self.bubbleView).offset(-8);
|
||||
make.left.equalTo(self.bubbleView).offset(12);
|
||||
make.right.equalTo(self.bubbleView).offset(-12);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)configureWithMessage:(KBChatMessage *)message {
|
||||
self.messageLabel.text = message.text ?: @"";
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
self.messageLabel.text = @"";
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIView *)bubbleView {
|
||||
if (!_bubbleView) {
|
||||
_bubbleView = [[UIView alloc] init];
|
||||
_bubbleView.backgroundColor = [UIColor colorWithHex:0x02BEAC];
|
||||
_bubbleView.layer.cornerRadius = 12;
|
||||
_bubbleView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _bubbleView;
|
||||
}
|
||||
|
||||
- (UILabel *)messageLabel {
|
||||
if (!_messageLabel) {
|
||||
_messageLabel = [[UILabel alloc] init];
|
||||
_messageLabel.numberOfLines = 0;
|
||||
_messageLabel.font = [UIFont systemFontOfSize:14];
|
||||
_messageLabel.textColor = [UIColor whiteColor];
|
||||
_messageLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
}
|
||||
return _messageLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
38
CustomKeyboard/View/KBChatMessageCell.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// KBChatMessageCell.h
|
||||
// CustomKeyboard
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
@class KBChatMessage;
|
||||
@class KBChatMessageCell;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol KBChatMessageCellDelegate <NSObject>
|
||||
@optional
|
||||
/// 点击语音播放按钮
|
||||
- (void)chatMessageCell:(KBChatMessageCell *)cell didTapVoiceButtonForMessage:(KBChatMessage *)message;
|
||||
@end
|
||||
|
||||
@interface KBChatMessageCell : UITableViewCell
|
||||
|
||||
@property (nonatomic, weak) id<KBChatMessageCellDelegate> delegate;
|
||||
|
||||
- (void)kb_configureWithMessage:(KBChatMessage *)message;
|
||||
|
||||
/// 更新语音播放状态
|
||||
- (void)kb_updateVoicePlayingState:(BOOL)isPlaying;
|
||||
|
||||
/// 显示语音加载动画
|
||||
- (void)kb_showVoiceLoadingAnimation;
|
||||
|
||||
/// 隐藏语音加载动画
|
||||
- (void)kb_hideVoiceLoadingAnimation;
|
||||
|
||||
/// 停止打字机效果
|
||||
- (void)kb_stopTypewriterEffect;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
495
CustomKeyboard/View/KBChatMessageCell.m
Normal file
@@ -0,0 +1,495 @@
|
||||
//
|
||||
// KBChatMessageCell.m
|
||||
// CustomKeyboard
|
||||
//
|
||||
|
||||
#import "KBChatMessageCell.h"
|
||||
#import "KBChatMessage.h"
|
||||
#import "Masonry.h"
|
||||
|
||||
@interface KBChatMessageCell ()
|
||||
|
||||
@property (nonatomic, strong) UIImageView *avatarView;
|
||||
@property (nonatomic, strong) UILabel *nameLabel;
|
||||
@property (nonatomic, strong) UIView *bubbleView;
|
||||
@property (nonatomic, strong) UILabel *messageLabel;
|
||||
@property (nonatomic, strong) UIImageView *audioIconView;
|
||||
@property (nonatomic, strong) UILabel *audioLabel;
|
||||
|
||||
/// 语音播放按钮
|
||||
@property (nonatomic, strong) UIButton *voiceButton;
|
||||
/// 语音时长标签
|
||||
@property (nonatomic, strong) UILabel *durationLabel;
|
||||
/// 语音加载指示器
|
||||
@property (nonatomic, strong) UIActivityIndicatorView *voiceLoadingIndicator;
|
||||
/// 消息加载指示器(AI 回复 loading)
|
||||
@property (nonatomic, strong) UIActivityIndicatorView *messageLoadingIndicator;
|
||||
|
||||
/// 当前消息
|
||||
@property (nonatomic, strong) KBChatMessage *currentMessage;
|
||||
|
||||
/// 打字机效果
|
||||
@property (nonatomic, strong) NSTimer *typewriterTimer;
|
||||
@property (nonatomic, copy) NSString *fullText;
|
||||
@property (nonatomic, assign) NSInteger currentCharIndex;
|
||||
|
||||
@end
|
||||
|
||||
@implementation KBChatMessageCell
|
||||
|
||||
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
|
||||
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.contentView.backgroundColor = [UIColor clearColor];
|
||||
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
[self.contentView addSubview:self.avatarView];
|
||||
[self.contentView addSubview:self.nameLabel];
|
||||
[self.contentView addSubview:self.voiceButton];
|
||||
[self.contentView addSubview:self.durationLabel];
|
||||
[self.contentView addSubview:self.voiceLoadingIndicator];
|
||||
[self.contentView addSubview:self.messageLoadingIndicator];
|
||||
[self.contentView addSubview:self.bubbleView];
|
||||
[self.bubbleView addSubview:self.messageLabel];
|
||||
[self.bubbleView addSubview:self.audioIconView];
|
||||
[self.bubbleView addSubview:self.audioLabel];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)kb_configureWithMessage:(KBChatMessage *)message {
|
||||
// 先停止之前的打字机效果
|
||||
[self kb_stopTypewriterEffect];
|
||||
|
||||
self.currentMessage = message;
|
||||
|
||||
BOOL outgoing = message.outgoing;
|
||||
BOOL audioMessage = (!outgoing && message.audioFilePath.length > 0);
|
||||
UIColor *bubbleColor = outgoing ? [UIColor colorWithHex:0x02BEAC] : [UIColor colorWithWhite:1 alpha:0.95];
|
||||
UIColor *incomingTextColor =
|
||||
[UIColor kb_dynamicColorWithLightColor:[UIColor colorWithHex:0x1B1F1A]
|
||||
darkColor:[UIColor whiteColor]];
|
||||
UIColor *textColor = outgoing ? [UIColor whiteColor] : incomingTextColor;
|
||||
UIColor *nameColor =
|
||||
[UIColor kb_dynamicColorWithLightColor:[UIColor colorWithHex:0x6B6F7A]
|
||||
darkColor:[UIColor colorWithHex:0xC7CBD4]];
|
||||
|
||||
self.bubbleView.backgroundColor = bubbleColor;
|
||||
self.messageLabel.textColor = textColor;
|
||||
self.audioLabel.textColor = textColor;
|
||||
self.audioIconView.tintColor = textColor;
|
||||
self.audioLabel.text =
|
||||
(message.text.length > 0) ? message.text : KBLocalized(@"语音回复");
|
||||
self.messageLabel.hidden = audioMessage;
|
||||
self.audioIconView.hidden = !audioMessage;
|
||||
self.audioLabel.hidden = !audioMessage;
|
||||
|
||||
UIImage *avatarImage = message.avatarImage;
|
||||
if (!avatarImage) {
|
||||
avatarImage = [self kb_defaultAvatarImage];
|
||||
}
|
||||
self.avatarView.image = avatarImage;
|
||||
self.avatarView.backgroundColor =
|
||||
avatarImage ? [UIColor clearColor] : [UIColor colorWithWhite:0.9 alpha:1.0];
|
||||
self.nameLabel.hidden = outgoing;
|
||||
self.nameLabel.textColor = nameColor;
|
||||
self.nameLabel.text =
|
||||
(message.displayName.length > 0) ? message.displayName : KBLocalized(@"AI助手");
|
||||
|
||||
// 处理 loading 状态
|
||||
if (message.isLoading && !outgoing) {
|
||||
self.bubbleView.hidden = YES;
|
||||
self.voiceButton.hidden = YES;
|
||||
self.durationLabel.hidden = YES;
|
||||
[self.messageLoadingIndicator startAnimating];
|
||||
[self kb_layoutForOutgoing:outgoing audioMessage:NO];
|
||||
return;
|
||||
}
|
||||
|
||||
// 非 loading 状态
|
||||
[self.messageLoadingIndicator stopAnimating];
|
||||
self.bubbleView.hidden = NO;
|
||||
|
||||
// 语音按钮显示逻辑(仅 AI 消息且有 audioId 或 audioData)
|
||||
BOOL hasAudio = (!outgoing) && (message.audioId.length > 0 || message.audioData.length > 0);
|
||||
self.voiceButton.hidden = !hasAudio;
|
||||
self.durationLabel.hidden = !hasAudio;
|
||||
if (hasAudio && message.audioDuration > 0) {
|
||||
NSInteger seconds = (NSInteger)ceil(message.audioDuration);
|
||||
self.durationLabel.text = [NSString stringWithFormat:@"%ld\"", (long)seconds];
|
||||
} else {
|
||||
self.durationLabel.text = @"";
|
||||
}
|
||||
|
||||
// 打字机效果
|
||||
if (!outgoing && message.needsTypewriterEffect && !message.isComplete && message.text.length > 0) {
|
||||
[self kb_startTypewriterEffectWithText:message.text];
|
||||
} else {
|
||||
self.messageLabel.attributedText = nil;
|
||||
self.messageLabel.text = message.text ?: @"";
|
||||
}
|
||||
|
||||
[self kb_layoutForOutgoing:outgoing audioMessage:audioMessage];
|
||||
}
|
||||
|
||||
- (void)kb_layoutForOutgoing:(BOOL)outgoing audioMessage:(BOOL)audioMessage {
|
||||
CGFloat avatarSize = 28.0;
|
||||
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.height.mas_equalTo(avatarSize);
|
||||
make.top.equalTo(self.contentView.mas_top).offset(6);
|
||||
if (outgoing) {
|
||||
make.right.equalTo(self.contentView.mas_right).offset(-8);
|
||||
} else {
|
||||
make.left.equalTo(self.contentView.mas_left).offset(8);
|
||||
}
|
||||
}];
|
||||
|
||||
if (outgoing) {
|
||||
[self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.contentView.mas_top).offset(0);
|
||||
make.left.equalTo(self.contentView.mas_left);
|
||||
}];
|
||||
// 用户消息不显示语音按钮
|
||||
[self.voiceButton mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.height.mas_equalTo(0);
|
||||
make.left.top.equalTo(self.contentView);
|
||||
}];
|
||||
[self.durationLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.height.mas_equalTo(0);
|
||||
make.left.top.equalTo(self.contentView);
|
||||
}];
|
||||
} else {
|
||||
[self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.avatarView.mas_right).offset(6);
|
||||
make.top.equalTo(self.contentView.mas_top).offset(2);
|
||||
make.right.lessThanOrEqualTo(self.contentView.mas_right).offset(-12);
|
||||
}];
|
||||
// AI 消息语音按钮
|
||||
[self.voiceButton mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.avatarView.mas_right).offset(6);
|
||||
make.top.equalTo(self.nameLabel.mas_bottom).offset(4);
|
||||
make.width.height.mas_equalTo(20);
|
||||
}];
|
||||
[self.durationLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.voiceButton.mas_right).offset(4);
|
||||
make.centerY.equalTo(self.voiceButton);
|
||||
}];
|
||||
[self.voiceLoadingIndicator mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.center.equalTo(self.voiceButton);
|
||||
}];
|
||||
}
|
||||
|
||||
// 消息加载指示器
|
||||
[self.messageLoadingIndicator mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
if (outgoing) {
|
||||
make.right.equalTo(self.avatarView.mas_left).offset(-10);
|
||||
} else {
|
||||
make.left.equalTo(self.avatarView.mas_right).offset(10);
|
||||
}
|
||||
make.top.equalTo(self.nameLabel.mas_bottom).offset(8);
|
||||
}];
|
||||
|
||||
[self.bubbleView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.lessThanOrEqualTo(self.contentView.mas_width).multipliedBy(0.65);
|
||||
if (outgoing) {
|
||||
make.top.equalTo(self.contentView.mas_top).offset(6);
|
||||
make.bottom.equalTo(self.contentView.mas_bottom).offset(-6);
|
||||
make.right.equalTo(self.avatarView.mas_left).offset(-6);
|
||||
} else {
|
||||
// AI 消息:气泡在语音按钮下方
|
||||
make.top.equalTo(self.voiceButton.mas_bottom).offset(4);
|
||||
make.bottom.equalTo(self.contentView.mas_bottom).offset(-6);
|
||||
make.left.equalTo(self.avatarView.mas_right).offset(6);
|
||||
make.right.lessThanOrEqualTo(self.contentView.mas_right).offset(-12);
|
||||
}
|
||||
}];
|
||||
|
||||
if (audioMessage) {
|
||||
[self.messageLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.height.mas_equalTo(0);
|
||||
make.left.equalTo(self.bubbleView.mas_left);
|
||||
make.top.equalTo(self.bubbleView.mas_top);
|
||||
}];
|
||||
[self.audioIconView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.bubbleView.mas_left).offset(10);
|
||||
make.centerY.equalTo(self.bubbleView);
|
||||
make.width.height.mas_equalTo(16);
|
||||
}];
|
||||
[self.audioLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.audioIconView.mas_right).offset(6);
|
||||
make.centerY.equalTo(self.bubbleView);
|
||||
make.right.equalTo(self.bubbleView.mas_right).offset(-10);
|
||||
make.top.greaterThanOrEqualTo(self.bubbleView.mas_top).offset(8);
|
||||
make.bottom.lessThanOrEqualTo(self.bubbleView.mas_bottom).offset(-8);
|
||||
}];
|
||||
} else {
|
||||
[self.audioIconView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.height.mas_equalTo(0);
|
||||
make.left.equalTo(self.bubbleView.mas_left);
|
||||
make.top.equalTo(self.bubbleView.mas_top);
|
||||
}];
|
||||
[self.audioLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.width.height.mas_equalTo(0);
|
||||
make.left.equalTo(self.audioIconView.mas_right);
|
||||
make.top.equalTo(self.bubbleView.mas_top);
|
||||
}];
|
||||
[self.messageLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.bubbleView).insets(UIEdgeInsetsMake(8, 10, 8, 10));
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Typewriter Effect
|
||||
|
||||
- (void)kb_startTypewriterEffectWithText:(NSString *)text {
|
||||
if (text.length == 0) return;
|
||||
|
||||
self.fullText = text;
|
||||
self.currentCharIndex = 0;
|
||||
|
||||
// 先设置完整文本让布局计算正确高度
|
||||
self.messageLabel.text = text;
|
||||
[self.contentView setNeedsLayout];
|
||||
[self.contentView layoutIfNeeded];
|
||||
|
||||
// 应用打字机效果
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:[UIColor clearColor]
|
||||
range:NSMakeRange(0, text.length)];
|
||||
[attributedText addAttribute:NSFontAttributeName
|
||||
value:self.messageLabel.font
|
||||
range:NSMakeRange(0, text.length)];
|
||||
self.messageLabel.attributedText = attributedText;
|
||||
|
||||
self.typewriterTimer = [NSTimer scheduledTimerWithTimeInterval:0.03
|
||||
target:self
|
||||
selector:@selector(kb_typewriterTick)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
[[NSRunLoop currentRunLoop] addTimer:self.typewriterTimer forMode:NSRunLoopCommonModes];
|
||||
[self kb_typewriterTick];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)kb_typewriterTick {
|
||||
NSString *text = self.fullText;
|
||||
if (!text || text.length == 0) {
|
||||
[self kb_stopTypewriterEffect];
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.currentCharIndex < text.length) {
|
||||
self.currentCharIndex++;
|
||||
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
|
||||
UIColor *textColor = self.messageLabel.textColor ?: [UIColor blackColor];
|
||||
|
||||
if (self.currentCharIndex > 0) {
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:textColor
|
||||
range:NSMakeRange(0, self.currentCharIndex)];
|
||||
}
|
||||
if (self.currentCharIndex < text.length) {
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:[UIColor clearColor]
|
||||
range:NSMakeRange(self.currentCharIndex, text.length - self.currentCharIndex)];
|
||||
}
|
||||
[attributedText addAttribute:NSFontAttributeName
|
||||
value:self.messageLabel.font
|
||||
range:NSMakeRange(0, text.length)];
|
||||
|
||||
self.messageLabel.attributedText = attributedText;
|
||||
} else {
|
||||
[self kb_stopTypewriterEffect];
|
||||
|
||||
// 显示完整文本
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
|
||||
UIColor *textColor = self.messageLabel.textColor ?: [UIColor blackColor];
|
||||
[attributedText addAttribute:NSForegroundColorAttributeName
|
||||
value:textColor
|
||||
range:NSMakeRange(0, text.length)];
|
||||
[attributedText addAttribute:NSFontAttributeName
|
||||
value:self.messageLabel.font
|
||||
range:NSMakeRange(0, text.length)];
|
||||
self.messageLabel.attributedText = attributedText;
|
||||
|
||||
// 标记完成
|
||||
if (self.currentMessage) {
|
||||
self.currentMessage.isComplete = YES;
|
||||
self.currentMessage.needsTypewriterEffect = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_stopTypewriterEffect {
|
||||
if (self.typewriterTimer && self.typewriterTimer.isValid) {
|
||||
[self.typewriterTimer invalidate];
|
||||
}
|
||||
self.typewriterTimer = nil;
|
||||
self.currentCharIndex = 0;
|
||||
self.fullText = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Voice Button
|
||||
|
||||
- (void)kb_updateVoicePlayingState:(BOOL)isPlaying {
|
||||
UIImage *icon = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
icon = isPlaying ? [UIImage systemImageNamed:@"pause.circle.fill"] : [UIImage systemImageNamed:@"play.circle.fill"];
|
||||
}
|
||||
[self.voiceButton setImage:icon forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)kb_showVoiceLoadingAnimation {
|
||||
[self.voiceButton setImage:nil forState:UIControlStateNormal];
|
||||
[self.voiceLoadingIndicator startAnimating];
|
||||
}
|
||||
|
||||
- (void)kb_hideVoiceLoadingAnimation {
|
||||
[self.voiceLoadingIndicator stopAnimating];
|
||||
UIImage *icon = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
icon = [UIImage systemImageNamed:@"play.circle.fill"];
|
||||
}
|
||||
[self.voiceButton setImage:icon forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)kb_onVoiceButtonTapped {
|
||||
if ([self.delegate respondsToSelector:@selector(chatMessageCell:didTapVoiceButtonForMessage:)]) {
|
||||
[self.delegate chatMessageCell:self didTapVoiceButtonForMessage:self.currentMessage];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Reuse
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
[self kb_stopTypewriterEffect];
|
||||
self.messageLabel.text = @"";
|
||||
self.messageLabel.attributedText = nil;
|
||||
[self.messageLoadingIndicator stopAnimating];
|
||||
[self.voiceLoadingIndicator stopAnimating];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self kb_stopTypewriterEffect];
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIImageView *)avatarView {
|
||||
if (!_avatarView) {
|
||||
_avatarView = [[UIImageView alloc] init];
|
||||
_avatarView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_avatarView.layer.cornerRadius = 14;
|
||||
_avatarView.layer.masksToBounds = YES;
|
||||
_avatarView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
|
||||
_avatarView.tintColor =
|
||||
[UIColor kb_dynamicColorWithLightColor:[UIColor colorWithHex:0xB9BDC8]
|
||||
darkColor:[UIColor colorWithHex:0x6B6F7A]];
|
||||
}
|
||||
return _avatarView;
|
||||
}
|
||||
|
||||
- (UILabel *)nameLabel {
|
||||
if (!_nameLabel) {
|
||||
_nameLabel = [[UILabel alloc] init];
|
||||
_nameLabel.font = [UIFont systemFontOfSize:11];
|
||||
_nameLabel.textColor = [UIColor colorWithHex:0x6B6F7A];
|
||||
_nameLabel.numberOfLines = 1;
|
||||
}
|
||||
return _nameLabel;
|
||||
}
|
||||
|
||||
- (UIView *)bubbleView {
|
||||
if (!_bubbleView) {
|
||||
_bubbleView = [[UIView alloc] init];
|
||||
_bubbleView.layer.cornerRadius = 12;
|
||||
_bubbleView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _bubbleView;
|
||||
}
|
||||
|
||||
- (UILabel *)messageLabel {
|
||||
if (!_messageLabel) {
|
||||
_messageLabel = [[UILabel alloc] init];
|
||||
_messageLabel.font = [UIFont systemFontOfSize:14];
|
||||
_messageLabel.numberOfLines = 0;
|
||||
}
|
||||
return _messageLabel;
|
||||
}
|
||||
|
||||
- (UIImageView *)audioIconView {
|
||||
if (!_audioIconView) {
|
||||
_audioIconView = [[UIImageView alloc] init];
|
||||
_audioIconView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
_audioIconView.tintColor = [UIColor colorWithHex:0x1B1F1A];
|
||||
UIImage *icon = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
icon = [UIImage systemImageNamed:@"waveform"];
|
||||
}
|
||||
_audioIconView.image = icon;
|
||||
}
|
||||
return _audioIconView;
|
||||
}
|
||||
|
||||
- (UILabel *)audioLabel {
|
||||
if (!_audioLabel) {
|
||||
_audioLabel = [[UILabel alloc] init];
|
||||
_audioLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
|
||||
_audioLabel.numberOfLines = 1;
|
||||
}
|
||||
return _audioLabel;
|
||||
}
|
||||
|
||||
- (UIButton *)voiceButton {
|
||||
if (!_voiceButton) {
|
||||
_voiceButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage *icon = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
icon = [UIImage systemImageNamed:@"play.circle.fill"];
|
||||
}
|
||||
[_voiceButton setImage:icon forState:UIControlStateNormal];
|
||||
_voiceButton.tintColor = [UIColor whiteColor];
|
||||
[_voiceButton addTarget:self action:@selector(kb_onVoiceButtonTapped) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _voiceButton;
|
||||
}
|
||||
|
||||
- (UILabel *)durationLabel {
|
||||
if (!_durationLabel) {
|
||||
_durationLabel = [[UILabel alloc] init];
|
||||
_durationLabel.font = [UIFont systemFontOfSize:11];
|
||||
_durationLabel.textColor = [UIColor whiteColor];
|
||||
}
|
||||
return _durationLabel;
|
||||
}
|
||||
|
||||
- (UIActivityIndicatorView *)voiceLoadingIndicator {
|
||||
if (!_voiceLoadingIndicator) {
|
||||
_voiceLoadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium];
|
||||
_voiceLoadingIndicator.color = [UIColor whiteColor];
|
||||
_voiceLoadingIndicator.hidesWhenStopped = YES;
|
||||
}
|
||||
return _voiceLoadingIndicator;
|
||||
}
|
||||
|
||||
- (UIActivityIndicatorView *)messageLoadingIndicator {
|
||||
if (!_messageLoadingIndicator) {
|
||||
_messageLoadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium];
|
||||
_messageLoadingIndicator.color = [UIColor whiteColor];
|
||||
_messageLoadingIndicator.hidesWhenStopped = YES;
|
||||
}
|
||||
return _messageLoadingIndicator;
|
||||
}
|
||||
|
||||
- (UIImage *)kb_defaultAvatarImage {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
return [UIImage systemImageNamed:@"person.circle.fill"];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -360,7 +360,6 @@ static inline NSString *KBTrimRight(NSString *s) {
|
||||
contextAfter = proxy.documentContextAfterInput ?: @"";
|
||||
}
|
||||
}
|
||||
|
||||
NSString *contextBefore = proxy.documentContextBeforeInput ?: @"";
|
||||
while (contextBefore.length > 0) {
|
||||
for (NSUInteger i = 0; i < contextBefore.length; i++) {
|
||||
@@ -372,6 +371,16 @@ static inline NSString *KBTrimRight(NSString *s) {
|
||||
if (rawText.length > 0) {
|
||||
[proxy insertText:rawText];
|
||||
}
|
||||
NSMutableDictionary *extra = [NSMutableDictionary dictionary];
|
||||
extra[@"send_text"] = rawText ? rawText : @"";
|
||||
extra[@"index"] = index ? rawText : 0;
|
||||
|
||||
[[KBMaiPointReporter sharedReporter]
|
||||
reportClickWithEventName:@"send_stream_text_action"
|
||||
pageId:@"keyboard_StreamTextView"
|
||||
elementId:@"handle_label"
|
||||
extra:extra.copy
|
||||
completion:nil];
|
||||
[[KBInputBufferManager shared] resetWithText:rawText ?: @""];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@property (nonatomic, weak, nullable) id<KBToolBarDelegate> delegate;
|
||||
|
||||
/// 左侧按钮的标题(数量由数组决定)。默认值:@[@"AI"]。
|
||||
/// 左侧按钮的标题(数量由数组决定)。默认值:@[@"AI", @"语音"]。
|
||||
@property (nonatomic, copy) NSArray<NSString *> *leftButtonTitles;
|
||||
|
||||
/// 暴露按钮以便外部定制(只读;首次访问时懒加载创建)
|
||||
|
||||
@@ -26,11 +26,12 @@ static NSString * const kKBAIKeyIdentifier = @"ai";
|
||||
static NSString * const kKBUndoKeyIdentifier = @"key_revoke";
|
||||
static const CGFloat kKBAIButtonWidth = 40;
|
||||
static const CGFloat kKBAIButtonHeight = 40;
|
||||
static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
_leftButtonTitles = @[@"AI"]; // 默认标题
|
||||
_leftButtonTitles = @[@"AI", KBLocalized(@"语音")]; // 默认标题
|
||||
[self setupUI];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(kb_undoStateChanged)
|
||||
@@ -68,6 +69,7 @@ static const CGFloat kKBAIButtonHeight = 40;
|
||||
}
|
||||
}];
|
||||
[self kb_updateAIButtonAppearance];
|
||||
[self kb_updateVoiceButtonAppearance];
|
||||
}
|
||||
|
||||
#pragma mark - 视图搭建
|
||||
@@ -171,6 +173,7 @@ static const CGFloat kKBAIButtonHeight = 40;
|
||||
|
||||
- (void)kb_applyTheme {
|
||||
[self kb_updateAIButtonAppearance];
|
||||
[self kb_updateVoiceButtonAppearance];
|
||||
[self kb_updateUndoButtonAppearance];
|
||||
}
|
||||
|
||||
@@ -208,6 +211,16 @@ static const CGFloat kKBAIButtonHeight = 40;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_updateVoiceButtonAppearance {
|
||||
UIButton *voiceButton = [self kb_voiceButton];
|
||||
if (!voiceButton) { return; }
|
||||
|
||||
voiceButton.backgroundColor = [UIColor colorWithHex:0xE53935];
|
||||
[voiceButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||
voiceButton.layer.cornerRadius = 16;
|
||||
voiceButton.layer.masksToBounds = YES;
|
||||
}
|
||||
|
||||
- (void)kb_updateUndoButtonAppearance {
|
||||
if (!self.undoButtonInternal) { return; }
|
||||
|
||||
@@ -306,6 +319,11 @@ static const CGFloat kKBAIButtonHeight = 40;
|
||||
return self.leftButtonsInternal[0];
|
||||
}
|
||||
|
||||
- (UIButton *)kb_voiceButton {
|
||||
if (self.leftButtonsInternal.count <= kKBVoiceButtonIndex) { return nil; }
|
||||
return self.leftButtonsInternal[kKBVoiceButtonIndex];
|
||||
}
|
||||
|
||||
#pragma mark - Globe (Input Mode Switch)
|
||||
|
||||
// 根据宿主是否已提供系统切换键,决定是否显示地球按钮;并绑定系统事件。
|
||||
|
||||
1
Podfile
@@ -29,6 +29,7 @@ target 'CustomKeyboard' do
|
||||
use_frameworks!
|
||||
|
||||
pod 'AFNetworking','4.0.1'
|
||||
pod 'SDWebImage', '5.21.1'
|
||||
|
||||
pod 'Masonry', '1.1.0'
|
||||
pod 'MBProgressHUD', '1.2.0'
|
||||
|
||||
@@ -96,6 +96,6 @@ SPEC CHECKSUMS:
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
|
||||
|
||||
PODFILE CHECKSUM: 3b9d37a9d2c323afb33b6389f3c70184f53ea313
|
||||
PODFILE CHECKSUM: 890d1710715c017d7364a19c871e9bdf0d685fbf
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
2
Pods/Manifest.lock
generated
@@ -96,6 +96,6 @@ SPEC CHECKSUMS:
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
|
||||
|
||||
PODFILE CHECKSUM: 3b9d37a9d2c323afb33b6389f3c70184f53ea313
|
||||
PODFILE CHECKSUM: 890d1710715c017d7364a19c871e9bdf0d685fbf
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
412
Pods/Pods.xcodeproj/project.pbxproj
generated
@@ -83,6 +83,7 @@
|
||||
1CA85ECC202E5CF62530BAD7C0DCDAF2 /* LookinHierarchyInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = C792FA3E4D3612659DA4500FE9D4A687 /* LookinHierarchyInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1D18A1A5D485D57192B021A8765C0AF5 /* LookinTuple.h in Headers */ = {isa = PBXBuildFile; fileRef = A6D1CC45A7943BAD96C97D9225C9021D /* LookinTuple.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1D3DCD05B685A7CAF291C25D922B1831 /* HWPanModalPresentationController.m in Sources */ = {isa = PBXBuildFile; fileRef = F1FAB9A951323777D4A48D49725B9802 /* HWPanModalPresentationController.m */; };
|
||||
1D7A626B22937B65716BDF135E5566C2 /* Pods-CustomKeyboard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DDD0462C32F55EF5E9CB1056459809F /* Pods-CustomKeyboard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1DB724891F1F6468BDB333369F667F39 /* HWPanModalPresentableHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A518E59A590CAA7BC0D3ADD4113D0AC /* HWPanModalPresentableHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1DC161351EBD409CC622E826340E4FD8 /* JXCategoryTitleVerticalZoomCell.h in Headers */ = {isa = PBXBuildFile; fileRef = ECE929CFE87E3E6402751CE58A6B7439 /* JXCategoryTitleVerticalZoomCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1EA011B45EC780B434507AFB3D9647ED /* NSObject+MJCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 0157E81AF7D3A5016170216831D8914B /* NSObject+MJCoding.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -102,7 +103,6 @@
|
||||
2175B894008D948C762468307BA677B8 /* RTLManager.m in Sources */ = {isa = PBXBuildFile; fileRef = AD9FC9F1DFCA104E54D6E4547D96356D /* RTLManager.m */; };
|
||||
2210A1E405AB21104E7AF86D05C8AD39 /* LYEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = B7C6325AEC2E86B0B251C3EB931247DD /* LYEmptyView.m */; };
|
||||
22516EA77E7120000632C30BD9A03927 /* UIScrollView+MJExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 5ED944F2FDEEB1DA10261DC24BC5A158 /* UIScrollView+MJExtension.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
22A4B2F6485F38FC998C238B899ED0DE /* Pods-CustomKeyboard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CB13D51E717D347023EEB57263E3072 /* Pods-CustomKeyboard-dummy.m */; };
|
||||
22C38AE7AB145224FF646303AFED11D2 /* JXCategoryDotCellModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 44F2EA17CF495B3C7801177736C26647 /* JXCategoryDotCellModel.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
22F19B23471EE7840581A348EB735BD1 /* UIViewController+LayoutHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 44FDE6E0FD25622CBD1C32FE4FDD3698 /* UIViewController+LayoutHelper.m */; };
|
||||
231A40F14D020AE2F61AA5C3289E6CF9 /* UITextView+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 81D1208390281107018E2EF73BCE3B61 /* UITextView+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -216,6 +216,7 @@
|
||||
4DD9F4BAA95C3527A660D3AAD055CF1E /* HWPanModalContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = BF92FB29A700B0634F55358F1FC1D8BE /* HWPanModalContentView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4E56BA148170B3A6E7FA6D312B06C784 /* mz_zip_rw.h in Headers */ = {isa = PBXBuildFile; fileRef = B313FB2E02E6138E1628A481AF03A970 /* mz_zip_rw.h */; settings = {ATTRIBUTES = (Project, ); }; };
|
||||
4E964FFE29CFF8613C0029C913F39A05 /* LKS_InbuiltAttrModificationHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = A0041C94BD88F8B62868FB3EF9609FB8 /* LKS_InbuiltAttrModificationHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4EBF759D0963EB4E343C5B0A9CF3EA7F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8490F2CF00DB93F5FEEDE1C788BBE73 /* Foundation.framework */; };
|
||||
4EC8DBADA7BB954276351A639EB4398D /* UIBlurEffect+LookinServer.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A301C66E696681FADD2B5F1A72E77F /* UIBlurEffect+LookinServer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4ECE7F80A917130DE4045E25D741EAF9 /* JXCategoryTitleCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 677A9795E43833ACFE4BEFACEB9C9E50 /* JXCategoryTitleCellModel.m */; };
|
||||
4ED05DB3E43FF6AE1FA22130B2B50F05 /* UIImage+MemoryCacheCost.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF0A8FDB47640450B4AD235DDCCFFE1 /* UIImage+MemoryCacheCost.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -356,7 +357,6 @@
|
||||
7EB365BD2FC75CE205A638DD725B0555 /* LSTTimer-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B60A9EA622DCF45E87F4BCA20F525D85 /* LSTTimer-dummy.m */; };
|
||||
7ED6C3C05EA6EE83780A3600C7088B46 /* mz_crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 43F7DFAD54A39AC067B93B7F37CEACC4 /* mz_crypt.h */; settings = {ATTRIBUTES = (Project, ); }; };
|
||||
7F10C0D094C74F2FA4CD38C7FD77B0A8 /* WKWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = E7430A9EA4CB87590757C1508062129E /* WKWebView+AFNetworking.m */; };
|
||||
7F2995EC78B2E2AA4D1A778EF6965729 /* Pods-CustomKeyboard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DDD0462C32F55EF5E9CB1056459809F /* Pods-CustomKeyboard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
7F886FC2763F0BF1625A24EE4F94C04D /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = A496809B712DE9F509171A8B6356A099 /* UIRefreshControl+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
7FA48BF8B9F73775654E75CEB5363FF4 /* UIViewController+PanModalPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FDD439886220AA95FF6B36A5C000873 /* UIViewController+PanModalPresenter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
7FA8C78DB021A7731D30D80C102DE042 /* NSObject+MJKeyValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 36F771A08989CA5134B23D5F5E970ACA /* NSObject+MJKeyValue.m */; };
|
||||
@@ -395,7 +395,6 @@
|
||||
8B47B7F220A2B9E121EFF5A28B477972 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8490F2CF00DB93F5FEEDE1C788BBE73 /* Foundation.framework */; };
|
||||
8B990235A0006E1F9C1E6F68AD81F77C /* JXCategoryView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F727D55D6275E422C78261D496AAC93 /* JXCategoryView-dummy.m */; };
|
||||
8C6C7E25C5A24C936F81823978190E96 /* ViewController+MASAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 03CF13D7504F201F21E62DE0C23B49F7 /* ViewController+MASAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8C910EBFEAB32D47BA166C7A2BDA4833 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8490F2CF00DB93F5FEEDE1C788BBE73 /* Foundation.framework */; };
|
||||
8D2CBEBF5F1DA6766A833CCD0BF02B5B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B039DC77C7D8D33CEAB56314AAFE04CB /* CoreGraphics.framework */; };
|
||||
8D8AD606ECD8E1F247965CD43956D412 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FD20E21FF7A2BAB6FAAB004A82D3143 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8F43694404EAFF6D73EE58928154C0F2 /* mz_strm_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 263454233B5B0DBB14C5D80582B2B2AD /* mz_strm_buf.h */; settings = {ATTRIBUTES = (Project, ); }; };
|
||||
@@ -624,6 +623,7 @@
|
||||
E1BF615DD0422B06C97542F03C879D41 /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 06A64D211ADC6AF2DF1D9E7D4F7F2788 /* AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
E1DE69F6BB6235A6EDB6C99A184BEDB4 /* UIScrollView+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 85E0616DFCFEB6E1346B75E425451AFD /* UIScrollView+MJExtension.m */; };
|
||||
E283D8FF283E09D9CF863A27B55886EF /* mz_crypt_apple.c in Sources */ = {isa = PBXBuildFile; fileRef = 59AF9F3690B04B3F352C8CAC3F871AB8 /* mz_crypt_apple.c */; };
|
||||
E2BFC7E0926543D2958A027FF90ADB7D /* Pods-CustomKeyboard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CB13D51E717D347023EEB57263E3072 /* Pods-CustomKeyboard-dummy.m */; };
|
||||
E2DF1B379D9444D40D78320E90B1DC07 /* JXCategoryIndicatorLineView.h in Headers */ = {isa = PBXBuildFile; fileRef = 67CB215173B14FC72227F43EE74EF96E /* JXCategoryIndicatorLineView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
E3FC6BEE41652C0500F57E0CB83B347F /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 9187109C444449118A500CD6A1F2D532 /* UIButton+AFNetworking.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
E42D6EF120A5C17DA2F6FD6473CE7E7A /* JXCategoryTitleVerticalZoomCellModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E9252395065AF703DEC1F4DB7906407 /* JXCategoryTitleVerticalZoomCellModel.m */; };
|
||||
@@ -720,6 +720,13 @@
|
||||
remoteGlobalIDString = B32AF3F43989CBA171BB1FB3957A4509;
|
||||
remoteInfo = "MJExtension-MJExtension";
|
||||
};
|
||||
0BA199CC20B25ECBF52240507FDC08C4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E;
|
||||
remoteInfo = Masonry;
|
||||
};
|
||||
0F9E615457E5337681A14D3D3D4458A5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
@@ -734,12 +741,12 @@
|
||||
remoteGlobalIDString = 8BEAFAA726C1965864B79B4B441AA513;
|
||||
remoteInfo = JXCategoryView;
|
||||
};
|
||||
27B965B2A5BF3AAB32C259DCFA82E713 /* PBXContainerItemProxy */ = {
|
||||
251D3BEB8BCF4207A404D692AE545BC0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0;
|
||||
remoteInfo = MBProgressHUD;
|
||||
remoteGlobalIDString = 0130B3724283586C0E9D2A112D4F2AA1;
|
||||
remoteInfo = AFNetworking;
|
||||
};
|
||||
2FE163B88A520FE9B2F4EF7346158A53 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
@@ -755,20 +762,6 @@
|
||||
remoteGlobalIDString = 5A2609DB0612F95A3450D2E02CA850A0;
|
||||
remoteInfo = LSTTimer;
|
||||
};
|
||||
35DB38B21DD3BB8CCFFEBEA22F70E3EC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85;
|
||||
remoteInfo = MJExtension;
|
||||
};
|
||||
4087212A2E57778E1FAE4448329729FC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 0130B3724283586C0E9D2A112D4F2AA1;
|
||||
remoteInfo = AFNetworking;
|
||||
};
|
||||
43E0BC7F6C06EB0590226928F1AA1BA3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
@@ -825,6 +818,13 @@
|
||||
remoteGlobalIDString = 4A68CFD979D413A619DF631BB121D98F;
|
||||
remoteInfo = Bugly;
|
||||
};
|
||||
7008466503D9ECD9A228719ABE80A8B8 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 3847153A6E5EEFB86565BA840768F429;
|
||||
remoteInfo = SDWebImage;
|
||||
};
|
||||
73A9CA6BDE2B4D18F9677452E6992CBE /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
@@ -839,6 +839,20 @@
|
||||
remoteGlobalIDString = 638FEAAFC575BB76BC6AC055CDDA3506;
|
||||
remoteInfo = LookinServer;
|
||||
};
|
||||
8E4A89375470440DB2A9D7DE942EA358 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F1BCD9702276377FB5B3BDB6EAF709D7;
|
||||
remoteInfo = DZNEmptyDataSet;
|
||||
};
|
||||
8FA5A660DC27E9C3CA22FAEBEAFD4EAE /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 82B0A41D3031FF27D78E17B0A9A46FB0;
|
||||
remoteInfo = MBProgressHUD;
|
||||
};
|
||||
9E12D5E078E322AEAC001666EEE5AA65 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
@@ -846,6 +860,13 @@
|
||||
remoteGlobalIDString = 94CFBA7D633ECA58DF85C327B035E6A3;
|
||||
remoteInfo = "SDWebImage-SDWebImage";
|
||||
};
|
||||
A54DB880113009E6DC0A1C72BF95FEBC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F60E38364AFF5E1349FF07415B944396;
|
||||
remoteInfo = SSZipArchive;
|
||||
};
|
||||
A671E8D796937C62D30391BE1F16A0AD /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
@@ -888,13 +909,6 @@
|
||||
remoteGlobalIDString = C4E1020AF425614337737213AA26DBD5;
|
||||
remoteInfo = JXPagingView;
|
||||
};
|
||||
C64183E6A8A311BA11445309E5971A39 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F60E38364AFF5E1349FF07415B944396;
|
||||
remoteInfo = SSZipArchive;
|
||||
};
|
||||
D264D8BA205995C828877A13415E636F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
@@ -902,19 +916,12 @@
|
||||
remoteGlobalIDString = 8B7D23DD98E41BAE91418E9E85F191D6;
|
||||
remoteInfo = LSTPopView;
|
||||
};
|
||||
E84BA8741985D658E053DCDE9D54DC93 /* PBXContainerItemProxy */ = {
|
||||
FF3D3DA5C34F21FD0969B09D751C9FE4 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 55AF53E6C77A10ED4985E04D74A8878E;
|
||||
remoteInfo = Masonry;
|
||||
};
|
||||
E9AF0D0B9313853D3F5E9187EFFEFD3E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F1BCD9702276377FB5B3BDB6EAF709D7;
|
||||
remoteInfo = DZNEmptyDataSet;
|
||||
remoteGlobalIDString = 4D3BA58D0583DF37575CACAB3DDADC85;
|
||||
remoteInfo = MJExtension;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
@@ -1734,14 +1741,6 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2B2A05DA621D2C41C33F96F10A8D14CA /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8C910EBFEAB32D47BA166C7A2BDA4833 /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
37145BAEB1B97BA7ADD7D6C3E86E99BD /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1759,6 +1758,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
3EC76FC6C791E7FE69C7759A8887094C /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4EBF759D0963EB4E343C5B0A9CF3EA7F /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
481273BD538BE69936DB3D2C8EB1E61B /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -3281,6 +3288,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
25CC84E8B8C20837CF92C21B1D12D6A5 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1D7A626B22937B65716BDF135E5566C2 /* Pods-CustomKeyboard-umbrella.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
33783D69751B087D045FCF1FCA02E724 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -3554,14 +3569,6 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9410C6DE72A0330546B884B956D00AE3 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7F2995EC78B2E2AA4D1A778EF6965729 /* Pods-CustomKeyboard-umbrella.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9AD51F59D2F73C167710F5A0609DC491 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4019,22 +4026,23 @@
|
||||
};
|
||||
D9B2DB11933DB55A80A118934E6680AB /* Pods-CustomKeyboard */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 9D98282E352578D31FFA72EC2EA10205 /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */;
|
||||
buildConfigurationList = C91382D1639D3BC69FAE164863007F33 /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */;
|
||||
buildPhases = (
|
||||
9410C6DE72A0330546B884B956D00AE3 /* Headers */,
|
||||
8699DF800B987868E64537798BF35D21 /* Sources */,
|
||||
2B2A05DA621D2C41C33F96F10A8D14CA /* Frameworks */,
|
||||
58D6818319C1893F5DD838DA2E524465 /* Resources */,
|
||||
25CC84E8B8C20837CF92C21B1D12D6A5 /* Headers */,
|
||||
544B1A3A7751D86ED8D64727A731F538 /* Sources */,
|
||||
3EC76FC6C791E7FE69C7759A8887094C /* Frameworks */,
|
||||
2B96AF27C134A995F5218E67CF3B6DFC /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
29EEEFA492E836FF504DC738E40616C1 /* PBXTargetDependency */,
|
||||
563A5BA80B0E2469A5B175F42B4CDCB3 /* PBXTargetDependency */,
|
||||
DBDC4DC1910238D9E4AFB348253087E0 /* PBXTargetDependency */,
|
||||
D81C399F78E00E0C0F046839ECAECED8 /* PBXTargetDependency */,
|
||||
A0F93D6E706C7F4A596E07F119D77189 /* PBXTargetDependency */,
|
||||
1D4616B2C078FD73573BFBC623E9C978 /* PBXTargetDependency */,
|
||||
7793C47E78D668D8DF962F887006EBBA /* PBXTargetDependency */,
|
||||
D9CDEC212B78FBACD23CCBFBB4AEF183 /* PBXTargetDependency */,
|
||||
96BBA4F53A10C9797B36082CF698D670 /* PBXTargetDependency */,
|
||||
3461C912C0C986DEA384D3845A39EBDE /* PBXTargetDependency */,
|
||||
1CAF7447041685C03E13BF8B2B8AC1B2 /* PBXTargetDependency */,
|
||||
2E0AB221F45B2386A80E75669D7FD229 /* PBXTargetDependency */,
|
||||
BB80D6BB502E21A84C54851E8BB7233D /* PBXTargetDependency */,
|
||||
);
|
||||
name = "Pods-CustomKeyboard";
|
||||
productName = Pods_CustomKeyboard;
|
||||
@@ -4177,6 +4185,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2B96AF27C134A995F5218E67CF3B6DFC /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
311EF2CB460B544059B769919A899ECA /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4209,13 +4224,6 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
58D6818319C1893F5DD838DA2E524465 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
5C89912961D7B3B99680563233DBEA04 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4505,6 +4513,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
544B1A3A7751D86ED8D64727A731F538 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E2BFC7E0926543D2958A027FF90ADB7D /* Pods-CustomKeyboard-dummy.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6027CC4F7393762F72827585E71DFAB2 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4520,14 +4536,6 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8699DF800B987868E64537798BF35D21 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
22A4B2F6485F38FC998C238B899ED0DE /* Pods-CustomKeyboard-dummy.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8AF957863B2E92075C7B36542829939B /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -4806,11 +4814,11 @@
|
||||
target = 638FEAAFC575BB76BC6AC055CDDA3506 /* LookinServer */;
|
||||
targetProxy = 8B4AF11BA988C8F1F93788F8C486B793 /* PBXContainerItemProxy */;
|
||||
};
|
||||
1D4616B2C078FD73573BFBC623E9C978 /* PBXTargetDependency */ = {
|
||||
1CAF7447041685C03E13BF8B2B8AC1B2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = SSZipArchive;
|
||||
target = F60E38364AFF5E1349FF07415B944396 /* SSZipArchive */;
|
||||
targetProxy = C64183E6A8A311BA11445309E5971A39 /* PBXContainerItemProxy */;
|
||||
name = Masonry;
|
||||
target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */;
|
||||
targetProxy = 0BA199CC20B25ECBF52240507FDC08C4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
248F793A182F289B47E8B7AC0E143C15 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
@@ -4818,24 +4826,30 @@
|
||||
target = 8B7D23DD98E41BAE91418E9E85F191D6 /* LSTPopView */;
|
||||
targetProxy = D264D8BA205995C828877A13415E636F /* PBXContainerItemProxy */;
|
||||
};
|
||||
29EEEFA492E836FF504DC738E40616C1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = AFNetworking;
|
||||
target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */;
|
||||
targetProxy = 4087212A2E57778E1FAE4448329729FC /* PBXContainerItemProxy */;
|
||||
};
|
||||
2A8FD4D63439C4E1939EBDE48A029628 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = AFNetworking;
|
||||
target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */;
|
||||
targetProxy = 5E2F9C1908DE8387A6F9BF93EF451351 /* PBXContainerItemProxy */;
|
||||
};
|
||||
2E0AB221F45B2386A80E75669D7FD229 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = SDWebImage;
|
||||
target = 3847153A6E5EEFB86565BA840768F429 /* SDWebImage */;
|
||||
targetProxy = 7008466503D9ECD9A228719ABE80A8B8 /* PBXContainerItemProxy */;
|
||||
};
|
||||
318E148AD8C551E2DEAB4E4705F3E9A3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = LSTTimer;
|
||||
target = 5A2609DB0612F95A3450D2E02CA850A0 /* LSTTimer */;
|
||||
targetProxy = B4B05B8E8A2B8CDA0C66D6BAD76B2853 /* PBXContainerItemProxy */;
|
||||
};
|
||||
3461C912C0C986DEA384D3845A39EBDE /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = MJExtension;
|
||||
target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */;
|
||||
targetProxy = FF3D3DA5C34F21FD0969B09D751C9FE4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
3C59938CEAB0C654F6E6F4BDA7461510 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = SDWebImage;
|
||||
@@ -4848,12 +4862,6 @@
|
||||
target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */;
|
||||
targetProxy = C4958E3B26588834E71F94361C112780 /* PBXContainerItemProxy */;
|
||||
};
|
||||
563A5BA80B0E2469A5B175F42B4CDCB3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = DZNEmptyDataSet;
|
||||
target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */;
|
||||
targetProxy = E9AF0D0B9313853D3F5E9187EFFEFD3E /* PBXContainerItemProxy */;
|
||||
};
|
||||
639EDB1EF0277187CB2CFA270FDAF6FB /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = Bugly;
|
||||
@@ -4878,6 +4886,12 @@
|
||||
target = F60E38364AFF5E1349FF07415B944396 /* SSZipArchive */;
|
||||
targetProxy = 0F9E615457E5337681A14D3D3D4458A5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
7793C47E78D668D8DF962F887006EBBA /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = AFNetworking;
|
||||
target = 0130B3724283586C0E9D2A112D4F2AA1 /* AFNetworking */;
|
||||
targetProxy = 251D3BEB8BCF4207A404D692AE545BC0 /* PBXContainerItemProxy */;
|
||||
};
|
||||
8FDFA4D41ED37BC3CC62156D15AAAD81 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "MJRefresh-MJRefresh.Privacy";
|
||||
@@ -4896,24 +4910,30 @@
|
||||
target = E79E29F55A2453370D27112480FCF6A2 /* JXCategoryView-JXCategoryView */;
|
||||
targetProxy = AB4EC7D2E9FDF608986EDAF1E480CFD7 /* PBXContainerItemProxy */;
|
||||
};
|
||||
96BBA4F53A10C9797B36082CF698D670 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = MBProgressHUD;
|
||||
target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */;
|
||||
targetProxy = 8FA5A660DC27E9C3CA22FAEBEAFD4EAE /* PBXContainerItemProxy */;
|
||||
};
|
||||
9E31237C8A36AF7A7A0B110E3EB735D6 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = MJExtension;
|
||||
target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */;
|
||||
targetProxy = A671E8D796937C62D30391BE1F16A0AD /* PBXContainerItemProxy */;
|
||||
};
|
||||
A0F93D6E706C7F4A596E07F119D77189 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = Masonry;
|
||||
target = 55AF53E6C77A10ED4985E04D74A8878E /* Masonry */;
|
||||
targetProxy = E84BA8741985D658E053DCDE9D54DC93 /* PBXContainerItemProxy */;
|
||||
};
|
||||
B44D94075E090726E517F9003F07D314 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = MJRefresh;
|
||||
target = 6868056D761E163D10FDAF8CF1C4D9B8 /* MJRefresh */;
|
||||
targetProxy = 43E0BC7F6C06EB0590226928F1AA1BA3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
BB80D6BB502E21A84C54851E8BB7233D /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = SSZipArchive;
|
||||
target = F60E38364AFF5E1349FF07415B944396 /* SSZipArchive */;
|
||||
targetProxy = A54DB880113009E6DC0A1C72BF95FEBC /* PBXContainerItemProxy */;
|
||||
};
|
||||
BDAE500408DCC4FE45DED4761241917F /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = LYEmptyView;
|
||||
@@ -4932,17 +4952,11 @@
|
||||
target = 16704C6B67439DA959DB043702C75A7A /* JXPagingView-JXPagerView */;
|
||||
targetProxy = 682B4482FB905997BF77F5EE588BD3E4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D81C399F78E00E0C0F046839ECAECED8 /* PBXTargetDependency */ = {
|
||||
D9CDEC212B78FBACD23CCBFBB4AEF183 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = MJExtension;
|
||||
target = 4D3BA58D0583DF37575CACAB3DDADC85 /* MJExtension */;
|
||||
targetProxy = 35DB38B21DD3BB8CCFFEBEA22F70E3EC /* PBXContainerItemProxy */;
|
||||
};
|
||||
DBDC4DC1910238D9E4AFB348253087E0 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = MBProgressHUD;
|
||||
target = 82B0A41D3031FF27D78E17B0A9A46FB0 /* MBProgressHUD */;
|
||||
targetProxy = 27B965B2A5BF3AAB32C259DCFA82E713 /* PBXContainerItemProxy */;
|
||||
name = DZNEmptyDataSet;
|
||||
target = F1BCD9702276377FB5B3BDB6EAF709D7 /* DZNEmptyDataSet */;
|
||||
targetProxy = 8E4A89375470440DB2A9D7DE942EA358 /* PBXContainerItemProxy */;
|
||||
};
|
||||
E4C8B75060752222288EE781ED53D28B /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
@@ -5217,6 +5231,46 @@
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
24665D97781934C3B37DE62A9BDDAC61 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 1D774D8146EBC82B4A77204A273761B8 /* Pods-CustomKeyboard.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
|
||||
CLANG_ENABLE_OBJC_WEAK = NO;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_MODULE_VERIFIER = NO;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.modulemap";
|
||||
OTHER_LDFLAGS = "";
|
||||
OTHER_LIBTOOLFLAGS = "";
|
||||
PODS_ROOT = "$(SRCROOT)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
26CEDC3022E1F92C78B66EF88DA3E538 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 35BFA337F4E1FDE67C773A82CCDFD6DA /* Pods-keyBoard.debug.xcconfig */;
|
||||
@@ -5256,6 +5310,45 @@
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
275B39FBA2E7104CEE81B3D399E7C7D3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 0D6215D1BCCE125B8DF73E38013CBBDC /* Pods-CustomKeyboard.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
|
||||
CLANG_ENABLE_OBJC_WEAK = NO;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_MODULE_VERIFIER = NO;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.modulemap";
|
||||
OTHER_LDFLAGS = "";
|
||||
OTHER_LIBTOOLFLAGS = "";
|
||||
PODS_ROOT = "$(SRCROOT)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
319C3324D522C12DEC60436B1B3B2CE7 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 01771F71A5835C346537272402AFB9A6 /* LSTTimer.debug.xcconfig */;
|
||||
@@ -5350,45 +5443,6 @@
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4B175742078B8D3442EF645D38AE40CC /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 0D6215D1BCCE125B8DF73E38013CBBDC /* Pods-CustomKeyboard.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
|
||||
CLANG_ENABLE_OBJC_WEAK = NO;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_MODULE_VERIFIER = NO;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.modulemap";
|
||||
OTHER_LDFLAGS = "";
|
||||
OTHER_LIBTOOLFLAGS = "";
|
||||
PODS_ROOT = "$(SRCROOT)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
4C8CF8906202B413F352B558474547DF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = BEB9455CE0A06FE1E60E43D8A39479DA /* JXCategoryView.debug.xcconfig */;
|
||||
@@ -6147,46 +6201,6 @@
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
AF99EB3786A8B2C9346426EAB1BB2239 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 1D774D8146EBC82B4A77204A273761B8 /* Pods-CustomKeyboard.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
|
||||
CLANG_ENABLE_OBJC_WEAK = NO;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_MODULE_VERIFIER = NO;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
INFOPLIST_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard-Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MODULEMAP_FILE = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.modulemap";
|
||||
OTHER_LDFLAGS = "";
|
||||
OTHER_LIBTOOLFLAGS = "";
|
||||
PODS_ROOT = "$(SRCROOT)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
B26FBB655ABB114E4C0D589843814D6C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 73625BF0D8F9A3389059227F5BE246B9 /* Bugly.release.xcconfig */;
|
||||
@@ -6850,15 +6864,6 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
9D98282E352578D31FFA72EC2EA10205 /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
4B175742078B8D3442EF645D38AE40CC /* Debug */,
|
||||
AF99EB3786A8B2C9346426EAB1BB2239 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
A0F23D46D133F936F0565C0D3363B200 /* Build configuration list for PBXNativeTarget "LSTTimer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
@@ -6877,6 +6882,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C91382D1639D3BC69FAE164863007F33 /* Build configuration list for PBXNativeTarget "Pods-CustomKeyboard" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
275B39FBA2E7104CEE81B3D399E7C7D3 /* Debug */,
|
||||
24665D97781934C3B37DE62A9BDDAC61 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D47A0ADD8E3841C9330561C3E1664BB3 /* Build configuration list for PBXNativeTarget "HWPanModal" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -104,6 +104,30 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
## SDWebImage
|
||||
|
||||
Copyright (c) 2009-2020 Olivier Poitrey rs@dailymotion.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
|
||||
## SSZipArchive
|
||||
|
||||
Copyright (c) 2013-2021, ZipArchive, https://github.com/ZipArchive
|
||||
|
||||
@@ -145,6 +145,36 @@ THE SOFTWARE.</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2009-2020 Olivier Poitrey rs@dailymotion.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
</string>
|
||||
<key>License</key>
|
||||
<string>MIT</string>
|
||||
<key>Title</key>
|
||||
<string>SDWebImage</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>Copyright (c) 2013-2021, ZipArchive, https://github.com/ZipArchive
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers"
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks'
|
||||
OTHER_LDFLAGS = $(inherited) -l"iconv" -l"z" -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "MBProgressHUD" -framework "MJExtension" -framework "Masonry" -framework "QuartzCore" -framework "SSZipArchive" -framework "Security" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
OTHER_LDFLAGS = $(inherited) -l"iconv" -l"z" -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "MBProgressHUD" -framework "MJExtension" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "SSZipArchive" -framework "Security" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers"
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJExtension/MJExtension.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers"
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks'
|
||||
OTHER_LDFLAGS = $(inherited) -l"iconv" -l"z" -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "MBProgressHUD" -framework "MJExtension" -framework "Masonry" -framework "QuartzCore" -framework "SSZipArchive" -framework "Security" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
OTHER_LDFLAGS = $(inherited) -l"iconv" -l"z" -framework "AFNetworking" -framework "CoreGraphics" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "ImageIO" -framework "MBProgressHUD" -framework "MJExtension" -framework "Masonry" -framework "QuartzCore" -framework "SDWebImage" -framework "SSZipArchive" -framework "Security" -framework "UIKit"
|
||||
OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "-F${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "-F${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "-F${PODS_CONFIGURATION_BUILD_DIR}/MJExtension" "-F${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "-F${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "-F${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
APPLICATION_EXTENSION_API_ONLY = YES
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO
|
||||
|
||||
@@ -69,6 +69,11 @@
|
||||
|
||||
/// AI
|
||||
#define API_AI_TALK @"/chat/talk"
|
||||
#define API_AI_VOICE_TALK @"/chat/voice" // 语音对话(替换为后端真实路径)
|
||||
#define API_AI_CHAT_SYNC @"/chat/sync" // 同步对话
|
||||
#define API_AI_CHAT_MESSAGE @"/chat/message" // 文本润色
|
||||
#define API_AI_AUDIO_UPLOAD @"/chat/audio/upload" // 语音上传(替换为后端真实路径)
|
||||
#define API_AI_SPEECH_TRANSCRIBE @"/speech/transcribe" // 语音转文字
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
/// 键盘 -> 主 App 订阅页预填充数据(用于免二次请求)
|
||||
#define AppGroup_SubscriptionPrefillPayload @"AppGroup_SubscriptionPrefillPayload"
|
||||
|
||||
/// 用户头像 URL(主 App 写入,键盘扩展读取)
|
||||
#define AppGroup_UserAvatarURL @"AppGroup_UserAvatarURL"
|
||||
|
||||
/// 皮肤图标加载模式:
|
||||
/// 0 = 使用本地 Assets 图片名(key_icons 的 value 写成图片名,例如 "kb_q_melon")
|
||||
/// 1 = 使用远程 Zip 皮肤包(skinJSON 中提供 zip_url;key_icons 的 value 写成 Zip 内图标文件名,例如 "key_a")
|
||||
@@ -38,7 +41,7 @@
|
||||
// 基础baseUrl
|
||||
#ifndef KB_BASE_URL
|
||||
//#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/"
|
||||
//#define KB_BASE_URL @"http://192.168.2.21:7529/api"
|
||||
//#define KB_BASE_URL @"http://192.168.2.22:7529/api"
|
||||
#define KB_BASE_URL @"https://devcallback.loveamorkey.com/api"
|
||||
#endif
|
||||
|
||||
|
||||
469
_spm/repositories/swift-collections-9a58d5cf/FETCH_HEAD
Normal file
@@ -0,0 +1,469 @@
|
||||
1f8dcd4726717a4b724e5408ca24829bdef67a49 not-for-merge branch 'action-xcode-versions' of https://github.com/apple/swift-collections
|
||||
7ae9880f0fb622992a8a5328fd4af78af5b6b26f not-for-merge branch 'dn/remove-retain-release-during-find' of https://github.com/apple/swift-collections
|
||||
ddff9004d745c4b2d13e35ebdd1a3d0b67e14717 not-for-merge branch 'doc-basic-span-index-mutation' of https://github.com/apple/swift-collections
|
||||
ebd51171f0e45788e2cdb3cc6d54233e11d7443c not-for-merge branch 'future' of https://github.com/apple/swift-collections
|
||||
534c0cbbfef9d2f6e7a6519930967d75f7c60336 not-for-merge branch 'main' of https://github.com/apple/swift-collections
|
||||
68c32ed80b138d1f8a6ec5dcf1b105f32fcaaf12 not-for-merge branch 'maxd/run-wasm-tests' of https://github.com/apple/swift-collections
|
||||
762bc5757de4bcf86cc3b3266e3df93f76469089 not-for-merge branch 'nate/zip_dispatch_benchmarking' of https://github.com/apple/swift-collections
|
||||
d029d9d39c87bed85b1c50adee7c41795261a192 not-for-merge branch 'release/1.0' of https://github.com/apple/swift-collections
|
||||
c11818f3cae0780656baa430b49e7f163f08dffd not-for-merge branch 'release/1.1' of https://github.com/apple/swift-collections
|
||||
2d1f4172091ca272b461397748fd2c32847036dd not-for-merge branch 'release/1.2' of https://github.com/apple/swift-collections
|
||||
c55cbe540366c704c279298ca6ad4c09a067ebe0 not-for-merge branch 'release/1.3' of https://github.com/apple/swift-collections
|
||||
a26fc8e7e4c6e0d63b08951f5b7268044fb95c83 not-for-merge branch 'span-prototype' of https://github.com/apple/swift-collections
|
||||
434d30dae30fbb57699370260c69c2108c1abf8f not-for-merge branch 'wasm-tests' of https://github.com/apple/swift-collections
|
||||
c65cd649fb91f64636f2f1ef5da4991987139f68 not-for-merge 'refs/pull/10/head' of https://github.com/apple/swift-collections
|
||||
6a9703c3f13061291eff1baf8af4fce1e6ce35af not-for-merge 'refs/pull/100/head' of https://github.com/apple/swift-collections
|
||||
8303a77bc2915be76777d6fc17b702146b6fb192 not-for-merge 'refs/pull/102/head' of https://github.com/apple/swift-collections
|
||||
6cd03922372c85e2dca476f665527976911e7397 not-for-merge 'refs/pull/105/head' of https://github.com/apple/swift-collections
|
||||
96100d4b6ad61bbfbf549ee42dc73239325b353f not-for-merge 'refs/pull/106/head' of https://github.com/apple/swift-collections
|
||||
f69104b5071ef9a44112e3c4fef8904b5e8b6d73 not-for-merge 'refs/pull/107/head' of https://github.com/apple/swift-collections
|
||||
5f255a887e51093f058e7ee9ea0b959051be38d4 not-for-merge 'refs/pull/108/head' of https://github.com/apple/swift-collections
|
||||
c46c77f7f85f9efe83cc5cb8d54b32c538b06450 not-for-merge 'refs/pull/109/head' of https://github.com/apple/swift-collections
|
||||
cfca1038b53eecd4fc50da15cc715f966904012e not-for-merge 'refs/pull/11/head' of https://github.com/apple/swift-collections
|
||||
103008aca495f3b80a50713086d451b08cef9f50 not-for-merge 'refs/pull/110/head' of https://github.com/apple/swift-collections
|
||||
39a16a15cc8c7e11486015d2deb78468b4a64c85 not-for-merge 'refs/pull/111/head' of https://github.com/apple/swift-collections
|
||||
7f57a0ed1c8b1d44eacab95d3cfd57d87482b25a not-for-merge 'refs/pull/112/head' of https://github.com/apple/swift-collections
|
||||
efefae56531b30d75553f234134e3c83bd26c6a6 not-for-merge 'refs/pull/113/head' of https://github.com/apple/swift-collections
|
||||
565b1ab20bef052f52fad4ebe112803facb325e3 not-for-merge 'refs/pull/114/head' of https://github.com/apple/swift-collections
|
||||
8b3af12ece11ea7b0e748749c39a59c59269ca25 not-for-merge 'refs/pull/115/head' of https://github.com/apple/swift-collections
|
||||
8be0f192e8f120969427cb2645aabe6f5fdf15a1 not-for-merge 'refs/pull/116/head' of https://github.com/apple/swift-collections
|
||||
771bca404c0ee603bb6cc2ea3a19cfc4ebc3d001 not-for-merge 'refs/pull/117/head' of https://github.com/apple/swift-collections
|
||||
95be379a3ac1e4278d114a22501267065062b39a not-for-merge 'refs/pull/118/head' of https://github.com/apple/swift-collections
|
||||
f41f2cae69dc6ffcc178227a0a46607561fa925c not-for-merge 'refs/pull/119/head' of https://github.com/apple/swift-collections
|
||||
276ddee5df4ea0f44c5edea0dbe726cb74682498 not-for-merge 'refs/pull/121/head' of https://github.com/apple/swift-collections
|
||||
1c1e6206fa1a4b0a6bf97ac979f841c1d1821ad7 not-for-merge 'refs/pull/122/head' of https://github.com/apple/swift-collections
|
||||
074b0ad21387e767b5b3ff1cb014a118a3b80bde not-for-merge 'refs/pull/123/head' of https://github.com/apple/swift-collections
|
||||
ddc8b9c66d07cb0af38e98ca160f1f7cc85c88d3 not-for-merge 'refs/pull/126/head' of https://github.com/apple/swift-collections
|
||||
9dde4b560323d43ec2ca8225a6c5c79a9bc0735d not-for-merge 'refs/pull/128/head' of https://github.com/apple/swift-collections
|
||||
453adb695f615886cd7a897d62676713aeb25bf9 not-for-merge 'refs/pull/13/head' of https://github.com/apple/swift-collections
|
||||
286fedb1e8f6b2567cd214cf1127a9322dea1400 not-for-merge 'refs/pull/130/head' of https://github.com/apple/swift-collections
|
||||
e77d82c71271b7848e3ac9e007a52f36f04a1c7e not-for-merge 'refs/pull/132/head' of https://github.com/apple/swift-collections
|
||||
1bde9674f42e41bfb62deb96d8b247a537171ba7 not-for-merge 'refs/pull/132/merge' of https://github.com/apple/swift-collections
|
||||
cee04e96ed96fefa5527e33a4a055482e4ea14e9 not-for-merge 'refs/pull/14/head' of https://github.com/apple/swift-collections
|
||||
50e6a1ac71df96e5cd257c565e9a3299f491ba3e not-for-merge 'refs/pull/140/head' of https://github.com/apple/swift-collections
|
||||
29120ea6406a856c36496b4f5d3b13ca381436a6 not-for-merge 'refs/pull/141/head' of https://github.com/apple/swift-collections
|
||||
867231031ac792328eff9133a289ce9e693a03c3 not-for-merge 'refs/pull/15/head' of https://github.com/apple/swift-collections
|
||||
6cb037037d45f78622fd7cab3f62e3c6a4ff5ddb not-for-merge 'refs/pull/153/head' of https://github.com/apple/swift-collections
|
||||
7016a13f0e8d0d0a36f3566a6dc6acaf5b83fbf4 not-for-merge 'refs/pull/155/head' of https://github.com/apple/swift-collections
|
||||
00a99aa77c4982a6e7343982220e44b15e4d5974 not-for-merge 'refs/pull/156/head' of https://github.com/apple/swift-collections
|
||||
74a800ac534877875d5d1187ac04f35b31a0b98c not-for-merge 'refs/pull/159/head' of https://github.com/apple/swift-collections
|
||||
b9d73a5bab8d71e121687f79ed4aabfbd73d016b not-for-merge 'refs/pull/16/head' of https://github.com/apple/swift-collections
|
||||
ddb6d141b3e4e8726a15e3e9e916ee697bd310db not-for-merge 'refs/pull/160/head' of https://github.com/apple/swift-collections
|
||||
3437abecc49cfbbb91893e3a0d0f124db163637f not-for-merge 'refs/pull/161/head' of https://github.com/apple/swift-collections
|
||||
1071b372942289dbd3209ede40f613d339cca8e1 not-for-merge 'refs/pull/162/head' of https://github.com/apple/swift-collections
|
||||
b9d91f4a9aa3cfd6c8589aee997c4399e6d7d83d not-for-merge 'refs/pull/163/head' of https://github.com/apple/swift-collections
|
||||
ee1b2de06edf18545084d99a5c99995e9c1ff8d4 not-for-merge 'refs/pull/165/head' of https://github.com/apple/swift-collections
|
||||
b379fa7aee604738bd0b4076984c934e242bb7a5 not-for-merge 'refs/pull/168/head' of https://github.com/apple/swift-collections
|
||||
71aa4a39ae59addf40e9dd40e79a4968f1c857cc not-for-merge 'refs/pull/169/head' of https://github.com/apple/swift-collections
|
||||
feca3b6f4c7bf7adf9fa4a0fd200f96cf1b5a4b5 not-for-merge 'refs/pull/170/head' of https://github.com/apple/swift-collections
|
||||
9a9d7d87d844b2a14ec602792d9ae216ea57ea53 not-for-merge 'refs/pull/172/head' of https://github.com/apple/swift-collections
|
||||
8cc0b1d43975a9d547053cf0e943498c0d6d7992 not-for-merge 'refs/pull/173/head' of https://github.com/apple/swift-collections
|
||||
aa428d0489be5888c72de4a4327f0f316a586632 not-for-merge 'refs/pull/174/head' of https://github.com/apple/swift-collections
|
||||
14f90620c89e311a067a1fa49813d8bbcd539950 not-for-merge 'refs/pull/175/head' of https://github.com/apple/swift-collections
|
||||
77edbef16d24e657fc3d7b0bc9adb57e6b0567d9 not-for-merge 'refs/pull/176/head' of https://github.com/apple/swift-collections
|
||||
9d9659a079644d300d3571fb64ac7bb14322e506 not-for-merge 'refs/pull/177/head' of https://github.com/apple/swift-collections
|
||||
9f38e7424baa3497e4d481790fc6ec2950725de8 not-for-merge 'refs/pull/178/head' of https://github.com/apple/swift-collections
|
||||
d45f264ef0dc625a37801ee6e05b764ccbef30b4 not-for-merge 'refs/pull/179/head' of https://github.com/apple/swift-collections
|
||||
58579394fc929c1b89b762c3ef68a1657442ca7d not-for-merge 'refs/pull/18/head' of https://github.com/apple/swift-collections
|
||||
39fc818e0efaa148e038e3d89cd78be64567849a not-for-merge 'refs/pull/180/head' of https://github.com/apple/swift-collections
|
||||
4c4154ca2350d981cd6abeadbdcad18071fe3b95 not-for-merge 'refs/pull/181/head' of https://github.com/apple/swift-collections
|
||||
59858a77210f506e622a68e5b92e36bae6fc9215 not-for-merge 'refs/pull/182/head' of https://github.com/apple/swift-collections
|
||||
ba303dca1d72860f0b253778f193010af20f9b79 not-for-merge 'refs/pull/184/head' of https://github.com/apple/swift-collections
|
||||
778b8ae977c420dfe323b27ed3a1cf3f747f936b not-for-merge 'refs/pull/185/head' of https://github.com/apple/swift-collections
|
||||
0f92943ba349d0337d254789bc49e9a5c45ff74e not-for-merge 'refs/pull/187/head' of https://github.com/apple/swift-collections
|
||||
f71ebd9494b3b0b8c1450017f8c30fb61e4dcc37 not-for-merge 'refs/pull/188/head' of https://github.com/apple/swift-collections
|
||||
66651795d89e760188908bb65b3398aa30b84897 not-for-merge 'refs/pull/189/head' of https://github.com/apple/swift-collections
|
||||
832e58027cdb86e618089ebdf2e3474da915c357 not-for-merge 'refs/pull/190/head' of https://github.com/apple/swift-collections
|
||||
9b7c6ecb10599568876b1108005b189de54d9ce9 not-for-merge 'refs/pull/191/head' of https://github.com/apple/swift-collections
|
||||
4604c1bc381c4d164a030d11830701b2897a0002 not-for-merge 'refs/pull/192/head' of https://github.com/apple/swift-collections
|
||||
0b86bb11d24e187ab6ab930f582f75ae00bcabf9 not-for-merge 'refs/pull/193/head' of https://github.com/apple/swift-collections
|
||||
c7c0a094f91bd5cce90b1dc1f3feeb9d2508e7f5 not-for-merge 'refs/pull/194/head' of https://github.com/apple/swift-collections
|
||||
1b71d2cd942459049b870264b7db649ba7509046 not-for-merge 'refs/pull/195/head' of https://github.com/apple/swift-collections
|
||||
7cec5d1ed71d0c29fc7515725401c8a711a01074 not-for-merge 'refs/pull/196/head' of https://github.com/apple/swift-collections
|
||||
b83d06b43337cc2855c1b55ba1cdba854724110b not-for-merge 'refs/pull/197/head' of https://github.com/apple/swift-collections
|
||||
6286cd0b99741db984e5c1115a4c748bc42efec1 not-for-merge 'refs/pull/198/head' of https://github.com/apple/swift-collections
|
||||
8b06c61c7e4ecb6777895a8fba275a44ec8c5e01 not-for-merge 'refs/pull/199/head' of https://github.com/apple/swift-collections
|
||||
5aed92655d73228211985c933e0d5141d8203a09 not-for-merge 'refs/pull/200/head' of https://github.com/apple/swift-collections
|
||||
51604cd196265a1e4444cef0a7ac749e34f5e64e not-for-merge 'refs/pull/201/head' of https://github.com/apple/swift-collections
|
||||
2a81cb1186ac3483183df32ba8c3e2fe7360cbcb not-for-merge 'refs/pull/202/head' of https://github.com/apple/swift-collections
|
||||
6dbc8b8c4f36ff470060464d69066e2e094a194f not-for-merge 'refs/pull/203/head' of https://github.com/apple/swift-collections
|
||||
6b428b5a7fadfae0120db4fc96a3d5b14f7b7c36 not-for-merge 'refs/pull/204/head' of https://github.com/apple/swift-collections
|
||||
b1506b62250f074d23cddc6d0318277dda5d21dc not-for-merge 'refs/pull/205/head' of https://github.com/apple/swift-collections
|
||||
2e872739d3a6201e2b888c73f08ef54ae4125d6d not-for-merge 'refs/pull/206/head' of https://github.com/apple/swift-collections
|
||||
4c842df1b8cfc9611762bdf5fbd9023ab2d3d333 not-for-merge 'refs/pull/207/head' of https://github.com/apple/swift-collections
|
||||
1228e9c1628925843575a11c1de8342e402c7c30 not-for-merge 'refs/pull/208/head' of https://github.com/apple/swift-collections
|
||||
b6184b667bd8f636558522f18cc2fe993a825679 not-for-merge 'refs/pull/21/head' of https://github.com/apple/swift-collections
|
||||
fc8092d0441e0073831d6b170c74b6cca0da9bf5 not-for-merge 'refs/pull/210/head' of https://github.com/apple/swift-collections
|
||||
cfc3d4a5179e61c36d77babd9fd3029a0f85cff4 not-for-merge 'refs/pull/211/head' of https://github.com/apple/swift-collections
|
||||
02ea4e849230bc2326c83c5560822a228d83afab not-for-merge 'refs/pull/212/head' of https://github.com/apple/swift-collections
|
||||
1490835b289653b145b91a16fe5522d928509efb not-for-merge 'refs/pull/213/head' of https://github.com/apple/swift-collections
|
||||
2b4ec22949acbfa99f9e22c390d850a650f3d298 not-for-merge 'refs/pull/214/head' of https://github.com/apple/swift-collections
|
||||
5e0a0149a4c9b2ab407f65b257b5b36bc589307d not-for-merge 'refs/pull/215/head' of https://github.com/apple/swift-collections
|
||||
734730d72460e7bd536e8021d4aa711cb3aa75b2 not-for-merge 'refs/pull/216/head' of https://github.com/apple/swift-collections
|
||||
381cf5d17e46f2d3266bd1be7295118647443313 not-for-merge 'refs/pull/217/head' of https://github.com/apple/swift-collections
|
||||
3c6cb8cd56d04392bf9f79a2d5020fc2abf1958d not-for-merge 'refs/pull/218/head' of https://github.com/apple/swift-collections
|
||||
67fdff5a25539a51ce2a8bf574a7e4a6b72ebfb8 not-for-merge 'refs/pull/219/head' of https://github.com/apple/swift-collections
|
||||
fbdf73e1b787a0ac113e930dff73382f612698d4 not-for-merge 'refs/pull/22/head' of https://github.com/apple/swift-collections
|
||||
d3987c79a1214e279a49a09304c13322560c8a1b not-for-merge 'refs/pull/220/head' of https://github.com/apple/swift-collections
|
||||
5783b82d72e620f37545924d46bdbfb429f03cbb not-for-merge 'refs/pull/221/head' of https://github.com/apple/swift-collections
|
||||
2df7f6d3a8fe5f9bb12b5034da2e095424694d44 not-for-merge 'refs/pull/222/head' of https://github.com/apple/swift-collections
|
||||
72e2df59e3ea600f4d5e67a324bd6df1a7acbd41 not-for-merge 'refs/pull/223/head' of https://github.com/apple/swift-collections
|
||||
98d62d236bef8c30af5b7015ccbb7db66f43399e not-for-merge 'refs/pull/224/head' of https://github.com/apple/swift-collections
|
||||
ba7e3927e76ff55b0579770fb036ffce6ea07b3c not-for-merge 'refs/pull/225/head' of https://github.com/apple/swift-collections
|
||||
207029a613dca008e708370c09fc69010cf6a11d not-for-merge 'refs/pull/226/head' of https://github.com/apple/swift-collections
|
||||
68bc6567be4c1ae96cfea1217b9e5cee63421c6a not-for-merge 'refs/pull/227/head' of https://github.com/apple/swift-collections
|
||||
1c147e3b06edbe0b00217e38e94d2d3bc4b4c6a7 not-for-merge 'refs/pull/228/head' of https://github.com/apple/swift-collections
|
||||
5aa603edfe8c13e0256141cb45f70ec427fe94c1 not-for-merge 'refs/pull/23/head' of https://github.com/apple/swift-collections
|
||||
d19fb14c46266a20cba9c5362923c6a076e74407 not-for-merge 'refs/pull/230/head' of https://github.com/apple/swift-collections
|
||||
a32048d44ee028b915565c3093ec5305e41aa6f1 not-for-merge 'refs/pull/231/head' of https://github.com/apple/swift-collections
|
||||
4448454fbc79b8052acc6b6e7eb6c75c70d1ee2f not-for-merge 'refs/pull/232/head' of https://github.com/apple/swift-collections
|
||||
14e86daeebe18bd32466a1f2bd2d8da936aa6508 not-for-merge 'refs/pull/233/head' of https://github.com/apple/swift-collections
|
||||
581490a7351be07e465100628ded472aaa137a99 not-for-merge 'refs/pull/234/head' of https://github.com/apple/swift-collections
|
||||
ff2d526c1baa53df478db47156bbdd68fcaed4df not-for-merge 'refs/pull/235/head' of https://github.com/apple/swift-collections
|
||||
98d519ec12ec6bc209ad61fed2e7e2101e312566 not-for-merge 'refs/pull/237/head' of https://github.com/apple/swift-collections
|
||||
339f1677450d7a8f43518d61cfd93be85fa080c3 not-for-merge 'refs/pull/238/head' of https://github.com/apple/swift-collections
|
||||
ff85ea9e4f1cf6fd50fb758cde3dedf01a742f52 not-for-merge 'refs/pull/240/head' of https://github.com/apple/swift-collections
|
||||
18c4f6dc5a771cd3f90ef3e7ae02a99e09e89115 not-for-merge 'refs/pull/241/head' of https://github.com/apple/swift-collections
|
||||
3d66da5f5baa3585aa4b5fe8f9d9eaaee5e5a6ef not-for-merge 'refs/pull/242/head' of https://github.com/apple/swift-collections
|
||||
2c33149e4e2cb9a5b2616cdbad9eabb5f51f0e0c not-for-merge 'refs/pull/243/head' of https://github.com/apple/swift-collections
|
||||
a2f4b18ae02cd14a8488c357c75fef3f2c2a9013 not-for-merge 'refs/pull/244/head' of https://github.com/apple/swift-collections
|
||||
69768b6eacd442681bc8424cc76516e7e24fdacc not-for-merge 'refs/pull/245/head' of https://github.com/apple/swift-collections
|
||||
f8252436e5e4384eaa1a68560db380d83b7c71eb not-for-merge 'refs/pull/246/head' of https://github.com/apple/swift-collections
|
||||
07032a92671dea282cbc935383dd3d5a0a598682 not-for-merge 'refs/pull/246/merge' of https://github.com/apple/swift-collections
|
||||
b8ed4950368d4d54cefd2b8bfe14c329e057172c not-for-merge 'refs/pull/247/head' of https://github.com/apple/swift-collections
|
||||
10a01bd9fb383668a987ec8f512da627dbe55f9e not-for-merge 'refs/pull/248/head' of https://github.com/apple/swift-collections
|
||||
470bf29d014757caae7222f3a41aea0b86b6ee1c not-for-merge 'refs/pull/249/head' of https://github.com/apple/swift-collections
|
||||
b43076ca7b46b8216590766fd446ae538ab91c5a not-for-merge 'refs/pull/25/head' of https://github.com/apple/swift-collections
|
||||
c0853ebef8dad7eddb6a44b76dac0f42f699b96a not-for-merge 'refs/pull/251/head' of https://github.com/apple/swift-collections
|
||||
089666b32ba82c06a166e072ebcdf988108b66b7 not-for-merge 'refs/pull/252/head' of https://github.com/apple/swift-collections
|
||||
fef38395004569688a967b88c70d8774c63f5fc5 not-for-merge 'refs/pull/254/head' of https://github.com/apple/swift-collections
|
||||
972578a44da6463eb8f88552cc7d30cf0b6de9a4 not-for-merge 'refs/pull/259/head' of https://github.com/apple/swift-collections
|
||||
0c2071ecda7a50dcdc8ec435a45b3b830b3e5bcf not-for-merge 'refs/pull/259/merge' of https://github.com/apple/swift-collections
|
||||
4e2f86b6cd24a124d69bf9257d2ffa751d11da8f not-for-merge 'refs/pull/26/head' of https://github.com/apple/swift-collections
|
||||
580beb4c121a85f60aaf6f10403e7f457c81ccb9 not-for-merge 'refs/pull/260/head' of https://github.com/apple/swift-collections
|
||||
5b4e4e032fc56ca77b888ca36b7a342e9932e5fa not-for-merge 'refs/pull/260/merge' of https://github.com/apple/swift-collections
|
||||
3e6df33472d54ed83dffe3bca7a3c8f65bab4c43 not-for-merge 'refs/pull/263/head' of https://github.com/apple/swift-collections
|
||||
fcd6800b9d1171fbe0a00f51a72afac32b0a1987 not-for-merge 'refs/pull/264/head' of https://github.com/apple/swift-collections
|
||||
5dc7a8970eabcf6aaa49529b5ef6401f5128637e not-for-merge 'refs/pull/265/head' of https://github.com/apple/swift-collections
|
||||
1666222de2200b2a614a0d5184751b8b6f7309b0 not-for-merge 'refs/pull/266/head' of https://github.com/apple/swift-collections
|
||||
e6ecdac581c3f03f442111b87655702e0664df67 not-for-merge 'refs/pull/267/head' of https://github.com/apple/swift-collections
|
||||
26de4aa094c87a9efd793f3ec37ec7facea24184 not-for-merge 'refs/pull/268/head' of https://github.com/apple/swift-collections
|
||||
73936bba69bd49e025aa8113fa81caa7f76ed571 not-for-merge 'refs/pull/269/head' of https://github.com/apple/swift-collections
|
||||
454c84b5e4253e462dac5472b853ee222ca93368 not-for-merge 'refs/pull/270/head' of https://github.com/apple/swift-collections
|
||||
9c3328e235e5f17c06328f021a5d11e7221690f5 not-for-merge 'refs/pull/271/head' of https://github.com/apple/swift-collections
|
||||
96d71628887275fc3010a0979cdebef15edde911 not-for-merge 'refs/pull/272/head' of https://github.com/apple/swift-collections
|
||||
4b6978bf8b220c9c7d03d1f8124d537fbbddc32a not-for-merge 'refs/pull/273/head' of https://github.com/apple/swift-collections
|
||||
7f63914a7161923e9af6889ed0f954de1ed4c7f0 not-for-merge 'refs/pull/275/head' of https://github.com/apple/swift-collections
|
||||
ac0c075ccc0fe2754a41dd777bb39507e73efe5b not-for-merge 'refs/pull/276/head' of https://github.com/apple/swift-collections
|
||||
a8dad62bc9c76f1f455a372c91759e7bb1e92e63 not-for-merge 'refs/pull/277/head' of https://github.com/apple/swift-collections
|
||||
99adbe97af48017fb51d884936f6bb87c27166c2 not-for-merge 'refs/pull/278/head' of https://github.com/apple/swift-collections
|
||||
b0fe7ca8bad02599faa6a308b561f71d4d5e3b4b not-for-merge 'refs/pull/279/head' of https://github.com/apple/swift-collections
|
||||
dce7b156e7276d44c3641f05bf675d90fea16523 not-for-merge 'refs/pull/280/head' of https://github.com/apple/swift-collections
|
||||
c4ad48826105dd299f45473784d22bf395b56863 not-for-merge 'refs/pull/281/head' of https://github.com/apple/swift-collections
|
||||
1f204555aa1678c0aa01cfba5836920acb8c5537 not-for-merge 'refs/pull/282/head' of https://github.com/apple/swift-collections
|
||||
992e0f3446b4f608f5ead9dd6edc92f6bbc0b0a0 not-for-merge 'refs/pull/283/head' of https://github.com/apple/swift-collections
|
||||
3f4d8f9912c9c3f5bacef6e6543b3f5b93168f65 not-for-merge 'refs/pull/284/head' of https://github.com/apple/swift-collections
|
||||
9befd06185369d287deee36f3d0de65f41edabb1 not-for-merge 'refs/pull/285/head' of https://github.com/apple/swift-collections
|
||||
0c002200bbee27acc8a663075da69120f666b4e5 not-for-merge 'refs/pull/286/head' of https://github.com/apple/swift-collections
|
||||
de0f59418503fc0c4866395751d930be3abbf17c not-for-merge 'refs/pull/287/head' of https://github.com/apple/swift-collections
|
||||
a5fda7c368e06561fba87dd33c47443e879dd6da not-for-merge 'refs/pull/288/head' of https://github.com/apple/swift-collections
|
||||
989bd7f2db6d9e7aa91881389359e369d621e3d9 not-for-merge 'refs/pull/29/head' of https://github.com/apple/swift-collections
|
||||
03c9ef743ad9de4eea816225afa2fc52490339cc not-for-merge 'refs/pull/290/head' of https://github.com/apple/swift-collections
|
||||
03e7f0c401e771f4a4c529eae4d3fde91f5bd355 not-for-merge 'refs/pull/291/head' of https://github.com/apple/swift-collections
|
||||
9c88dce30d213e1844ce60476e7d3eba2b1f1e60 not-for-merge 'refs/pull/292/head' of https://github.com/apple/swift-collections
|
||||
671cff0b3e579cbdad3a0818031063588d866ad2 not-for-merge 'refs/pull/296/head' of https://github.com/apple/swift-collections
|
||||
b3d089e37d0d4adc07bdbf1ecd14e9be3786bf25 not-for-merge 'refs/pull/297/head' of https://github.com/apple/swift-collections
|
||||
2f6606401781d32f3ffe3e245f2ba946acefe97e not-for-merge 'refs/pull/298/head' of https://github.com/apple/swift-collections
|
||||
8fbc1d318cf4c48931ffc6d204123284087fad0c not-for-merge 'refs/pull/299/head' of https://github.com/apple/swift-collections
|
||||
cf2cbd6ce39cbbdf7c60b76a8dca8e38b80486fc not-for-merge 'refs/pull/300/head' of https://github.com/apple/swift-collections
|
||||
09c09f0f734c006186df57595dc823159e0d49ef not-for-merge 'refs/pull/302/head' of https://github.com/apple/swift-collections
|
||||
a58628449c5e398433472b1bfd7e67e0acbe09fc not-for-merge 'refs/pull/303/head' of https://github.com/apple/swift-collections
|
||||
a82138e714dcd28ef5b7bacc4b708acc118e87ac not-for-merge 'refs/pull/304/head' of https://github.com/apple/swift-collections
|
||||
f15c276542595cb0f55368f8abf9f277e8eb51c9 not-for-merge 'refs/pull/304/merge' of https://github.com/apple/swift-collections
|
||||
1cf3b88cb3d237183cacd6482e4adaec48b17bb5 not-for-merge 'refs/pull/307/head' of https://github.com/apple/swift-collections
|
||||
ccd11e55dd4991055b260bb39d7e20ceb09046e9 not-for-merge 'refs/pull/31/head' of https://github.com/apple/swift-collections
|
||||
9efa05c583441159bd505dfde340cf774d6144e0 not-for-merge 'refs/pull/314/head' of https://github.com/apple/swift-collections
|
||||
bf742617f30870372ed235c6ccf4515ea0a204d3 not-for-merge 'refs/pull/315/head' of https://github.com/apple/swift-collections
|
||||
b6e227b9d779fe7405dc410812cb3aba6d2b529a not-for-merge 'refs/pull/316/head' of https://github.com/apple/swift-collections
|
||||
5c9ee680d20c4a758b0ffe06876fdca823f8068a not-for-merge 'refs/pull/316/merge' of https://github.com/apple/swift-collections
|
||||
de2c8a90865dcdbd97defe3c2c7396a2400e455a not-for-merge 'refs/pull/318/head' of https://github.com/apple/swift-collections
|
||||
bd1a62273592d5ad6ef388a70f53a61e33ffcba4 not-for-merge 'refs/pull/319/head' of https://github.com/apple/swift-collections
|
||||
171edb86e347f70d85ac593c139d26d6b4d3bbea not-for-merge 'refs/pull/32/head' of https://github.com/apple/swift-collections
|
||||
33f23b6a06f4a9f6b013fdef108cc1c82153afe4 not-for-merge 'refs/pull/320/head' of https://github.com/apple/swift-collections
|
||||
b67553e0c27857bbc5310f40cd6e68daa2d585de not-for-merge 'refs/pull/321/head' of https://github.com/apple/swift-collections
|
||||
b72a6cfd9384bc3ace8ea2412e79d5ec34c24934 not-for-merge 'refs/pull/322/head' of https://github.com/apple/swift-collections
|
||||
90b67c44eae7277d57e79e3c25c5dc72939a3b93 not-for-merge 'refs/pull/323/head' of https://github.com/apple/swift-collections
|
||||
19ec155f6089f6de453f8835aad46c09f5fd0b4d not-for-merge 'refs/pull/326/head' of https://github.com/apple/swift-collections
|
||||
069dd4e5df442e813eb30e3216aafa1cc1696a5f not-for-merge 'refs/pull/327/head' of https://github.com/apple/swift-collections
|
||||
53831b3a2264e24ca6c7ffcfe33c8653a72d51e1 not-for-merge 'refs/pull/328/head' of https://github.com/apple/swift-collections
|
||||
0b7ebf49775a8e5177eeaea6513083363a20e08c not-for-merge 'refs/pull/330/head' of https://github.com/apple/swift-collections
|
||||
3bd3d3ba28c6e72515e56b535b8a638144c12413 not-for-merge 'refs/pull/331/head' of https://github.com/apple/swift-collections
|
||||
cd03e5b471755b00aa948f7de950932c2c5a5d79 not-for-merge 'refs/pull/332/head' of https://github.com/apple/swift-collections
|
||||
e732790fde08a5e3d4f2347ac4a3e74399a5b457 not-for-merge 'refs/pull/333/head' of https://github.com/apple/swift-collections
|
||||
d2662892cd218eec7b56e505e4a343e5c676f02c not-for-merge 'refs/pull/335/head' of https://github.com/apple/swift-collections
|
||||
2bc657fad1def9519f88d851ef9e91bc01dc0e47 not-for-merge 'refs/pull/336/head' of https://github.com/apple/swift-collections
|
||||
6e91291cb24b777f0db29a6d50a728a2183ab660 not-for-merge 'refs/pull/337/head' of https://github.com/apple/swift-collections
|
||||
f9c400fb1c9bb8f2f76484b1a398135175d87a7f not-for-merge 'refs/pull/338/head' of https://github.com/apple/swift-collections
|
||||
071a1011d1f02ac96f92164b0313c429a159ad80 not-for-merge 'refs/pull/339/head' of https://github.com/apple/swift-collections
|
||||
85b00faba7071b5d7babb426bc06aa401ac8814d not-for-merge 'refs/pull/34/head' of https://github.com/apple/swift-collections
|
||||
525bb545c4c1f7dfe3ca461136c072af11cb6e4f not-for-merge 'refs/pull/340/head' of https://github.com/apple/swift-collections
|
||||
2122327782b71345cce48f23b688deebf582adc3 not-for-merge 'refs/pull/341/head' of https://github.com/apple/swift-collections
|
||||
40e737cdaf9341d821cba518ee990406fdcfd7e3 not-for-merge 'refs/pull/342/head' of https://github.com/apple/swift-collections
|
||||
8bfcaddd5fadea396620871451ca9ffc43b0985d not-for-merge 'refs/pull/343/head' of https://github.com/apple/swift-collections
|
||||
9d4a1e5ad279e6bc1c4230f90208b0886608a387 not-for-merge 'refs/pull/346/head' of https://github.com/apple/swift-collections
|
||||
cdcf9e606a12221e123a642353fbcfdc5d48bcf6 not-for-merge 'refs/pull/347/head' of https://github.com/apple/swift-collections
|
||||
1a0ac8c06c5a27f330a55a61464eaebc840d89d1 not-for-merge 'refs/pull/348/head' of https://github.com/apple/swift-collections
|
||||
258df0792818d6c331ccee923736ea234c24cf07 not-for-merge 'refs/pull/349/head' of https://github.com/apple/swift-collections
|
||||
3c9df19f7da674295f58f07f6dffa5d9e114fbc8 not-for-merge 'refs/pull/351/head' of https://github.com/apple/swift-collections
|
||||
c61e5e23c89b99d26aaaec6ec6c58bda1b502ebc not-for-merge 'refs/pull/352/head' of https://github.com/apple/swift-collections
|
||||
8dd4e591b3789ea14e8bd8cfde3ed81aa6edfefe not-for-merge 'refs/pull/353/head' of https://github.com/apple/swift-collections
|
||||
50f6307501712d87110f3f4d2e4959e84ace3bc8 not-for-merge 'refs/pull/354/head' of https://github.com/apple/swift-collections
|
||||
8e64f064f562a918993b147a3872e92c157e8e01 not-for-merge 'refs/pull/355/head' of https://github.com/apple/swift-collections
|
||||
ab744afc39dcd099948bfeb7fa4ac14f3f53dd36 not-for-merge 'refs/pull/356/head' of https://github.com/apple/swift-collections
|
||||
75395832459d3e7a05ec51ca2ea081fe99be5e8e not-for-merge 'refs/pull/357/head' of https://github.com/apple/swift-collections
|
||||
e004cd36fa3900c67d97f9944320a213e0d62c42 not-for-merge 'refs/pull/358/head' of https://github.com/apple/swift-collections
|
||||
f6380bb6608eb7d43c199b3d0ab2f932d300a338 not-for-merge 'refs/pull/36/head' of https://github.com/apple/swift-collections
|
||||
e424b487611d755ee5fe94271dd69677cc7688f0 not-for-merge 'refs/pull/360/head' of https://github.com/apple/swift-collections
|
||||
a45e90653a50d7cd8813775cbf3d4ae546db1479 not-for-merge 'refs/pull/361/head' of https://github.com/apple/swift-collections
|
||||
1e132acbb4f4aceea67ac8cdd5a4afdb1053e13d not-for-merge 'refs/pull/362/head' of https://github.com/apple/swift-collections
|
||||
09566acb3a06bcb80147555395ae564402a4013f not-for-merge 'refs/pull/367/head' of https://github.com/apple/swift-collections
|
||||
7425af3a9e29913aeb7cae881f9583f204ca5310 not-for-merge 'refs/pull/368/head' of https://github.com/apple/swift-collections
|
||||
e9112f40dd90d800c46adf88c7ad58653276bb5b not-for-merge 'refs/pull/370/head' of https://github.com/apple/swift-collections
|
||||
f46333d4a7c3a3f408131e268589203a68b84a09 not-for-merge 'refs/pull/371/head' of https://github.com/apple/swift-collections
|
||||
37feda1bb815269044e98991edf011dd713eda6a not-for-merge 'refs/pull/372/head' of https://github.com/apple/swift-collections
|
||||
ba5154b934dde320698eb31623e6c61eb63675e8 not-for-merge 'refs/pull/373/head' of https://github.com/apple/swift-collections
|
||||
e3954cdae4f9e97fbd7fd3ec1e80f01abbd6c06c not-for-merge 'refs/pull/375/head' of https://github.com/apple/swift-collections
|
||||
89b3ca0146f7371dd1008b0f6dd1d1452840deb2 not-for-merge 'refs/pull/377/head' of https://github.com/apple/swift-collections
|
||||
8d9e1e32484fa7fbbfe49df058fee41304c47213 not-for-merge 'refs/pull/378/head' of https://github.com/apple/swift-collections
|
||||
5d891350f44eecd7767b85259b1fd3068afe3c16 not-for-merge 'refs/pull/379/head' of https://github.com/apple/swift-collections
|
||||
d46a563351a5785e7ece59366fb80d1ffc21885c not-for-merge 'refs/pull/38/head' of https://github.com/apple/swift-collections
|
||||
ead6314a1cb17c2ecce50c80876f1998dcff6286 not-for-merge 'refs/pull/381/head' of https://github.com/apple/swift-collections
|
||||
35d5746117b42a556f81cff9fe016fdff8a6ddaa not-for-merge 'refs/pull/382/head' of https://github.com/apple/swift-collections
|
||||
a0b839d7de3278c5003836ad27d8ab75b994cbf5 not-for-merge 'refs/pull/384/head' of https://github.com/apple/swift-collections
|
||||
d10a328f79966ada76c0f5e1f13922363e1d7da9 not-for-merge 'refs/pull/385/head' of https://github.com/apple/swift-collections
|
||||
21264913c5162a74f58ef8af8d675417b188b8b9 not-for-merge 'refs/pull/386/head' of https://github.com/apple/swift-collections
|
||||
dbf90bd36bcfdd3659670e26259e1a1cf40b053a not-for-merge 'refs/pull/388/head' of https://github.com/apple/swift-collections
|
||||
5c2623b1a8d01d670455c739d07d94ba4f731f72 not-for-merge 'refs/pull/389/head' of https://github.com/apple/swift-collections
|
||||
7d18b37a95732fa58da3863efb4f8f142524abdb not-for-merge 'refs/pull/390/head' of https://github.com/apple/swift-collections
|
||||
094bf7ff2c87c735eb7ef41e1eeaedb41c8c0625 not-for-merge 'refs/pull/391/head' of https://github.com/apple/swift-collections
|
||||
16fcea238788bd5d298d96a199ffbbeea9f0845a not-for-merge 'refs/pull/392/head' of https://github.com/apple/swift-collections
|
||||
b7ccc7206cefa77e0139cd01af053895a5021fce not-for-merge 'refs/pull/393/head' of https://github.com/apple/swift-collections
|
||||
79e3fee891cf132262e66a192424cc5a5892c732 not-for-merge 'refs/pull/394/head' of https://github.com/apple/swift-collections
|
||||
7afbd7686e3ed22f4fff4f12721e944fb94c3476 not-for-merge 'refs/pull/394/merge' of https://github.com/apple/swift-collections
|
||||
36d53620b57f2c90b897525049d50d327f174edf not-for-merge 'refs/pull/395/head' of https://github.com/apple/swift-collections
|
||||
ce574378f856d15eec794157225005947534a6ca not-for-merge 'refs/pull/396/head' of https://github.com/apple/swift-collections
|
||||
99b025049e3fd4f1a791349716d7e3a6e6742ea7 not-for-merge 'refs/pull/397/head' of https://github.com/apple/swift-collections
|
||||
09f9340dcec6744e7238c0d966cad57e302a7419 not-for-merge 'refs/pull/398/head' of https://github.com/apple/swift-collections
|
||||
f049c7ae66996b3be81be9688aecc313fb62d2bd not-for-merge 'refs/pull/399/head' of https://github.com/apple/swift-collections
|
||||
3595ca05808ce018fb0fe6ca985a94d162cee300 not-for-merge 'refs/pull/4/head' of https://github.com/apple/swift-collections
|
||||
ec1893ac2372b7f596f4bdcff9b3fdbf1017dddc not-for-merge 'refs/pull/40/head' of https://github.com/apple/swift-collections
|
||||
105afd86fbc2a40752f4d522f7168c4f5c68f551 not-for-merge 'refs/pull/400/head' of https://github.com/apple/swift-collections
|
||||
3dd72d1c289e56fac76e5a5416c397da4946e98d not-for-merge 'refs/pull/401/head' of https://github.com/apple/swift-collections
|
||||
edb00bd980448f956a07b3d513f27fca32a1bb08 not-for-merge 'refs/pull/402/head' of https://github.com/apple/swift-collections
|
||||
cf241c3b6c32196768d825f961fc9b00e7e6b53f not-for-merge 'refs/pull/402/merge' of https://github.com/apple/swift-collections
|
||||
6b8276e2521d63ae1adc2cfd41d9e5a03e099ebe not-for-merge 'refs/pull/403/head' of https://github.com/apple/swift-collections
|
||||
6f4d9d856088be4b13c96717e45e94f902bb3fbd not-for-merge 'refs/pull/404/head' of https://github.com/apple/swift-collections
|
||||
5e1fe6e8f04e609273ee4fafe2fb77922ac2012f not-for-merge 'refs/pull/405/head' of https://github.com/apple/swift-collections
|
||||
93efdb9e4e967a0ad0cb735721b0a67447cd12b2 not-for-merge 'refs/pull/406/head' of https://github.com/apple/swift-collections
|
||||
effb33569a926c12dc8e7bae979ac2075c219189 not-for-merge 'refs/pull/408/head' of https://github.com/apple/swift-collections
|
||||
e14970493019b12d03046f2fdd01b76fd4f9fa3c not-for-merge 'refs/pull/409/head' of https://github.com/apple/swift-collections
|
||||
897b7c1a387e7afc2c95b4022c3b303137631c62 not-for-merge 'refs/pull/41/head' of https://github.com/apple/swift-collections
|
||||
5dd817c33df1a62776320437413ad7afbeaab414 not-for-merge 'refs/pull/410/head' of https://github.com/apple/swift-collections
|
||||
75aa5b075534ab11b77bc694f4c6d7cc29eab26f not-for-merge 'refs/pull/411/head' of https://github.com/apple/swift-collections
|
||||
0f138be4021524c1b9b8fa2dcd343876695b8101 not-for-merge 'refs/pull/414/head' of https://github.com/apple/swift-collections
|
||||
ca0c7a28b9b94243cac476dc4275db29f5d0be46 not-for-merge 'refs/pull/415/head' of https://github.com/apple/swift-collections
|
||||
0030b455f42d9a8588cb9791fdf9e62a4d0e401c not-for-merge 'refs/pull/417/head' of https://github.com/apple/swift-collections
|
||||
0030b455f42d9a8588cb9791fdf9e62a4d0e401c not-for-merge 'refs/pull/418/head' of https://github.com/apple/swift-collections
|
||||
7f49fa5164ce43bd1bfcdfe2b43b56cdf6845bd6 not-for-merge 'refs/pull/419/head' of https://github.com/apple/swift-collections
|
||||
ea4ab58dbc0a886c8a50752068de817ba1e49e81 not-for-merge 'refs/pull/42/head' of https://github.com/apple/swift-collections
|
||||
fec5a5a6302e3bd30b71cbb8a22706d417eb5e72 not-for-merge 'refs/pull/421/head' of https://github.com/apple/swift-collections
|
||||
a49afbe1be5e5d26f74b32d77057bf01ecee83bf not-for-merge 'refs/pull/422/head' of https://github.com/apple/swift-collections
|
||||
ccff1fbf71b315e0eee2ba2b46b82dda44fac55d not-for-merge 'refs/pull/423/head' of https://github.com/apple/swift-collections
|
||||
3f6522fef12acbebec4e425fec2a0d63a4bbac60 not-for-merge 'refs/pull/424/head' of https://github.com/apple/swift-collections
|
||||
b33922ed298ce150cd04d0ee330d0c85b3cee104 not-for-merge 'refs/pull/426/head' of https://github.com/apple/swift-collections
|
||||
84087c786e25744e47affbaae0b44415a973bdc9 not-for-merge 'refs/pull/427/head' of https://github.com/apple/swift-collections
|
||||
ebe01ea88769ec788cdcd91bdd9d24ae5ceb4f55 not-for-merge 'refs/pull/43/head' of https://github.com/apple/swift-collections
|
||||
2709b9694779797954b7bebb18764c2a85876e7e not-for-merge 'refs/pull/433/head' of https://github.com/apple/swift-collections
|
||||
98d345bd66496d36a1d62506d405e6d7b07e8cde not-for-merge 'refs/pull/436/head' of https://github.com/apple/swift-collections
|
||||
2d4df7d85dea6c6e81edb7a51de92c413318b6c9 not-for-merge 'refs/pull/438/head' of https://github.com/apple/swift-collections
|
||||
8d73c7cced4d9a8403e2353f02359844bd33b5b9 not-for-merge 'refs/pull/438/merge' of https://github.com/apple/swift-collections
|
||||
117c81053b70de031bac51b53288c001662c9305 not-for-merge 'refs/pull/44/head' of https://github.com/apple/swift-collections
|
||||
4450b7c62274bc08f21b94269e0316e2799afe90 not-for-merge 'refs/pull/445/head' of https://github.com/apple/swift-collections
|
||||
99db3179fcfab1add1a2418ed5f5392f25156aa0 not-for-merge 'refs/pull/446/head' of https://github.com/apple/swift-collections
|
||||
40adeb7fd7e86a3d84779a2c43c2211ae805b804 not-for-merge 'refs/pull/447/head' of https://github.com/apple/swift-collections
|
||||
1cb3ca50a63e8eac9dc503b3fba69ef56a99bce2 not-for-merge 'refs/pull/449/head' of https://github.com/apple/swift-collections
|
||||
0f73f0ace74ea44f39ab10f23a3d2c03afd54a8f not-for-merge 'refs/pull/450/head' of https://github.com/apple/swift-collections
|
||||
7ae9880f0fb622992a8a5328fd4af78af5b6b26f not-for-merge 'refs/pull/451/head' of https://github.com/apple/swift-collections
|
||||
c5ac12e2bc1ad8df1df0ee9d1236ab6366a2c32d not-for-merge 'refs/pull/452/head' of https://github.com/apple/swift-collections
|
||||
cfbebf4c80d0bc18609e7d603366f384dbdc8ef3 not-for-merge 'refs/pull/453/head' of https://github.com/apple/swift-collections
|
||||
dbc2866bb5f564d3be3fa5efdda769f2946ee968 not-for-merge 'refs/pull/454/head' of https://github.com/apple/swift-collections
|
||||
225159599d37106d63795d2df1bcbe0ccf7b3479 not-for-merge 'refs/pull/455/head' of https://github.com/apple/swift-collections
|
||||
25509c0b883738629b6a13c013b6274538112fbe not-for-merge 'refs/pull/456/head' of https://github.com/apple/swift-collections
|
||||
c42b4d1ebc5d198401f3efbcda36874b987e29d4 not-for-merge 'refs/pull/457/head' of https://github.com/apple/swift-collections
|
||||
fd9ee69e0ba4e389a5ecdd85822a0932b0496e3c not-for-merge 'refs/pull/458/head' of https://github.com/apple/swift-collections
|
||||
769bc7b07c3b986d928540d74d53bdd3d73f4374 not-for-merge 'refs/pull/459/head' of https://github.com/apple/swift-collections
|
||||
ca939f84e132eb64a44db49c8092c8ec261b3092 not-for-merge 'refs/pull/46/head' of https://github.com/apple/swift-collections
|
||||
75837a77174c0dd3243a599fae8c1675c64860d1 not-for-merge 'refs/pull/460/head' of https://github.com/apple/swift-collections
|
||||
3fffe2ad2062eabe93dddb4d2e37bffe9bf278dc not-for-merge 'refs/pull/461/head' of https://github.com/apple/swift-collections
|
||||
fea1d24e7be3284646858ef7bc9950f685adaa61 not-for-merge 'refs/pull/462/head' of https://github.com/apple/swift-collections
|
||||
b765db28be0063341ef9048a8c4f6efb8b0e4cbd not-for-merge 'refs/pull/463/head' of https://github.com/apple/swift-collections
|
||||
6385ebbe4d5fd7235dca833a4b041b14f06d46cf not-for-merge 'refs/pull/464/head' of https://github.com/apple/swift-collections
|
||||
7ec497fb53a8d0a680576f1e0b0781fb71c99429 not-for-merge 'refs/pull/47/head' of https://github.com/apple/swift-collections
|
||||
a7fec81fc4c4af5e49d2ce19f3b39ef51202fd22 not-for-merge 'refs/pull/470/head' of https://github.com/apple/swift-collections
|
||||
117a1aad2d8194b8632bb46483573bb0b7aa50f1 not-for-merge 'refs/pull/471/head' of https://github.com/apple/swift-collections
|
||||
0bd8dec08b8bb484f4a39e8d241a40c8e0c8a051 not-for-merge 'refs/pull/472/head' of https://github.com/apple/swift-collections
|
||||
d5f3b81e690242c750deb4ede721539250297bd6 not-for-merge 'refs/pull/473/head' of https://github.com/apple/swift-collections
|
||||
c25a388c1375c634d42a6f5608a863a4b6aace2c not-for-merge 'refs/pull/474/head' of https://github.com/apple/swift-collections
|
||||
a09d7cdf458769f6f9586a2782b03d624d710428 not-for-merge 'refs/pull/475/head' of https://github.com/apple/swift-collections
|
||||
e1be57c0f55f90d9489773dec69449bd86fce692 not-for-merge 'refs/pull/476/head' of https://github.com/apple/swift-collections
|
||||
1812091001b264fc9b0db6a4b847ef9b330f5fd4 not-for-merge 'refs/pull/478/head' of https://github.com/apple/swift-collections
|
||||
e337c2b936320f538fc8b9e8b66d51bff56646e4 not-for-merge 'refs/pull/479/head' of https://github.com/apple/swift-collections
|
||||
137bd464c14792cadc721d90afd412c2e7735424 not-for-merge 'refs/pull/48/head' of https://github.com/apple/swift-collections
|
||||
6819c6d1491caf6819649a0635d35956700cd165 not-for-merge 'refs/pull/480/head' of https://github.com/apple/swift-collections
|
||||
c50c57f52eaae3f241dd3a4338d05f199d0bd94d not-for-merge 'refs/pull/481/head' of https://github.com/apple/swift-collections
|
||||
83457e19c8b17548bf30f43bdfe7563cc6621633 not-for-merge 'refs/pull/482/head' of https://github.com/apple/swift-collections
|
||||
d5568ee899f3b9487cf752cb28027910f84aad46 not-for-merge 'refs/pull/483/head' of https://github.com/apple/swift-collections
|
||||
65f99e3eff346e5033d9ac9310021a4ff55a9a64 not-for-merge 'refs/pull/485/head' of https://github.com/apple/swift-collections
|
||||
fc411858ee8c2d1ca4113555c185752f5d8212f5 not-for-merge 'refs/pull/486/head' of https://github.com/apple/swift-collections
|
||||
05ad8633a8d6e407bd9dfce36da47b3fe36b3da2 not-for-merge 'refs/pull/487/head' of https://github.com/apple/swift-collections
|
||||
a1f8f33a5b5ae60c6bdad045176e3fc96427a0a5 not-for-merge 'refs/pull/488/head' of https://github.com/apple/swift-collections
|
||||
3fe754c0804d97b446a8ca70b3e4aa8d9c17c831 not-for-merge 'refs/pull/49/head' of https://github.com/apple/swift-collections
|
||||
2d5ed365ff0a9d7c7bf9a84e8ac0692b80caed92 not-for-merge 'refs/pull/490/head' of https://github.com/apple/swift-collections
|
||||
9f68408a70172d6c4ce3ba4e3a7528f489629e43 not-for-merge 'refs/pull/491/head' of https://github.com/apple/swift-collections
|
||||
2fe5c4a31d9e599dfb55d21a02b8f9b74c5b3165 not-for-merge 'refs/pull/492/head' of https://github.com/apple/swift-collections
|
||||
1f8dcd4726717a4b724e5408ca24829bdef67a49 not-for-merge 'refs/pull/493/head' of https://github.com/apple/swift-collections
|
||||
c883a1729ac36de8cfc30729dd9650a98ce5c5a3 not-for-merge 'refs/pull/494/head' of https://github.com/apple/swift-collections
|
||||
f44eabc30ee11beb77577f4c059bc6cf1643885b not-for-merge 'refs/pull/495/head' of https://github.com/apple/swift-collections
|
||||
ab46d6415275a4f1c66923aad5d9759394b9999f not-for-merge 'refs/pull/496/head' of https://github.com/apple/swift-collections
|
||||
31183bf059d3d1698d2b5e10a17bfb892a57876b not-for-merge 'refs/pull/497/head' of https://github.com/apple/swift-collections
|
||||
b33592ebce263de67a30234f5952833e58f519f8 not-for-merge 'refs/pull/498/head' of https://github.com/apple/swift-collections
|
||||
efac873c1357fd397b246e601021930c2a1561b9 not-for-merge 'refs/pull/499/head' of https://github.com/apple/swift-collections
|
||||
efac873c1357fd397b246e601021930c2a1561b9 not-for-merge 'refs/pull/500/head' of https://github.com/apple/swift-collections
|
||||
f6256df2628c6dc9b8637a81c9ce3bd9354b4df5 not-for-merge 'refs/pull/501/head' of https://github.com/apple/swift-collections
|
||||
a98fbaba8b4236b1f98a9a4ee8269f5beb054425 not-for-merge 'refs/pull/502/head' of https://github.com/apple/swift-collections
|
||||
8db0c6eb7539e9e73dce1a74be02093f531c8c60 not-for-merge 'refs/pull/503/head' of https://github.com/apple/swift-collections
|
||||
890f33b56a7c03f5d8c680b5b566b07669adf6fb not-for-merge 'refs/pull/504/head' of https://github.com/apple/swift-collections
|
||||
16f8d5b6bf91315e87e3922d2acae52d38c6bfe1 not-for-merge 'refs/pull/505/head' of https://github.com/apple/swift-collections
|
||||
4ea19dd03e4c9632ee09a94f32f18a12df02da9e not-for-merge 'refs/pull/506/head' of https://github.com/apple/swift-collections
|
||||
21757b6add20f67be68cad7c3b36e3ef3ec6875a not-for-merge 'refs/pull/507/head' of https://github.com/apple/swift-collections
|
||||
5cd51978a44752b0432329904e72fe3ffbe22523 not-for-merge 'refs/pull/508/head' of https://github.com/apple/swift-collections
|
||||
5f92d48d0d590f68340a9a6acdf0c7ae9638bb7e not-for-merge 'refs/pull/509/head' of https://github.com/apple/swift-collections
|
||||
dff2b1783badd696c3135abd8e26c3b7ad2e67fd not-for-merge 'refs/pull/51/head' of https://github.com/apple/swift-collections
|
||||
434d30dae30fbb57699370260c69c2108c1abf8f not-for-merge 'refs/pull/512/head' of https://github.com/apple/swift-collections
|
||||
fb75c41e703f7ddaf22edfce3488c888cbb3136e not-for-merge 'refs/pull/512/merge' of https://github.com/apple/swift-collections
|
||||
43367db377713ef76db6e16df128a96a7db5a805 not-for-merge 'refs/pull/513/head' of https://github.com/apple/swift-collections
|
||||
50a9c6c655766bcbabac0453a5dce8cddd3e8cf7 not-for-merge 'refs/pull/514/head' of https://github.com/apple/swift-collections
|
||||
101bac2d30cce81a24eb2b223aa64d928ca6598d not-for-merge 'refs/pull/515/head' of https://github.com/apple/swift-collections
|
||||
6340fa0e9b818a19be3982951106ec6071075843 not-for-merge 'refs/pull/516/head' of https://github.com/apple/swift-collections
|
||||
90934a152b26db2cacafaf26c0f85261815f2344 not-for-merge 'refs/pull/517/head' of https://github.com/apple/swift-collections
|
||||
3fe1bb8561a92c45a56afb6dc3af95755cc2273c not-for-merge 'refs/pull/519/head' of https://github.com/apple/swift-collections
|
||||
42e6045ca1307cdd5b13a69aef57336abb7ea486 not-for-merge 'refs/pull/519/merge' of https://github.com/apple/swift-collections
|
||||
5e6b95649be69c3e9d6c326f2a7c2ba88c25f460 not-for-merge 'refs/pull/52/head' of https://github.com/apple/swift-collections
|
||||
377d2a55a8b9506d56d4eedefe26565240b208f0 not-for-merge 'refs/pull/520/head' of https://github.com/apple/swift-collections
|
||||
4cc6cad50849690b2c551f306265509d7168730b not-for-merge 'refs/pull/521/head' of https://github.com/apple/swift-collections
|
||||
b88e7d0b00bcd6721cc0b11ac2b948a32a9c444d not-for-merge 'refs/pull/522/head' of https://github.com/apple/swift-collections
|
||||
f4d851a739f6f1cfd0364b1c1ceb9aadd1b07f2f not-for-merge 'refs/pull/523/head' of https://github.com/apple/swift-collections
|
||||
68eca941248011fdc278bd752f39fbd3f62e46c7 not-for-merge 'refs/pull/524/head' of https://github.com/apple/swift-collections
|
||||
ccb60599696d69e9744224367ca927e6ba3f74b3 not-for-merge 'refs/pull/525/head' of https://github.com/apple/swift-collections
|
||||
bb8d56683375160bdcc35d0ca7dcf06bb875bece not-for-merge 'refs/pull/526/head' of https://github.com/apple/swift-collections
|
||||
ab7ca1353732f13ba1b24f4b95efe3dc148a0a73 not-for-merge 'refs/pull/527/head' of https://github.com/apple/swift-collections
|
||||
f9669dc4186220345d8a856550386492aae74e5c not-for-merge 'refs/pull/528/head' of https://github.com/apple/swift-collections
|
||||
b0f915ac6981dc529e3aa27bfe13b93c067da83e not-for-merge 'refs/pull/529/head' of https://github.com/apple/swift-collections
|
||||
cf2685d6213f8966f3e453d66aa51c5f993cb514 not-for-merge 'refs/pull/529/merge' of https://github.com/apple/swift-collections
|
||||
4432aa8d79607328e6e96ae2a89f878ea58b27fe not-for-merge 'refs/pull/53/head' of https://github.com/apple/swift-collections
|
||||
fa45e0e0cc63150df8ff27c49a8385f1f989d2fb not-for-merge 'refs/pull/530/head' of https://github.com/apple/swift-collections
|
||||
a2a4bbd3dcd04b7ec7fc84258c1732298fb95d60 not-for-merge 'refs/pull/530/merge' of https://github.com/apple/swift-collections
|
||||
ea71bf2ce9a4420dc5716b94c0e02032ef3b0486 not-for-merge 'refs/pull/531/head' of https://github.com/apple/swift-collections
|
||||
347825dd43e9c7f3b346aff777ae4a0cffe93ea0 not-for-merge 'refs/pull/532/head' of https://github.com/apple/swift-collections
|
||||
ab649ca5fc756ed6b3b290662fb273460c4a038b not-for-merge 'refs/pull/533/head' of https://github.com/apple/swift-collections
|
||||
a7e40d20551cab8bdf753c9ea809f80443903290 not-for-merge 'refs/pull/534/head' of https://github.com/apple/swift-collections
|
||||
55130cecb0b8eb39da9c281e9124168d1068079e not-for-merge 'refs/pull/535/head' of https://github.com/apple/swift-collections
|
||||
e5e653088cb61fae41189623b208cb100624b0d8 not-for-merge 'refs/pull/535/merge' of https://github.com/apple/swift-collections
|
||||
fa408c9e853e04971c32351bab2e2200c4e07349 not-for-merge 'refs/pull/536/head' of https://github.com/apple/swift-collections
|
||||
f2b51f49978351bc6225aec3cb18a916b0c4245a not-for-merge 'refs/pull/536/merge' of https://github.com/apple/swift-collections
|
||||
65d174cc77577c972ed34fa03efa8c982c72f0ac not-for-merge 'refs/pull/537/head' of https://github.com/apple/swift-collections
|
||||
e2e2d0088182c22f26a007d3ea4fdb3497cc830a not-for-merge 'refs/pull/538/head' of https://github.com/apple/swift-collections
|
||||
0cf0071c1db25a01454339aa1dac6f8c984f8244 not-for-merge 'refs/pull/538/merge' of https://github.com/apple/swift-collections
|
||||
691855a60fca67d1176bbca0871ce9beb9170bbb not-for-merge 'refs/pull/539/head' of https://github.com/apple/swift-collections
|
||||
788c17c16b5bc88466d1a0a96f0bf7eaef8b9352 not-for-merge 'refs/pull/54/head' of https://github.com/apple/swift-collections
|
||||
8b3d2878dea8451badb5b66094e7b4d0e4d1c658 not-for-merge 'refs/pull/540/head' of https://github.com/apple/swift-collections
|
||||
ddff9004d745c4b2d13e35ebdd1a3d0b67e14717 not-for-merge 'refs/pull/541/head' of https://github.com/apple/swift-collections
|
||||
5e091e541bc88b91fc750bb908aab665a4f13334 not-for-merge 'refs/pull/541/merge' of https://github.com/apple/swift-collections
|
||||
1d63cdd629a5fc9e2b15a25b667f804d872f9e47 not-for-merge 'refs/pull/542/head' of https://github.com/apple/swift-collections
|
||||
a617f5e2b1e7bee60846a2033645f28015990d2b not-for-merge 'refs/pull/543/head' of https://github.com/apple/swift-collections
|
||||
92baa3289dee72e28b5add8cfd88c3a909d68f17 not-for-merge 'refs/pull/545/head' of https://github.com/apple/swift-collections
|
||||
cf642a237ea2c2c0e345fdb856e203d418aedc81 not-for-merge 'refs/pull/545/merge' of https://github.com/apple/swift-collections
|
||||
347825dd43e9c7f3b346aff777ae4a0cffe93ea0 not-for-merge 'refs/pull/547/head' of https://github.com/apple/swift-collections
|
||||
2b5cbd54cf8d59e4780dad338b31cf31c3ea4aa8 not-for-merge 'refs/pull/547/merge' of https://github.com/apple/swift-collections
|
||||
68c32ed80b138d1f8a6ec5dcf1b105f32fcaaf12 not-for-merge 'refs/pull/548/head' of https://github.com/apple/swift-collections
|
||||
c35ca292f71bd0c2d7eb37e1dbac9318fae5bb68 not-for-merge 'refs/pull/548/merge' of https://github.com/apple/swift-collections
|
||||
ad176827391e97cc1a919f38f3f6af655184facb not-for-merge 'refs/pull/549/head' of https://github.com/apple/swift-collections
|
||||
ff76bbdc775050687a8495f75122faa8fef37d84 not-for-merge 'refs/pull/55/head' of https://github.com/apple/swift-collections
|
||||
353496019475df6047027998d1cf69505fef172f not-for-merge 'refs/pull/550/head' of https://github.com/apple/swift-collections
|
||||
7f8a32c5a9c9b07f57ebef314a5a289c7eb51021 not-for-merge 'refs/pull/551/head' of https://github.com/apple/swift-collections
|
||||
a0e7df98638abbdaa452dc08b929538bda94ae18 not-for-merge 'refs/pull/552/head' of https://github.com/apple/swift-collections
|
||||
174b3135c3a20094b65edb2e2c4e3e1c13693d58 not-for-merge 'refs/pull/553/head' of https://github.com/apple/swift-collections
|
||||
c5d5d97c43f38162bb49fef37149ea6c4a136c50 not-for-merge 'refs/pull/554/head' of https://github.com/apple/swift-collections
|
||||
7c926083822b8eea2c51cf6c6f425b9101b5d2bf not-for-merge 'refs/pull/556/head' of https://github.com/apple/swift-collections
|
||||
b36804e15608a070213059cf803cc353ef88263a not-for-merge 'refs/pull/556/merge' of https://github.com/apple/swift-collections
|
||||
80b8a6fb80ebb1ce7f5e918027b77a99fc57759c not-for-merge 'refs/pull/557/head' of https://github.com/apple/swift-collections
|
||||
6274c2a3b1ed55f5227f54b37c1437b74a060b3c not-for-merge 'refs/pull/558/head' of https://github.com/apple/swift-collections
|
||||
81514112d770a2ceeddcbba2207204661f40c650 not-for-merge 'refs/pull/558/merge' of https://github.com/apple/swift-collections
|
||||
fdaf3fe24c72ac54998e4d2361aaa5d9fedd12b5 not-for-merge 'refs/pull/560/head' of https://github.com/apple/swift-collections
|
||||
59bb505b1a18e05342fd58d873a967b484f2f268 not-for-merge 'refs/pull/562/head' of https://github.com/apple/swift-collections
|
||||
de54709ca9dffef94ee4f1b04f6a6483d620d1a3 not-for-merge 'refs/pull/563/head' of https://github.com/apple/swift-collections
|
||||
d1efcb19db72befae31841116b43586350a60a72 not-for-merge 'refs/pull/565/head' of https://github.com/apple/swift-collections
|
||||
b7d2cf8908b42f35b5a3929e18ab63d3a321a3a1 not-for-merge 'refs/pull/58/head' of https://github.com/apple/swift-collections
|
||||
956ea437dfdfcc6b431315fe54a9388271f5b512 not-for-merge 'refs/pull/6/head' of https://github.com/apple/swift-collections
|
||||
175e1eb6b3395e3808218e72910235658819bdc5 not-for-merge 'refs/pull/60/head' of https://github.com/apple/swift-collections
|
||||
083102e1e2bad3bfc869f3072f134fc48a401550 not-for-merge 'refs/pull/61/head' of https://github.com/apple/swift-collections
|
||||
0b963fe790c694a35c34b2b31caa84a681f74945 not-for-merge 'refs/pull/62/head' of https://github.com/apple/swift-collections
|
||||
cfe64fa1f270ff99ae4c5bf36502656d5c77596f not-for-merge 'refs/pull/63/head' of https://github.com/apple/swift-collections
|
||||
787c4fac1492d4d877127ccf086195b5051b5c01 not-for-merge 'refs/pull/64/head' of https://github.com/apple/swift-collections
|
||||
478d3cc73fe173775883d35a2b0a073567da3b4b not-for-merge 'refs/pull/65/head' of https://github.com/apple/swift-collections
|
||||
2a60245369a3e88485ed4f8c92ca5c378ce77c06 not-for-merge 'refs/pull/76/head' of https://github.com/apple/swift-collections
|
||||
b70b6fec29949244914e7501725deb52370da0b0 not-for-merge 'refs/pull/77/head' of https://github.com/apple/swift-collections
|
||||
303e1990d6317fc39c5c072483d18e4f0235db60 not-for-merge 'refs/pull/78/head' of https://github.com/apple/swift-collections
|
||||
cfaab9a73140595755a5bcc138c45ad817dc4f44 not-for-merge 'refs/pull/79/head' of https://github.com/apple/swift-collections
|
||||
8de85365808b3d984148d0adb5dc36125a71c36f not-for-merge 'refs/pull/8/head' of https://github.com/apple/swift-collections
|
||||
976a8c276338a00a436f620f9cb8d3c0f74f6d81 not-for-merge 'refs/pull/80/head' of https://github.com/apple/swift-collections
|
||||
1146f2644c44ff629c5dfc8f5588d6d4cc734a22 not-for-merge 'refs/pull/80/merge' of https://github.com/apple/swift-collections
|
||||
07134a5bce472917a2fc2f2a19401861a688530b not-for-merge 'refs/pull/81/head' of https://github.com/apple/swift-collections
|
||||
3d4aca47308287244f2dd7b9c2085dea63c27b60 not-for-merge 'refs/pull/82/head' of https://github.com/apple/swift-collections
|
||||
140a1752fdfa9788db9e5b23ee32d8bdbed4c9f7 not-for-merge 'refs/pull/83/head' of https://github.com/apple/swift-collections
|
||||
40ab3405b25719a490abea591d80b7ce27ab8803 not-for-merge 'refs/pull/84/head' of https://github.com/apple/swift-collections
|
||||
52f77c4486ea96a3c5ed373932ee0220d5a7ebee not-for-merge 'refs/pull/85/head' of https://github.com/apple/swift-collections
|
||||
029dd258a1d19cbcd8e22523b0811c7dcb6d450a not-for-merge 'refs/pull/86/head' of https://github.com/apple/swift-collections
|
||||
8ef7b779cd17e95baeef138a612c48b063036aca not-for-merge 'refs/pull/87/head' of https://github.com/apple/swift-collections
|
||||
ace0073826e3e2bdc1b08d78e6fe6f1efc700aab not-for-merge 'refs/pull/9/head' of https://github.com/apple/swift-collections
|
||||
e78605942c7fb08c3e8812a166e85bcae2ddd15e not-for-merge 'refs/pull/91/head' of https://github.com/apple/swift-collections
|
||||
7c68b05ed94391100c1933770cd18e95533bd53d not-for-merge 'refs/pull/92/head' of https://github.com/apple/swift-collections
|
||||
d6774be62f7f857f0b30dae49a3a6f02b58e5679 not-for-merge 'refs/pull/93/head' of https://github.com/apple/swift-collections
|
||||
6192ad1fc8795b647f8fb9eec20257ae2cb4716d not-for-merge 'refs/pull/95/head' of https://github.com/apple/swift-collections
|
||||
dcdd7ebabbdcac6442e45db68f6e3d10b96f0c88 not-for-merge 'refs/pull/96/head' of https://github.com/apple/swift-collections
|
||||
41bfaaae0af3809b808405df0fab4a5e02ddd206 not-for-merge 'refs/pull/97/head' of https://github.com/apple/swift-collections
|
||||
462fb1d3fc318f4e1f81d6945b87f1dc32dd8079 not-for-merge 'refs/pull/98/head' of https://github.com/apple/swift-collections
|
||||
c1c9541a3b91ec076076ad8e9a4e28a00b80cb6b not-for-merge 'refs/pull/99/head' of https://github.com/apple/swift-collections
|
||||
bd924007a25488900d2e3f3437a0388a97636020 not-for-merge tag '0.0.1' of https://github.com/apple/swift-collections
|
||||
2d719d75a2065f213e58a5164384a3d2fcf9b59a not-for-merge tag '0.0.2' of https://github.com/apple/swift-collections
|
||||
d45e63421d3dff834949ac69d3c37691e994bd69 not-for-merge tag '0.0.3' of https://github.com/apple/swift-collections
|
||||
3426dba9ee5c9f8e4981b0fc9d39a818d36eec28 not-for-merge tag '0.0.4' of https://github.com/apple/swift-collections
|
||||
0959ba76a1d4a98fd11163aa83fd49c25b93bfae not-for-merge tag '0.0.5' of https://github.com/apple/swift-collections
|
||||
9d8719c8bebdc79740b6969c912ac706eb721d7a not-for-merge tag '0.0.7' of https://github.com/apple/swift-collections
|
||||
07e47b1e93e5a1e0ef0c50fcb2d6739fb6be4003 not-for-merge tag '1.0.0' of https://github.com/apple/swift-collections
|
||||
2d33a0ea89c961dcb2b3da2157963d9c0370347e not-for-merge tag '1.0.1' of https://github.com/apple/swift-collections
|
||||
48254824bb4248676bf7ce56014ff57b142b77eb not-for-merge tag '1.0.2' of https://github.com/apple/swift-collections
|
||||
f504716c27d2e5d4144fa4794b12129301d17729 not-for-merge tag '1.0.3' of https://github.com/apple/swift-collections
|
||||
937e904258d22af6e447a0b72c0bc67583ef64a2 not-for-merge tag '1.0.4' of https://github.com/apple/swift-collections
|
||||
a902f1823a7ff3c9ab2fba0f992396b948eda307 not-for-merge tag '1.0.5' of https://github.com/apple/swift-collections
|
||||
d029d9d39c87bed85b1c50adee7c41795261a192 not-for-merge tag '1.0.6' of https://github.com/apple/swift-collections
|
||||
94cf62b3ba8d4bed62680a282d4c25f9c63c2efb not-for-merge tag '1.1.0' of https://github.com/apple/swift-collections
|
||||
ee97538f5b81ae89698fd95938896dec5217b148 not-for-merge tag '1.1.1' of https://github.com/apple/swift-collections
|
||||
3d2dc41a01f9e49d84f0a3925fb858bed64f702d not-for-merge tag '1.1.2' of https://github.com/apple/swift-collections
|
||||
9bf03ff58ce34478e66aaee630e491823326fd06 not-for-merge tag '1.1.3' of https://github.com/apple/swift-collections
|
||||
671108c96644956dddcd89dd59c203dcdb36cec7 not-for-merge tag '1.1.4' of https://github.com/apple/swift-collections
|
||||
ad9f6723fd29591e6c0a19a9c4982cae51d65b1d not-for-merge tag '1.1.5' of https://github.com/apple/swift-collections
|
||||
c11818f3cae0780656baa430b49e7f163f08dffd not-for-merge tag '1.1.6' of https://github.com/apple/swift-collections
|
||||
c1805596154bb3a265fd91b8ac0c4433b4348fb0 not-for-merge tag '1.2.0' of https://github.com/apple/swift-collections
|
||||
8c0c0a8b49e080e54e5e328cc552821ff07cd341 not-for-merge tag '1.2.1' of https://github.com/apple/swift-collections
|
||||
7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e not-for-merge tag '1.3.0' of https://github.com/apple/swift-collections
|
||||
1
_spm/repositories/swift-collections-9a58d5cf/HEAD
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/heads/main
|
||||
10
_spm/repositories/swift-collections-9a58d5cf/config
Normal file
@@ -0,0 +1,10 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[remote "origin"]
|
||||
url = https://github.com/apple/swift-collections.git
|
||||
fetch = +refs/*:refs/*
|
||||
mirror = true
|
||||
1
_spm/repositories/swift-collections-9a58d5cf/description
Normal file
@@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
15
_spm/repositories/swift-collections-9a58d5cf/hooks/applypatch-msg.sample
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message taken by
|
||||
# applypatch from an e-mail message.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an
|
||||
# appropriate message if it wants to stop the commit. The hook is
|
||||
# allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "applypatch-msg".
|
||||
|
||||
. git-sh-setup
|
||||
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
|
||||
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
|
||||
:
|
||||
24
_spm/repositories/swift-collections-9a58d5cf/hooks/commit-msg.sample
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message.
|
||||
# Called by "git commit" with one argument, the name of the file
|
||||
# that has the commit message. The hook should exit with non-zero
|
||||
# status after issuing an appropriate message if it wants to stop the
|
||||
# commit. The hook is allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "commit-msg".
|
||||
|
||||
# Uncomment the below to add a Signed-off-by line to the message.
|
||||
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
|
||||
# hook is more suited to it.
|
||||
#
|
||||
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
|
||||
|
||||
# This example catches duplicate Signed-off-by lines.
|
||||
|
||||
test "" = "$(grep '^Signed-off-by: ' "$1" |
|
||||
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
|
||||
echo >&2 Duplicate Signed-off-by lines.
|
||||
exit 1
|
||||
}
|
||||
174
_spm/repositories/swift-collections-9a58d5cf/hooks/fsmonitor-watchman.sample
Executable file
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IPC::Open2;
|
||||
|
||||
# An example hook script to integrate Watchman
|
||||
# (https://facebook.github.io/watchman/) with git to speed up detecting
|
||||
# new and modified files.
|
||||
#
|
||||
# The hook is passed a version (currently 2) and last update token
|
||||
# formatted as a string and outputs to stdout a new update token and
|
||||
# all files that have been modified since the update token. Paths must
|
||||
# be relative to the root of the working tree and separated by a single NUL.
|
||||
#
|
||||
# To enable this hook, rename this file to "query-watchman" and set
|
||||
# 'git config core.fsmonitor .git/hooks/query-watchman'
|
||||
#
|
||||
my ($version, $last_update_token) = @ARGV;
|
||||
|
||||
# Uncomment for debugging
|
||||
# print STDERR "$0 $version $last_update_token\n";
|
||||
|
||||
# Check the hook interface version
|
||||
if ($version ne 2) {
|
||||
die "Unsupported query-fsmonitor hook version '$version'.\n" .
|
||||
"Falling back to scanning...\n";
|
||||
}
|
||||
|
||||
my $git_work_tree = get_working_dir();
|
||||
|
||||
my $retry = 1;
|
||||
|
||||
my $json_pkg;
|
||||
eval {
|
||||
require JSON::XS;
|
||||
$json_pkg = "JSON::XS";
|
||||
1;
|
||||
} or do {
|
||||
require JSON::PP;
|
||||
$json_pkg = "JSON::PP";
|
||||
};
|
||||
|
||||
launch_watchman();
|
||||
|
||||
sub launch_watchman {
|
||||
my $o = watchman_query();
|
||||
if (is_work_tree_watched($o)) {
|
||||
output_result($o->{clock}, @{$o->{files}});
|
||||
}
|
||||
}
|
||||
|
||||
sub output_result {
|
||||
my ($clockid, @files) = @_;
|
||||
|
||||
# Uncomment for debugging watchman output
|
||||
# open (my $fh, ">", ".git/watchman-output.out");
|
||||
# binmode $fh, ":utf8";
|
||||
# print $fh "$clockid\n@files\n";
|
||||
# close $fh;
|
||||
|
||||
binmode STDOUT, ":utf8";
|
||||
print $clockid;
|
||||
print "\0";
|
||||
local $, = "\0";
|
||||
print @files;
|
||||
}
|
||||
|
||||
sub watchman_clock {
|
||||
my $response = qx/watchman clock "$git_work_tree"/;
|
||||
die "Failed to get clock id on '$git_work_tree'.\n" .
|
||||
"Falling back to scanning...\n" if $? != 0;
|
||||
|
||||
return $json_pkg->new->utf8->decode($response);
|
||||
}
|
||||
|
||||
sub watchman_query {
|
||||
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
|
||||
or die "open2() failed: $!\n" .
|
||||
"Falling back to scanning...\n";
|
||||
|
||||
# In the query expression below we're asking for names of files that
|
||||
# changed since $last_update_token but not from the .git folder.
|
||||
#
|
||||
# To accomplish this, we're using the "since" generator to use the
|
||||
# recency index to select candidate nodes and "fields" to limit the
|
||||
# output to file names only. Then we're using the "expression" term to
|
||||
# further constrain the results.
|
||||
my $last_update_line = "";
|
||||
if (substr($last_update_token, 0, 1) eq "c") {
|
||||
$last_update_token = "\"$last_update_token\"";
|
||||
$last_update_line = qq[\n"since": $last_update_token,];
|
||||
}
|
||||
my $query = <<" END";
|
||||
["query", "$git_work_tree", {$last_update_line
|
||||
"fields": ["name"],
|
||||
"expression": ["not", ["dirname", ".git"]]
|
||||
}]
|
||||
END
|
||||
|
||||
# Uncomment for debugging the watchman query
|
||||
# open (my $fh, ">", ".git/watchman-query.json");
|
||||
# print $fh $query;
|
||||
# close $fh;
|
||||
|
||||
print CHLD_IN $query;
|
||||
close CHLD_IN;
|
||||
my $response = do {local $/; <CHLD_OUT>};
|
||||
|
||||
# Uncomment for debugging the watch response
|
||||
# open ($fh, ">", ".git/watchman-response.json");
|
||||
# print $fh $response;
|
||||
# close $fh;
|
||||
|
||||
die "Watchman: command returned no output.\n" .
|
||||
"Falling back to scanning...\n" if $response eq "";
|
||||
die "Watchman: command returned invalid output: $response\n" .
|
||||
"Falling back to scanning...\n" unless $response =~ /^\{/;
|
||||
|
||||
return $json_pkg->new->utf8->decode($response);
|
||||
}
|
||||
|
||||
sub is_work_tree_watched {
|
||||
my ($output) = @_;
|
||||
my $error = $output->{error};
|
||||
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
|
||||
$retry--;
|
||||
my $response = qx/watchman watch "$git_work_tree"/;
|
||||
die "Failed to make watchman watch '$git_work_tree'.\n" .
|
||||
"Falling back to scanning...\n" if $? != 0;
|
||||
$output = $json_pkg->new->utf8->decode($response);
|
||||
$error = $output->{error};
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
# Uncomment for debugging watchman output
|
||||
# open (my $fh, ">", ".git/watchman-output.out");
|
||||
# close $fh;
|
||||
|
||||
# Watchman will always return all files on the first query so
|
||||
# return the fast "everything is dirty" flag to git and do the
|
||||
# Watchman query just to get it over with now so we won't pay
|
||||
# the cost in git to look up each individual file.
|
||||
my $o = watchman_clock();
|
||||
$error = $output->{error};
|
||||
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
output_result($o->{clock}, ("/"));
|
||||
$last_update_token = $o->{clock};
|
||||
|
||||
eval { launch_watchman() };
|
||||
return 0;
|
||||
}
|
||||
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub get_working_dir {
|
||||
my $working_dir;
|
||||
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
|
||||
$working_dir = Win32::GetCwd();
|
||||
$working_dir =~ tr/\\/\//;
|
||||
} else {
|
||||
require Cwd;
|
||||
$working_dir = Cwd::cwd();
|
||||
}
|
||||
|
||||
return $working_dir;
|
||||
}
|
||||
8
_spm/repositories/swift-collections-9a58d5cf/hooks/post-update.sample
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to prepare a packed repository for use over
|
||||
# dumb transports.
|
||||
#
|
||||
# To enable this hook, rename this file to "post-update".
|
||||
|
||||
exec git update-server-info
|
||||
14
_spm/repositories/swift-collections-9a58d5cf/hooks/pre-applypatch.sample
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed
|
||||
# by applypatch from an e-mail message.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an
|
||||
# appropriate message if it wants to stop the commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-applypatch".
|
||||
|
||||
. git-sh-setup
|
||||
precommit="$(git rev-parse --git-path hooks/pre-commit)"
|
||||
test -x "$precommit" && exec "$precommit" ${1+"$@"}
|
||||
:
|
||||
49
_spm/repositories/swift-collections-9a58d5cf/hooks/pre-commit.sample
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed.
|
||||
# Called by "git commit" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message if
|
||||
# it wants to stop the commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-commit".
|
||||
|
||||
if git rev-parse --verify HEAD >/dev/null 2>&1
|
||||
then
|
||||
against=HEAD
|
||||
else
|
||||
# Initial commit: diff against an empty tree object
|
||||
against=$(git hash-object -t tree /dev/null)
|
||||
fi
|
||||
|
||||
# If you want to allow non-ASCII filenames set this variable to true.
|
||||
allownonascii=$(git config --type=bool hooks.allownonascii)
|
||||
|
||||
# Redirect output to stderr.
|
||||
exec 1>&2
|
||||
|
||||
# Cross platform projects tend to avoid non-ASCII filenames; prevent
|
||||
# them from being added to the repository. We exploit the fact that the
|
||||
# printable range starts at the space character and ends with tilde.
|
||||
if [ "$allownonascii" != "true" ] &&
|
||||
# Note that the use of brackets around a tr range is ok here, (it's
|
||||
# even required, for portability to Solaris 10's /usr/bin/tr), since
|
||||
# the square bracket bytes happen to fall in the designated range.
|
||||
test $(git diff --cached --name-only --diff-filter=A -z $against |
|
||||
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
|
||||
then
|
||||
cat <<\EOF
|
||||
Error: Attempt to add a non-ASCII file name.
|
||||
|
||||
This can cause problems if you want to work with people on other platforms.
|
||||
|
||||
To be portable it is advisable to rename the file.
|
||||
|
||||
If you know what you are doing you can disable this check using:
|
||||
|
||||
git config hooks.allownonascii true
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If there are whitespace errors, print the offending file names and fail.
|
||||
exec git diff-index --check --cached $against --
|
||||
13
_spm/repositories/swift-collections-9a58d5cf/hooks/pre-merge-commit.sample
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed.
|
||||
# Called by "git merge" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message to
|
||||
# stderr if it wants to stop the merge commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-merge-commit".
|
||||
|
||||
. git-sh-setup
|
||||
test -x "$GIT_DIR/hooks/pre-commit" &&
|
||||
exec "$GIT_DIR/hooks/pre-commit"
|
||||
:
|
||||
53
_spm/repositories/swift-collections-9a58d5cf/hooks/pre-push.sample
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/bin/sh
|
||||
|
||||
# An example hook script to verify what is about to be pushed. Called by "git
|
||||
# push" after it has checked the remote status, but before anything has been
|
||||
# pushed. If this script exits with a non-zero status nothing will be pushed.
|
||||
#
|
||||
# This hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- Name of the remote to which the push is being done
|
||||
# $2 -- URL to which the push is being done
|
||||
#
|
||||
# If pushing without using a named remote those arguments will be equal.
|
||||
#
|
||||
# Information about the commits which are being pushed is supplied as lines to
|
||||
# the standard input in the form:
|
||||
#
|
||||
# <local ref> <local oid> <remote ref> <remote oid>
|
||||
#
|
||||
# This sample shows how to prevent push of commits where the log message starts
|
||||
# with "WIP" (work in progress).
|
||||
|
||||
remote="$1"
|
||||
url="$2"
|
||||
|
||||
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||
|
||||
while read local_ref local_oid remote_ref remote_oid
|
||||
do
|
||||
if test "$local_oid" = "$zero"
|
||||
then
|
||||
# Handle delete
|
||||
:
|
||||
else
|
||||
if test "$remote_oid" = "$zero"
|
||||
then
|
||||
# New branch, examine all commits
|
||||
range="$local_oid"
|
||||
else
|
||||
# Update to existing branch, examine new commits
|
||||
range="$remote_oid..$local_oid"
|
||||
fi
|
||||
|
||||
# Check for WIP commit
|
||||
commit=$(git rev-list -n 1 --grep '^WIP' "$range")
|
||||
if test -n "$commit"
|
||||
then
|
||||
echo >&2 "Found WIP commit in $local_ref, not pushing"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
169
_spm/repositories/swift-collections-9a58d5cf/hooks/pre-rebase.sample
Executable file
@@ -0,0 +1,169 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006, 2008 Junio C Hamano
|
||||
#
|
||||
# The "pre-rebase" hook is run just before "git rebase" starts doing
|
||||
# its job, and can prevent the command from running by exiting with
|
||||
# non-zero status.
|
||||
#
|
||||
# The hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- the upstream the series was forked from.
|
||||
# $2 -- the branch being rebased (or empty when rebasing the current branch).
|
||||
#
|
||||
# This sample shows how to prevent topic branches that are already
|
||||
# merged to 'next' branch from getting rebased, because allowing it
|
||||
# would result in rebasing already published history.
|
||||
|
||||
publish=next
|
||||
basebranch="$1"
|
||||
if test "$#" = 2
|
||||
then
|
||||
topic="refs/heads/$2"
|
||||
else
|
||||
topic=`git symbolic-ref HEAD` ||
|
||||
exit 0 ;# we do not interrupt rebasing detached HEAD
|
||||
fi
|
||||
|
||||
case "$topic" in
|
||||
refs/heads/??/*)
|
||||
;;
|
||||
*)
|
||||
exit 0 ;# we do not interrupt others.
|
||||
;;
|
||||
esac
|
||||
|
||||
# Now we are dealing with a topic branch being rebased
|
||||
# on top of master. Is it OK to rebase it?
|
||||
|
||||
# Does the topic really exist?
|
||||
git show-ref -q "$topic" || {
|
||||
echo >&2 "No such branch $topic"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Is topic fully merged to master?
|
||||
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
|
||||
if test -z "$not_in_master"
|
||||
then
|
||||
echo >&2 "$topic is fully merged to master; better remove it."
|
||||
exit 1 ;# we could allow it, but there is no point.
|
||||
fi
|
||||
|
||||
# Is topic ever merged to next? If so you should not be rebasing it.
|
||||
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
|
||||
only_next_2=`git rev-list ^master ${publish} | sort`
|
||||
if test "$only_next_1" = "$only_next_2"
|
||||
then
|
||||
not_in_topic=`git rev-list "^$topic" master`
|
||||
if test -z "$not_in_topic"
|
||||
then
|
||||
echo >&2 "$topic is already up to date with master"
|
||||
exit 1 ;# we could allow it, but there is no point.
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
|
||||
/usr/bin/perl -e '
|
||||
my $topic = $ARGV[0];
|
||||
my $msg = "* $topic has commits already merged to public branch:\n";
|
||||
my (%not_in_next) = map {
|
||||
/^([0-9a-f]+) /;
|
||||
($1 => 1);
|
||||
} split(/\n/, $ARGV[1]);
|
||||
for my $elem (map {
|
||||
/^([0-9a-f]+) (.*)$/;
|
||||
[$1 => $2];
|
||||
} split(/\n/, $ARGV[2])) {
|
||||
if (!exists $not_in_next{$elem->[0]}) {
|
||||
if ($msg) {
|
||||
print STDERR $msg;
|
||||
undef $msg;
|
||||
}
|
||||
print STDERR " $elem->[1]\n";
|
||||
}
|
||||
}
|
||||
' "$topic" "$not_in_next" "$not_in_master"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
<<\DOC_END
|
||||
|
||||
This sample hook safeguards topic branches that have been
|
||||
published from being rewound.
|
||||
|
||||
The workflow assumed here is:
|
||||
|
||||
* Once a topic branch forks from "master", "master" is never
|
||||
merged into it again (either directly or indirectly).
|
||||
|
||||
* Once a topic branch is fully cooked and merged into "master",
|
||||
it is deleted. If you need to build on top of it to correct
|
||||
earlier mistakes, a new topic branch is created by forking at
|
||||
the tip of the "master". This is not strictly necessary, but
|
||||
it makes it easier to keep your history simple.
|
||||
|
||||
* Whenever you need to test or publish your changes to topic
|
||||
branches, merge them into "next" branch.
|
||||
|
||||
The script, being an example, hardcodes the publish branch name
|
||||
to be "next", but it is trivial to make it configurable via
|
||||
$GIT_DIR/config mechanism.
|
||||
|
||||
With this workflow, you would want to know:
|
||||
|
||||
(1) ... if a topic branch has ever been merged to "next". Young
|
||||
topic branches can have stupid mistakes you would rather
|
||||
clean up before publishing, and things that have not been
|
||||
merged into other branches can be easily rebased without
|
||||
affecting other people. But once it is published, you would
|
||||
not want to rewind it.
|
||||
|
||||
(2) ... if a topic branch has been fully merged to "master".
|
||||
Then you can delete it. More importantly, you should not
|
||||
build on top of it -- other people may already want to
|
||||
change things related to the topic as patches against your
|
||||
"master", so if you need further changes, it is better to
|
||||
fork the topic (perhaps with the same name) afresh from the
|
||||
tip of "master".
|
||||
|
||||
Let's look at this example:
|
||||
|
||||
o---o---o---o---o---o---o---o---o---o "next"
|
||||
/ / / /
|
||||
/ a---a---b A / /
|
||||
/ / / /
|
||||
/ / c---c---c---c B /
|
||||
/ / / \ /
|
||||
/ / / b---b C \ /
|
||||
/ / / / \ /
|
||||
---o---o---o---o---o---o---o---o---o---o---o "master"
|
||||
|
||||
|
||||
A, B and C are topic branches.
|
||||
|
||||
* A has one fix since it was merged up to "next".
|
||||
|
||||
* B has finished. It has been fully merged up to "master" and "next",
|
||||
and is ready to be deleted.
|
||||
|
||||
* C has not merged to "next" at all.
|
||||
|
||||
We would want to allow C to be rebased, refuse A, and encourage
|
||||
B to be deleted.
|
||||
|
||||
To compute (1):
|
||||
|
||||
git rev-list ^master ^topic next
|
||||
git rev-list ^master next
|
||||
|
||||
if these match, topic has not merged in next at all.
|
||||
|
||||
To compute (2):
|
||||
|
||||
git rev-list master..topic
|
||||
|
||||
if this is empty, it is fully merged to "master".
|
||||
|
||||
DOC_END
|
||||
24
_spm/repositories/swift-collections-9a58d5cf/hooks/pre-receive.sample
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to make use of push options.
|
||||
# The example simply echoes all push options that start with 'echoback='
|
||||
# and rejects all pushes when the "reject" push option is used.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-receive".
|
||||
|
||||
if test -n "$GIT_PUSH_OPTION_COUNT"
|
||||
then
|
||||
i=0
|
||||
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
|
||||
do
|
||||
eval "value=\$GIT_PUSH_OPTION_$i"
|
||||
case "$value" in
|
||||
echoback=*)
|
||||
echo "echo from the pre-receive-hook: ${value#*=}" >&2
|
||||
;;
|
||||
reject)
|
||||
exit 1
|
||||
esac
|
||||
i=$((i + 1))
|
||||
done
|
||||
fi
|
||||
42
_spm/repositories/swift-collections-9a58d5cf/hooks/prepare-commit-msg.sample
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to prepare the commit log message.
|
||||
# Called by "git commit" with the name of the file that has the
|
||||
# commit message, followed by the description of the commit
|
||||
# message's source. The hook's purpose is to edit the commit
|
||||
# message file. If the hook fails with a non-zero status,
|
||||
# the commit is aborted.
|
||||
#
|
||||
# To enable this hook, rename this file to "prepare-commit-msg".
|
||||
|
||||
# This hook includes three examples. The first one removes the
|
||||
# "# Please enter the commit message..." help message.
|
||||
#
|
||||
# The second includes the output of "git diff --name-status -r"
|
||||
# into the message, just before the "git status" output. It is
|
||||
# commented because it doesn't cope with --amend or with squashed
|
||||
# commits.
|
||||
#
|
||||
# The third example adds a Signed-off-by line to the message, that can
|
||||
# still be edited. This is rarely a good idea.
|
||||
|
||||
COMMIT_MSG_FILE=$1
|
||||
COMMIT_SOURCE=$2
|
||||
SHA1=$3
|
||||
|
||||
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
|
||||
|
||||
# case "$COMMIT_SOURCE,$SHA1" in
|
||||
# ,|template,)
|
||||
# /usr/bin/perl -i.bak -pe '
|
||||
# print "\n" . `git diff --cached --name-status -r`
|
||||
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
|
||||
# *) ;;
|
||||
# esac
|
||||
|
||||
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
|
||||
# if test -z "$COMMIT_SOURCE"
|
||||
# then
|
||||
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
|
||||
# fi
|
||||
78
_spm/repositories/swift-collections-9a58d5cf/hooks/push-to-checkout.sample
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
# An example hook script to update a checked-out tree on a git push.
|
||||
#
|
||||
# This hook is invoked by git-receive-pack(1) when it reacts to git
|
||||
# push and updates reference(s) in its repository, and when the push
|
||||
# tries to update the branch that is currently checked out and the
|
||||
# receive.denyCurrentBranch configuration variable is set to
|
||||
# updateInstead.
|
||||
#
|
||||
# By default, such a push is refused if the working tree and the index
|
||||
# of the remote repository has any difference from the currently
|
||||
# checked out commit; when both the working tree and the index match
|
||||
# the current commit, they are updated to match the newly pushed tip
|
||||
# of the branch. This hook is to be used to override the default
|
||||
# behaviour; however the code below reimplements the default behaviour
|
||||
# as a starting point for convenient modification.
|
||||
#
|
||||
# The hook receives the commit with which the tip of the current
|
||||
# branch is going to be updated:
|
||||
commit=$1
|
||||
|
||||
# It can exit with a non-zero status to refuse the push (when it does
|
||||
# so, it must not modify the index or the working tree).
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Or it can make any necessary changes to the working tree and to the
|
||||
# index to bring them to the desired state when the tip of the current
|
||||
# branch is updated to the new commit, and exit with a zero status.
|
||||
#
|
||||
# For example, the hook can simply run git read-tree -u -m HEAD "$1"
|
||||
# in order to emulate git fetch that is run in the reverse direction
|
||||
# with git push, as the two-tree form of git read-tree -u -m is
|
||||
# essentially the same as git switch or git checkout that switches
|
||||
# branches while keeping the local changes in the working tree that do
|
||||
# not interfere with the difference between the branches.
|
||||
|
||||
# The below is a more-or-less exact translation to shell of the C code
|
||||
# for the default behaviour for git's push-to-checkout hook defined in
|
||||
# the push_to_deploy() function in builtin/receive-pack.c.
|
||||
#
|
||||
# Note that the hook will be executed from the repository directory,
|
||||
# not from the working tree, so if you want to perform operations on
|
||||
# the working tree, you will have to adapt your code accordingly, e.g.
|
||||
# by adding "cd .." or using relative paths.
|
||||
|
||||
if ! git update-index -q --ignore-submodules --refresh
|
||||
then
|
||||
die "Up-to-date check failed"
|
||||
fi
|
||||
|
||||
if ! git diff-files --quiet --ignore-submodules --
|
||||
then
|
||||
die "Working directory has unstaged changes"
|
||||
fi
|
||||
|
||||
# This is a rough translation of:
|
||||
#
|
||||
# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
|
||||
if git cat-file -e HEAD 2>/dev/null
|
||||
then
|
||||
head=HEAD
|
||||
else
|
||||
head=$(git hash-object -t tree --stdin </dev/null)
|
||||
fi
|
||||
|
||||
if ! git diff-index --quiet --cached --ignore-submodules $head --
|
||||
then
|
||||
die "Working directory has staged changes"
|
||||
fi
|
||||
|
||||
if ! git read-tree -u -m "$commit"
|
||||
then
|
||||
die "Could not update working tree to new HEAD"
|
||||
fi
|
||||
128
_spm/repositories/swift-collections-9a58d5cf/hooks/update.sample
Executable file
@@ -0,0 +1,128 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to block unannotated tags from entering.
|
||||
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
|
||||
#
|
||||
# To enable this hook, rename this file to "update".
|
||||
#
|
||||
# Config
|
||||
# ------
|
||||
# hooks.allowunannotated
|
||||
# This boolean sets whether unannotated tags will be allowed into the
|
||||
# repository. By default they won't be.
|
||||
# hooks.allowdeletetag
|
||||
# This boolean sets whether deleting tags will be allowed in the
|
||||
# repository. By default they won't be.
|
||||
# hooks.allowmodifytag
|
||||
# This boolean sets whether a tag may be modified after creation. By default
|
||||
# it won't be.
|
||||
# hooks.allowdeletebranch
|
||||
# This boolean sets whether deleting branches will be allowed in the
|
||||
# repository. By default they won't be.
|
||||
# hooks.denycreatebranch
|
||||
# This boolean sets whether remotely creating branches will be denied
|
||||
# in the repository. By default this is allowed.
|
||||
#
|
||||
|
||||
# --- Command line
|
||||
refname="$1"
|
||||
oldrev="$2"
|
||||
newrev="$3"
|
||||
|
||||
# --- Safety check
|
||||
if [ -z "$GIT_DIR" ]; then
|
||||
echo "Don't run this script from the command line." >&2
|
||||
echo " (if you want, you could supply GIT_DIR then run" >&2
|
||||
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
||||
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Config
|
||||
allowunannotated=$(git config --type=bool hooks.allowunannotated)
|
||||
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
|
||||
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
|
||||
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
|
||||
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
|
||||
|
||||
# check for no description
|
||||
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
|
||||
case "$projectdesc" in
|
||||
"Unnamed repository"* | "")
|
||||
echo "*** Project description file hasn't been set" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Check types
|
||||
# if $newrev is 0000...0000, it's a commit to delete a ref.
|
||||
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||
if [ "$newrev" = "$zero" ]; then
|
||||
newrev_type=delete
|
||||
else
|
||||
newrev_type=$(git cat-file -t $newrev)
|
||||
fi
|
||||
|
||||
case "$refname","$newrev_type" in
|
||||
refs/tags/*,commit)
|
||||
# un-annotated tag
|
||||
short_refname=${refname##refs/tags/}
|
||||
if [ "$allowunannotated" != "true" ]; then
|
||||
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
|
||||
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/tags/*,delete)
|
||||
# delete tag
|
||||
if [ "$allowdeletetag" != "true" ]; then
|
||||
echo "*** Deleting a tag is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/tags/*,tag)
|
||||
# annotated tag
|
||||
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
|
||||
then
|
||||
echo "*** Tag '$refname' already exists." >&2
|
||||
echo "*** Modifying a tag is not allowed in this repository." >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/heads/*,commit)
|
||||
# branch
|
||||
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
|
||||
echo "*** Creating a branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/heads/*,delete)
|
||||
# delete branch
|
||||
if [ "$allowdeletebranch" != "true" ]; then
|
||||
echo "*** Deleting a branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/remotes/*,commit)
|
||||
# tracking branch
|
||||
;;
|
||||
refs/remotes/*,delete)
|
||||
# delete tracking branch
|
||||
if [ "$allowdeletebranch" != "true" ]; then
|
||||
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Anything else (is there anything else?)
|
||||
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Finished
|
||||
exit 0
|
||||
@@ -0,0 +1,6 @@
|
||||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
||||
466
_spm/repositories/swift-collections-9a58d5cf/packed-refs
Normal file
@@ -0,0 +1,466 @@
|
||||
# pack-refs with: peeled fully-peeled sorted
|
||||
1f8dcd4726717a4b724e5408ca24829bdef67a49 refs/heads/action-xcode-versions
|
||||
7ae9880f0fb622992a8a5328fd4af78af5b6b26f refs/heads/dn/remove-retain-release-during-find
|
||||
ddff9004d745c4b2d13e35ebdd1a3d0b67e14717 refs/heads/doc-basic-span-index-mutation
|
||||
ebd51171f0e45788e2cdb3cc6d54233e11d7443c refs/heads/future
|
||||
39b83a1f44289d67e422b6030c498b8a2c6ff7ce refs/heads/main
|
||||
68c32ed80b138d1f8a6ec5dcf1b105f32fcaaf12 refs/heads/maxd/run-wasm-tests
|
||||
762bc5757de4bcf86cc3b3266e3df93f76469089 refs/heads/nate/zip_dispatch_benchmarking
|
||||
d029d9d39c87bed85b1c50adee7c41795261a192 refs/heads/release/1.0
|
||||
c11818f3cae0780656baa430b49e7f163f08dffd refs/heads/release/1.1
|
||||
2d1f4172091ca272b461397748fd2c32847036dd refs/heads/release/1.2
|
||||
c55cbe540366c704c279298ca6ad4c09a067ebe0 refs/heads/release/1.3
|
||||
a26fc8e7e4c6e0d63b08951f5b7268044fb95c83 refs/heads/span-prototype
|
||||
434d30dae30fbb57699370260c69c2108c1abf8f refs/heads/wasm-tests
|
||||
c65cd649fb91f64636f2f1ef5da4991987139f68 refs/pull/10/head
|
||||
6a9703c3f13061291eff1baf8af4fce1e6ce35af refs/pull/100/head
|
||||
8303a77bc2915be76777d6fc17b702146b6fb192 refs/pull/102/head
|
||||
6cd03922372c85e2dca476f665527976911e7397 refs/pull/105/head
|
||||
96100d4b6ad61bbfbf549ee42dc73239325b353f refs/pull/106/head
|
||||
f69104b5071ef9a44112e3c4fef8904b5e8b6d73 refs/pull/107/head
|
||||
5f255a887e51093f058e7ee9ea0b959051be38d4 refs/pull/108/head
|
||||
c46c77f7f85f9efe83cc5cb8d54b32c538b06450 refs/pull/109/head
|
||||
cfca1038b53eecd4fc50da15cc715f966904012e refs/pull/11/head
|
||||
103008aca495f3b80a50713086d451b08cef9f50 refs/pull/110/head
|
||||
39a16a15cc8c7e11486015d2deb78468b4a64c85 refs/pull/111/head
|
||||
7f57a0ed1c8b1d44eacab95d3cfd57d87482b25a refs/pull/112/head
|
||||
efefae56531b30d75553f234134e3c83bd26c6a6 refs/pull/113/head
|
||||
565b1ab20bef052f52fad4ebe112803facb325e3 refs/pull/114/head
|
||||
8b3af12ece11ea7b0e748749c39a59c59269ca25 refs/pull/115/head
|
||||
8be0f192e8f120969427cb2645aabe6f5fdf15a1 refs/pull/116/head
|
||||
771bca404c0ee603bb6cc2ea3a19cfc4ebc3d001 refs/pull/117/head
|
||||
95be379a3ac1e4278d114a22501267065062b39a refs/pull/118/head
|
||||
f41f2cae69dc6ffcc178227a0a46607561fa925c refs/pull/119/head
|
||||
276ddee5df4ea0f44c5edea0dbe726cb74682498 refs/pull/121/head
|
||||
1c1e6206fa1a4b0a6bf97ac979f841c1d1821ad7 refs/pull/122/head
|
||||
074b0ad21387e767b5b3ff1cb014a118a3b80bde refs/pull/123/head
|
||||
ddc8b9c66d07cb0af38e98ca160f1f7cc85c88d3 refs/pull/126/head
|
||||
9dde4b560323d43ec2ca8225a6c5c79a9bc0735d refs/pull/128/head
|
||||
453adb695f615886cd7a897d62676713aeb25bf9 refs/pull/13/head
|
||||
286fedb1e8f6b2567cd214cf1127a9322dea1400 refs/pull/130/head
|
||||
e77d82c71271b7848e3ac9e007a52f36f04a1c7e refs/pull/132/head
|
||||
1bde9674f42e41bfb62deb96d8b247a537171ba7 refs/pull/132/merge
|
||||
cee04e96ed96fefa5527e33a4a055482e4ea14e9 refs/pull/14/head
|
||||
50e6a1ac71df96e5cd257c565e9a3299f491ba3e refs/pull/140/head
|
||||
29120ea6406a856c36496b4f5d3b13ca381436a6 refs/pull/141/head
|
||||
867231031ac792328eff9133a289ce9e693a03c3 refs/pull/15/head
|
||||
6cb037037d45f78622fd7cab3f62e3c6a4ff5ddb refs/pull/153/head
|
||||
7016a13f0e8d0d0a36f3566a6dc6acaf5b83fbf4 refs/pull/155/head
|
||||
00a99aa77c4982a6e7343982220e44b15e4d5974 refs/pull/156/head
|
||||
74a800ac534877875d5d1187ac04f35b31a0b98c refs/pull/159/head
|
||||
b9d73a5bab8d71e121687f79ed4aabfbd73d016b refs/pull/16/head
|
||||
ddb6d141b3e4e8726a15e3e9e916ee697bd310db refs/pull/160/head
|
||||
3437abecc49cfbbb91893e3a0d0f124db163637f refs/pull/161/head
|
||||
1071b372942289dbd3209ede40f613d339cca8e1 refs/pull/162/head
|
||||
b9d91f4a9aa3cfd6c8589aee997c4399e6d7d83d refs/pull/163/head
|
||||
ee1b2de06edf18545084d99a5c99995e9c1ff8d4 refs/pull/165/head
|
||||
b379fa7aee604738bd0b4076984c934e242bb7a5 refs/pull/168/head
|
||||
71aa4a39ae59addf40e9dd40e79a4968f1c857cc refs/pull/169/head
|
||||
feca3b6f4c7bf7adf9fa4a0fd200f96cf1b5a4b5 refs/pull/170/head
|
||||
9a9d7d87d844b2a14ec602792d9ae216ea57ea53 refs/pull/172/head
|
||||
8cc0b1d43975a9d547053cf0e943498c0d6d7992 refs/pull/173/head
|
||||
aa428d0489be5888c72de4a4327f0f316a586632 refs/pull/174/head
|
||||
14f90620c89e311a067a1fa49813d8bbcd539950 refs/pull/175/head
|
||||
77edbef16d24e657fc3d7b0bc9adb57e6b0567d9 refs/pull/176/head
|
||||
9d9659a079644d300d3571fb64ac7bb14322e506 refs/pull/177/head
|
||||
9f38e7424baa3497e4d481790fc6ec2950725de8 refs/pull/178/head
|
||||
d45f264ef0dc625a37801ee6e05b764ccbef30b4 refs/pull/179/head
|
||||
58579394fc929c1b89b762c3ef68a1657442ca7d refs/pull/18/head
|
||||
39fc818e0efaa148e038e3d89cd78be64567849a refs/pull/180/head
|
||||
4c4154ca2350d981cd6abeadbdcad18071fe3b95 refs/pull/181/head
|
||||
59858a77210f506e622a68e5b92e36bae6fc9215 refs/pull/182/head
|
||||
ba303dca1d72860f0b253778f193010af20f9b79 refs/pull/184/head
|
||||
778b8ae977c420dfe323b27ed3a1cf3f747f936b refs/pull/185/head
|
||||
0f92943ba349d0337d254789bc49e9a5c45ff74e refs/pull/187/head
|
||||
f71ebd9494b3b0b8c1450017f8c30fb61e4dcc37 refs/pull/188/head
|
||||
66651795d89e760188908bb65b3398aa30b84897 refs/pull/189/head
|
||||
832e58027cdb86e618089ebdf2e3474da915c357 refs/pull/190/head
|
||||
9b7c6ecb10599568876b1108005b189de54d9ce9 refs/pull/191/head
|
||||
4604c1bc381c4d164a030d11830701b2897a0002 refs/pull/192/head
|
||||
0b86bb11d24e187ab6ab930f582f75ae00bcabf9 refs/pull/193/head
|
||||
c7c0a094f91bd5cce90b1dc1f3feeb9d2508e7f5 refs/pull/194/head
|
||||
1b71d2cd942459049b870264b7db649ba7509046 refs/pull/195/head
|
||||
7cec5d1ed71d0c29fc7515725401c8a711a01074 refs/pull/196/head
|
||||
b83d06b43337cc2855c1b55ba1cdba854724110b refs/pull/197/head
|
||||
6286cd0b99741db984e5c1115a4c748bc42efec1 refs/pull/198/head
|
||||
8b06c61c7e4ecb6777895a8fba275a44ec8c5e01 refs/pull/199/head
|
||||
5aed92655d73228211985c933e0d5141d8203a09 refs/pull/200/head
|
||||
51604cd196265a1e4444cef0a7ac749e34f5e64e refs/pull/201/head
|
||||
2a81cb1186ac3483183df32ba8c3e2fe7360cbcb refs/pull/202/head
|
||||
6dbc8b8c4f36ff470060464d69066e2e094a194f refs/pull/203/head
|
||||
6b428b5a7fadfae0120db4fc96a3d5b14f7b7c36 refs/pull/204/head
|
||||
b1506b62250f074d23cddc6d0318277dda5d21dc refs/pull/205/head
|
||||
2e872739d3a6201e2b888c73f08ef54ae4125d6d refs/pull/206/head
|
||||
4c842df1b8cfc9611762bdf5fbd9023ab2d3d333 refs/pull/207/head
|
||||
1228e9c1628925843575a11c1de8342e402c7c30 refs/pull/208/head
|
||||
b6184b667bd8f636558522f18cc2fe993a825679 refs/pull/21/head
|
||||
fc8092d0441e0073831d6b170c74b6cca0da9bf5 refs/pull/210/head
|
||||
cfc3d4a5179e61c36d77babd9fd3029a0f85cff4 refs/pull/211/head
|
||||
02ea4e849230bc2326c83c5560822a228d83afab refs/pull/212/head
|
||||
1490835b289653b145b91a16fe5522d928509efb refs/pull/213/head
|
||||
2b4ec22949acbfa99f9e22c390d850a650f3d298 refs/pull/214/head
|
||||
5e0a0149a4c9b2ab407f65b257b5b36bc589307d refs/pull/215/head
|
||||
734730d72460e7bd536e8021d4aa711cb3aa75b2 refs/pull/216/head
|
||||
381cf5d17e46f2d3266bd1be7295118647443313 refs/pull/217/head
|
||||
3c6cb8cd56d04392bf9f79a2d5020fc2abf1958d refs/pull/218/head
|
||||
67fdff5a25539a51ce2a8bf574a7e4a6b72ebfb8 refs/pull/219/head
|
||||
fbdf73e1b787a0ac113e930dff73382f612698d4 refs/pull/22/head
|
||||
d3987c79a1214e279a49a09304c13322560c8a1b refs/pull/220/head
|
||||
5783b82d72e620f37545924d46bdbfb429f03cbb refs/pull/221/head
|
||||
2df7f6d3a8fe5f9bb12b5034da2e095424694d44 refs/pull/222/head
|
||||
72e2df59e3ea600f4d5e67a324bd6df1a7acbd41 refs/pull/223/head
|
||||
98d62d236bef8c30af5b7015ccbb7db66f43399e refs/pull/224/head
|
||||
ba7e3927e76ff55b0579770fb036ffce6ea07b3c refs/pull/225/head
|
||||
207029a613dca008e708370c09fc69010cf6a11d refs/pull/226/head
|
||||
68bc6567be4c1ae96cfea1217b9e5cee63421c6a refs/pull/227/head
|
||||
1c147e3b06edbe0b00217e38e94d2d3bc4b4c6a7 refs/pull/228/head
|
||||
5aa603edfe8c13e0256141cb45f70ec427fe94c1 refs/pull/23/head
|
||||
d19fb14c46266a20cba9c5362923c6a076e74407 refs/pull/230/head
|
||||
a32048d44ee028b915565c3093ec5305e41aa6f1 refs/pull/231/head
|
||||
4448454fbc79b8052acc6b6e7eb6c75c70d1ee2f refs/pull/232/head
|
||||
14e86daeebe18bd32466a1f2bd2d8da936aa6508 refs/pull/233/head
|
||||
581490a7351be07e465100628ded472aaa137a99 refs/pull/234/head
|
||||
ff2d526c1baa53df478db47156bbdd68fcaed4df refs/pull/235/head
|
||||
98d519ec12ec6bc209ad61fed2e7e2101e312566 refs/pull/237/head
|
||||
339f1677450d7a8f43518d61cfd93be85fa080c3 refs/pull/238/head
|
||||
ff85ea9e4f1cf6fd50fb758cde3dedf01a742f52 refs/pull/240/head
|
||||
18c4f6dc5a771cd3f90ef3e7ae02a99e09e89115 refs/pull/241/head
|
||||
3d66da5f5baa3585aa4b5fe8f9d9eaaee5e5a6ef refs/pull/242/head
|
||||
2c33149e4e2cb9a5b2616cdbad9eabb5f51f0e0c refs/pull/243/head
|
||||
a2f4b18ae02cd14a8488c357c75fef3f2c2a9013 refs/pull/244/head
|
||||
69768b6eacd442681bc8424cc76516e7e24fdacc refs/pull/245/head
|
||||
f8252436e5e4384eaa1a68560db380d83b7c71eb refs/pull/246/head
|
||||
07032a92671dea282cbc935383dd3d5a0a598682 refs/pull/246/merge
|
||||
b8ed4950368d4d54cefd2b8bfe14c329e057172c refs/pull/247/head
|
||||
10a01bd9fb383668a987ec8f512da627dbe55f9e refs/pull/248/head
|
||||
470bf29d014757caae7222f3a41aea0b86b6ee1c refs/pull/249/head
|
||||
b43076ca7b46b8216590766fd446ae538ab91c5a refs/pull/25/head
|
||||
c0853ebef8dad7eddb6a44b76dac0f42f699b96a refs/pull/251/head
|
||||
089666b32ba82c06a166e072ebcdf988108b66b7 refs/pull/252/head
|
||||
fef38395004569688a967b88c70d8774c63f5fc5 refs/pull/254/head
|
||||
972578a44da6463eb8f88552cc7d30cf0b6de9a4 refs/pull/259/head
|
||||
0c2071ecda7a50dcdc8ec435a45b3b830b3e5bcf refs/pull/259/merge
|
||||
4e2f86b6cd24a124d69bf9257d2ffa751d11da8f refs/pull/26/head
|
||||
580beb4c121a85f60aaf6f10403e7f457c81ccb9 refs/pull/260/head
|
||||
5b4e4e032fc56ca77b888ca36b7a342e9932e5fa refs/pull/260/merge
|
||||
3e6df33472d54ed83dffe3bca7a3c8f65bab4c43 refs/pull/263/head
|
||||
fcd6800b9d1171fbe0a00f51a72afac32b0a1987 refs/pull/264/head
|
||||
5dc7a8970eabcf6aaa49529b5ef6401f5128637e refs/pull/265/head
|
||||
1666222de2200b2a614a0d5184751b8b6f7309b0 refs/pull/266/head
|
||||
e6ecdac581c3f03f442111b87655702e0664df67 refs/pull/267/head
|
||||
26de4aa094c87a9efd793f3ec37ec7facea24184 refs/pull/268/head
|
||||
73936bba69bd49e025aa8113fa81caa7f76ed571 refs/pull/269/head
|
||||
454c84b5e4253e462dac5472b853ee222ca93368 refs/pull/270/head
|
||||
9c3328e235e5f17c06328f021a5d11e7221690f5 refs/pull/271/head
|
||||
96d71628887275fc3010a0979cdebef15edde911 refs/pull/272/head
|
||||
4b6978bf8b220c9c7d03d1f8124d537fbbddc32a refs/pull/273/head
|
||||
7f63914a7161923e9af6889ed0f954de1ed4c7f0 refs/pull/275/head
|
||||
ac0c075ccc0fe2754a41dd777bb39507e73efe5b refs/pull/276/head
|
||||
a8dad62bc9c76f1f455a372c91759e7bb1e92e63 refs/pull/277/head
|
||||
99adbe97af48017fb51d884936f6bb87c27166c2 refs/pull/278/head
|
||||
b0fe7ca8bad02599faa6a308b561f71d4d5e3b4b refs/pull/279/head
|
||||
dce7b156e7276d44c3641f05bf675d90fea16523 refs/pull/280/head
|
||||
c4ad48826105dd299f45473784d22bf395b56863 refs/pull/281/head
|
||||
1f204555aa1678c0aa01cfba5836920acb8c5537 refs/pull/282/head
|
||||
992e0f3446b4f608f5ead9dd6edc92f6bbc0b0a0 refs/pull/283/head
|
||||
3f4d8f9912c9c3f5bacef6e6543b3f5b93168f65 refs/pull/284/head
|
||||
9befd06185369d287deee36f3d0de65f41edabb1 refs/pull/285/head
|
||||
0c002200bbee27acc8a663075da69120f666b4e5 refs/pull/286/head
|
||||
de0f59418503fc0c4866395751d930be3abbf17c refs/pull/287/head
|
||||
a5fda7c368e06561fba87dd33c47443e879dd6da refs/pull/288/head
|
||||
989bd7f2db6d9e7aa91881389359e369d621e3d9 refs/pull/29/head
|
||||
03c9ef743ad9de4eea816225afa2fc52490339cc refs/pull/290/head
|
||||
03e7f0c401e771f4a4c529eae4d3fde91f5bd355 refs/pull/291/head
|
||||
9c88dce30d213e1844ce60476e7d3eba2b1f1e60 refs/pull/292/head
|
||||
671cff0b3e579cbdad3a0818031063588d866ad2 refs/pull/296/head
|
||||
b3d089e37d0d4adc07bdbf1ecd14e9be3786bf25 refs/pull/297/head
|
||||
2f6606401781d32f3ffe3e245f2ba946acefe97e refs/pull/298/head
|
||||
8fbc1d318cf4c48931ffc6d204123284087fad0c refs/pull/299/head
|
||||
cf2cbd6ce39cbbdf7c60b76a8dca8e38b80486fc refs/pull/300/head
|
||||
09c09f0f734c006186df57595dc823159e0d49ef refs/pull/302/head
|
||||
a58628449c5e398433472b1bfd7e67e0acbe09fc refs/pull/303/head
|
||||
a82138e714dcd28ef5b7bacc4b708acc118e87ac refs/pull/304/head
|
||||
f15c276542595cb0f55368f8abf9f277e8eb51c9 refs/pull/304/merge
|
||||
1cf3b88cb3d237183cacd6482e4adaec48b17bb5 refs/pull/307/head
|
||||
ccd11e55dd4991055b260bb39d7e20ceb09046e9 refs/pull/31/head
|
||||
9efa05c583441159bd505dfde340cf774d6144e0 refs/pull/314/head
|
||||
bf742617f30870372ed235c6ccf4515ea0a204d3 refs/pull/315/head
|
||||
b6e227b9d779fe7405dc410812cb3aba6d2b529a refs/pull/316/head
|
||||
5c9ee680d20c4a758b0ffe06876fdca823f8068a refs/pull/316/merge
|
||||
de2c8a90865dcdbd97defe3c2c7396a2400e455a refs/pull/318/head
|
||||
bd1a62273592d5ad6ef388a70f53a61e33ffcba4 refs/pull/319/head
|
||||
171edb86e347f70d85ac593c139d26d6b4d3bbea refs/pull/32/head
|
||||
33f23b6a06f4a9f6b013fdef108cc1c82153afe4 refs/pull/320/head
|
||||
b67553e0c27857bbc5310f40cd6e68daa2d585de refs/pull/321/head
|
||||
b72a6cfd9384bc3ace8ea2412e79d5ec34c24934 refs/pull/322/head
|
||||
90b67c44eae7277d57e79e3c25c5dc72939a3b93 refs/pull/323/head
|
||||
19ec155f6089f6de453f8835aad46c09f5fd0b4d refs/pull/326/head
|
||||
069dd4e5df442e813eb30e3216aafa1cc1696a5f refs/pull/327/head
|
||||
53831b3a2264e24ca6c7ffcfe33c8653a72d51e1 refs/pull/328/head
|
||||
0b7ebf49775a8e5177eeaea6513083363a20e08c refs/pull/330/head
|
||||
3bd3d3ba28c6e72515e56b535b8a638144c12413 refs/pull/331/head
|
||||
cd03e5b471755b00aa948f7de950932c2c5a5d79 refs/pull/332/head
|
||||
e732790fde08a5e3d4f2347ac4a3e74399a5b457 refs/pull/333/head
|
||||
d2662892cd218eec7b56e505e4a343e5c676f02c refs/pull/335/head
|
||||
2bc657fad1def9519f88d851ef9e91bc01dc0e47 refs/pull/336/head
|
||||
6e91291cb24b777f0db29a6d50a728a2183ab660 refs/pull/337/head
|
||||
f9c400fb1c9bb8f2f76484b1a398135175d87a7f refs/pull/338/head
|
||||
071a1011d1f02ac96f92164b0313c429a159ad80 refs/pull/339/head
|
||||
85b00faba7071b5d7babb426bc06aa401ac8814d refs/pull/34/head
|
||||
525bb545c4c1f7dfe3ca461136c072af11cb6e4f refs/pull/340/head
|
||||
2122327782b71345cce48f23b688deebf582adc3 refs/pull/341/head
|
||||
40e737cdaf9341d821cba518ee990406fdcfd7e3 refs/pull/342/head
|
||||
8bfcaddd5fadea396620871451ca9ffc43b0985d refs/pull/343/head
|
||||
9d4a1e5ad279e6bc1c4230f90208b0886608a387 refs/pull/346/head
|
||||
cdcf9e606a12221e123a642353fbcfdc5d48bcf6 refs/pull/347/head
|
||||
1a0ac8c06c5a27f330a55a61464eaebc840d89d1 refs/pull/348/head
|
||||
258df0792818d6c331ccee923736ea234c24cf07 refs/pull/349/head
|
||||
3c9df19f7da674295f58f07f6dffa5d9e114fbc8 refs/pull/351/head
|
||||
c61e5e23c89b99d26aaaec6ec6c58bda1b502ebc refs/pull/352/head
|
||||
8dd4e591b3789ea14e8bd8cfde3ed81aa6edfefe refs/pull/353/head
|
||||
50f6307501712d87110f3f4d2e4959e84ace3bc8 refs/pull/354/head
|
||||
8e64f064f562a918993b147a3872e92c157e8e01 refs/pull/355/head
|
||||
ab744afc39dcd099948bfeb7fa4ac14f3f53dd36 refs/pull/356/head
|
||||
75395832459d3e7a05ec51ca2ea081fe99be5e8e refs/pull/357/head
|
||||
e004cd36fa3900c67d97f9944320a213e0d62c42 refs/pull/358/head
|
||||
f6380bb6608eb7d43c199b3d0ab2f932d300a338 refs/pull/36/head
|
||||
e424b487611d755ee5fe94271dd69677cc7688f0 refs/pull/360/head
|
||||
a45e90653a50d7cd8813775cbf3d4ae546db1479 refs/pull/361/head
|
||||
1e132acbb4f4aceea67ac8cdd5a4afdb1053e13d refs/pull/362/head
|
||||
09566acb3a06bcb80147555395ae564402a4013f refs/pull/367/head
|
||||
7425af3a9e29913aeb7cae881f9583f204ca5310 refs/pull/368/head
|
||||
e9112f40dd90d800c46adf88c7ad58653276bb5b refs/pull/370/head
|
||||
f46333d4a7c3a3f408131e268589203a68b84a09 refs/pull/371/head
|
||||
37feda1bb815269044e98991edf011dd713eda6a refs/pull/372/head
|
||||
ba5154b934dde320698eb31623e6c61eb63675e8 refs/pull/373/head
|
||||
e3954cdae4f9e97fbd7fd3ec1e80f01abbd6c06c refs/pull/375/head
|
||||
89b3ca0146f7371dd1008b0f6dd1d1452840deb2 refs/pull/377/head
|
||||
8d9e1e32484fa7fbbfe49df058fee41304c47213 refs/pull/378/head
|
||||
5d891350f44eecd7767b85259b1fd3068afe3c16 refs/pull/379/head
|
||||
d46a563351a5785e7ece59366fb80d1ffc21885c refs/pull/38/head
|
||||
ead6314a1cb17c2ecce50c80876f1998dcff6286 refs/pull/381/head
|
||||
35d5746117b42a556f81cff9fe016fdff8a6ddaa refs/pull/382/head
|
||||
a0b839d7de3278c5003836ad27d8ab75b994cbf5 refs/pull/384/head
|
||||
d10a328f79966ada76c0f5e1f13922363e1d7da9 refs/pull/385/head
|
||||
21264913c5162a74f58ef8af8d675417b188b8b9 refs/pull/386/head
|
||||
dbf90bd36bcfdd3659670e26259e1a1cf40b053a refs/pull/388/head
|
||||
5c2623b1a8d01d670455c739d07d94ba4f731f72 refs/pull/389/head
|
||||
7d18b37a95732fa58da3863efb4f8f142524abdb refs/pull/390/head
|
||||
094bf7ff2c87c735eb7ef41e1eeaedb41c8c0625 refs/pull/391/head
|
||||
16fcea238788bd5d298d96a199ffbbeea9f0845a refs/pull/392/head
|
||||
b7ccc7206cefa77e0139cd01af053895a5021fce refs/pull/393/head
|
||||
79e3fee891cf132262e66a192424cc5a5892c732 refs/pull/394/head
|
||||
7afbd7686e3ed22f4fff4f12721e944fb94c3476 refs/pull/394/merge
|
||||
36d53620b57f2c90b897525049d50d327f174edf refs/pull/395/head
|
||||
ce574378f856d15eec794157225005947534a6ca refs/pull/396/head
|
||||
99b025049e3fd4f1a791349716d7e3a6e6742ea7 refs/pull/397/head
|
||||
09f9340dcec6744e7238c0d966cad57e302a7419 refs/pull/398/head
|
||||
f049c7ae66996b3be81be9688aecc313fb62d2bd refs/pull/399/head
|
||||
3595ca05808ce018fb0fe6ca985a94d162cee300 refs/pull/4/head
|
||||
ec1893ac2372b7f596f4bdcff9b3fdbf1017dddc refs/pull/40/head
|
||||
105afd86fbc2a40752f4d522f7168c4f5c68f551 refs/pull/400/head
|
||||
3dd72d1c289e56fac76e5a5416c397da4946e98d refs/pull/401/head
|
||||
edb00bd980448f956a07b3d513f27fca32a1bb08 refs/pull/402/head
|
||||
cf241c3b6c32196768d825f961fc9b00e7e6b53f refs/pull/402/merge
|
||||
6b8276e2521d63ae1adc2cfd41d9e5a03e099ebe refs/pull/403/head
|
||||
6f4d9d856088be4b13c96717e45e94f902bb3fbd refs/pull/404/head
|
||||
5e1fe6e8f04e609273ee4fafe2fb77922ac2012f refs/pull/405/head
|
||||
93efdb9e4e967a0ad0cb735721b0a67447cd12b2 refs/pull/406/head
|
||||
effb33569a926c12dc8e7bae979ac2075c219189 refs/pull/408/head
|
||||
e14970493019b12d03046f2fdd01b76fd4f9fa3c refs/pull/409/head
|
||||
897b7c1a387e7afc2c95b4022c3b303137631c62 refs/pull/41/head
|
||||
5dd817c33df1a62776320437413ad7afbeaab414 refs/pull/410/head
|
||||
75aa5b075534ab11b77bc694f4c6d7cc29eab26f refs/pull/411/head
|
||||
0f138be4021524c1b9b8fa2dcd343876695b8101 refs/pull/414/head
|
||||
ca0c7a28b9b94243cac476dc4275db29f5d0be46 refs/pull/415/head
|
||||
0030b455f42d9a8588cb9791fdf9e62a4d0e401c refs/pull/417/head
|
||||
0030b455f42d9a8588cb9791fdf9e62a4d0e401c refs/pull/418/head
|
||||
7f49fa5164ce43bd1bfcdfe2b43b56cdf6845bd6 refs/pull/419/head
|
||||
ea4ab58dbc0a886c8a50752068de817ba1e49e81 refs/pull/42/head
|
||||
fec5a5a6302e3bd30b71cbb8a22706d417eb5e72 refs/pull/421/head
|
||||
a49afbe1be5e5d26f74b32d77057bf01ecee83bf refs/pull/422/head
|
||||
ccff1fbf71b315e0eee2ba2b46b82dda44fac55d refs/pull/423/head
|
||||
3f6522fef12acbebec4e425fec2a0d63a4bbac60 refs/pull/424/head
|
||||
b33922ed298ce150cd04d0ee330d0c85b3cee104 refs/pull/426/head
|
||||
84087c786e25744e47affbaae0b44415a973bdc9 refs/pull/427/head
|
||||
ebe01ea88769ec788cdcd91bdd9d24ae5ceb4f55 refs/pull/43/head
|
||||
2709b9694779797954b7bebb18764c2a85876e7e refs/pull/433/head
|
||||
98d345bd66496d36a1d62506d405e6d7b07e8cde refs/pull/436/head
|
||||
2d4df7d85dea6c6e81edb7a51de92c413318b6c9 refs/pull/438/head
|
||||
8d73c7cced4d9a8403e2353f02359844bd33b5b9 refs/pull/438/merge
|
||||
117c81053b70de031bac51b53288c001662c9305 refs/pull/44/head
|
||||
4450b7c62274bc08f21b94269e0316e2799afe90 refs/pull/445/head
|
||||
99db3179fcfab1add1a2418ed5f5392f25156aa0 refs/pull/446/head
|
||||
40adeb7fd7e86a3d84779a2c43c2211ae805b804 refs/pull/447/head
|
||||
1cb3ca50a63e8eac9dc503b3fba69ef56a99bce2 refs/pull/449/head
|
||||
0f73f0ace74ea44f39ab10f23a3d2c03afd54a8f refs/pull/450/head
|
||||
7ae9880f0fb622992a8a5328fd4af78af5b6b26f refs/pull/451/head
|
||||
c5ac12e2bc1ad8df1df0ee9d1236ab6366a2c32d refs/pull/452/head
|
||||
cfbebf4c80d0bc18609e7d603366f384dbdc8ef3 refs/pull/453/head
|
||||
dbc2866bb5f564d3be3fa5efdda769f2946ee968 refs/pull/454/head
|
||||
225159599d37106d63795d2df1bcbe0ccf7b3479 refs/pull/455/head
|
||||
25509c0b883738629b6a13c013b6274538112fbe refs/pull/456/head
|
||||
c42b4d1ebc5d198401f3efbcda36874b987e29d4 refs/pull/457/head
|
||||
fd9ee69e0ba4e389a5ecdd85822a0932b0496e3c refs/pull/458/head
|
||||
769bc7b07c3b986d928540d74d53bdd3d73f4374 refs/pull/459/head
|
||||
ca939f84e132eb64a44db49c8092c8ec261b3092 refs/pull/46/head
|
||||
75837a77174c0dd3243a599fae8c1675c64860d1 refs/pull/460/head
|
||||
3fffe2ad2062eabe93dddb4d2e37bffe9bf278dc refs/pull/461/head
|
||||
fea1d24e7be3284646858ef7bc9950f685adaa61 refs/pull/462/head
|
||||
b765db28be0063341ef9048a8c4f6efb8b0e4cbd refs/pull/463/head
|
||||
6385ebbe4d5fd7235dca833a4b041b14f06d46cf refs/pull/464/head
|
||||
7ec497fb53a8d0a680576f1e0b0781fb71c99429 refs/pull/47/head
|
||||
a7fec81fc4c4af5e49d2ce19f3b39ef51202fd22 refs/pull/470/head
|
||||
117a1aad2d8194b8632bb46483573bb0b7aa50f1 refs/pull/471/head
|
||||
0bd8dec08b8bb484f4a39e8d241a40c8e0c8a051 refs/pull/472/head
|
||||
d5f3b81e690242c750deb4ede721539250297bd6 refs/pull/473/head
|
||||
c25a388c1375c634d42a6f5608a863a4b6aace2c refs/pull/474/head
|
||||
a09d7cdf458769f6f9586a2782b03d624d710428 refs/pull/475/head
|
||||
e1be57c0f55f90d9489773dec69449bd86fce692 refs/pull/476/head
|
||||
1812091001b264fc9b0db6a4b847ef9b330f5fd4 refs/pull/478/head
|
||||
e337c2b936320f538fc8b9e8b66d51bff56646e4 refs/pull/479/head
|
||||
137bd464c14792cadc721d90afd412c2e7735424 refs/pull/48/head
|
||||
6819c6d1491caf6819649a0635d35956700cd165 refs/pull/480/head
|
||||
c50c57f52eaae3f241dd3a4338d05f199d0bd94d refs/pull/481/head
|
||||
83457e19c8b17548bf30f43bdfe7563cc6621633 refs/pull/482/head
|
||||
d5568ee899f3b9487cf752cb28027910f84aad46 refs/pull/483/head
|
||||
65f99e3eff346e5033d9ac9310021a4ff55a9a64 refs/pull/485/head
|
||||
fc411858ee8c2d1ca4113555c185752f5d8212f5 refs/pull/486/head
|
||||
05ad8633a8d6e407bd9dfce36da47b3fe36b3da2 refs/pull/487/head
|
||||
a1f8f33a5b5ae60c6bdad045176e3fc96427a0a5 refs/pull/488/head
|
||||
3fe754c0804d97b446a8ca70b3e4aa8d9c17c831 refs/pull/49/head
|
||||
2d5ed365ff0a9d7c7bf9a84e8ac0692b80caed92 refs/pull/490/head
|
||||
9f68408a70172d6c4ce3ba4e3a7528f489629e43 refs/pull/491/head
|
||||
2fe5c4a31d9e599dfb55d21a02b8f9b74c5b3165 refs/pull/492/head
|
||||
1f8dcd4726717a4b724e5408ca24829bdef67a49 refs/pull/493/head
|
||||
c883a1729ac36de8cfc30729dd9650a98ce5c5a3 refs/pull/494/head
|
||||
f44eabc30ee11beb77577f4c059bc6cf1643885b refs/pull/495/head
|
||||
ab46d6415275a4f1c66923aad5d9759394b9999f refs/pull/496/head
|
||||
31183bf059d3d1698d2b5e10a17bfb892a57876b refs/pull/497/head
|
||||
b33592ebce263de67a30234f5952833e58f519f8 refs/pull/498/head
|
||||
efac873c1357fd397b246e601021930c2a1561b9 refs/pull/499/head
|
||||
efac873c1357fd397b246e601021930c2a1561b9 refs/pull/500/head
|
||||
f6256df2628c6dc9b8637a81c9ce3bd9354b4df5 refs/pull/501/head
|
||||
a98fbaba8b4236b1f98a9a4ee8269f5beb054425 refs/pull/502/head
|
||||
8db0c6eb7539e9e73dce1a74be02093f531c8c60 refs/pull/503/head
|
||||
890f33b56a7c03f5d8c680b5b566b07669adf6fb refs/pull/504/head
|
||||
16f8d5b6bf91315e87e3922d2acae52d38c6bfe1 refs/pull/505/head
|
||||
4ea19dd03e4c9632ee09a94f32f18a12df02da9e refs/pull/506/head
|
||||
21757b6add20f67be68cad7c3b36e3ef3ec6875a refs/pull/507/head
|
||||
5cd51978a44752b0432329904e72fe3ffbe22523 refs/pull/508/head
|
||||
5f92d48d0d590f68340a9a6acdf0c7ae9638bb7e refs/pull/509/head
|
||||
dff2b1783badd696c3135abd8e26c3b7ad2e67fd refs/pull/51/head
|
||||
434d30dae30fbb57699370260c69c2108c1abf8f refs/pull/512/head
|
||||
fb75c41e703f7ddaf22edfce3488c888cbb3136e refs/pull/512/merge
|
||||
43367db377713ef76db6e16df128a96a7db5a805 refs/pull/513/head
|
||||
50a9c6c655766bcbabac0453a5dce8cddd3e8cf7 refs/pull/514/head
|
||||
101bac2d30cce81a24eb2b223aa64d928ca6598d refs/pull/515/head
|
||||
6340fa0e9b818a19be3982951106ec6071075843 refs/pull/516/head
|
||||
90934a152b26db2cacafaf26c0f85261815f2344 refs/pull/517/head
|
||||
3fe1bb8561a92c45a56afb6dc3af95755cc2273c refs/pull/519/head
|
||||
42e6045ca1307cdd5b13a69aef57336abb7ea486 refs/pull/519/merge
|
||||
5e6b95649be69c3e9d6c326f2a7c2ba88c25f460 refs/pull/52/head
|
||||
377d2a55a8b9506d56d4eedefe26565240b208f0 refs/pull/520/head
|
||||
4cc6cad50849690b2c551f306265509d7168730b refs/pull/521/head
|
||||
b88e7d0b00bcd6721cc0b11ac2b948a32a9c444d refs/pull/522/head
|
||||
f4d851a739f6f1cfd0364b1c1ceb9aadd1b07f2f refs/pull/523/head
|
||||
68eca941248011fdc278bd752f39fbd3f62e46c7 refs/pull/524/head
|
||||
ccb60599696d69e9744224367ca927e6ba3f74b3 refs/pull/525/head
|
||||
bb8d56683375160bdcc35d0ca7dcf06bb875bece refs/pull/526/head
|
||||
ab7ca1353732f13ba1b24f4b95efe3dc148a0a73 refs/pull/527/head
|
||||
f9669dc4186220345d8a856550386492aae74e5c refs/pull/528/head
|
||||
b0f915ac6981dc529e3aa27bfe13b93c067da83e refs/pull/529/head
|
||||
cf2685d6213f8966f3e453d66aa51c5f993cb514 refs/pull/529/merge
|
||||
4432aa8d79607328e6e96ae2a89f878ea58b27fe refs/pull/53/head
|
||||
fa45e0e0cc63150df8ff27c49a8385f1f989d2fb refs/pull/530/head
|
||||
a2a4bbd3dcd04b7ec7fc84258c1732298fb95d60 refs/pull/530/merge
|
||||
ea71bf2ce9a4420dc5716b94c0e02032ef3b0486 refs/pull/531/head
|
||||
347825dd43e9c7f3b346aff777ae4a0cffe93ea0 refs/pull/532/head
|
||||
ab649ca5fc756ed6b3b290662fb273460c4a038b refs/pull/533/head
|
||||
a7e40d20551cab8bdf753c9ea809f80443903290 refs/pull/534/head
|
||||
55130cecb0b8eb39da9c281e9124168d1068079e refs/pull/535/head
|
||||
e5e653088cb61fae41189623b208cb100624b0d8 refs/pull/535/merge
|
||||
fa408c9e853e04971c32351bab2e2200c4e07349 refs/pull/536/head
|
||||
f2b51f49978351bc6225aec3cb18a916b0c4245a refs/pull/536/merge
|
||||
65d174cc77577c972ed34fa03efa8c982c72f0ac refs/pull/537/head
|
||||
e2e2d0088182c22f26a007d3ea4fdb3497cc830a refs/pull/538/head
|
||||
0cf0071c1db25a01454339aa1dac6f8c984f8244 refs/pull/538/merge
|
||||
691855a60fca67d1176bbca0871ce9beb9170bbb refs/pull/539/head
|
||||
788c17c16b5bc88466d1a0a96f0bf7eaef8b9352 refs/pull/54/head
|
||||
8b3d2878dea8451badb5b66094e7b4d0e4d1c658 refs/pull/540/head
|
||||
ddff9004d745c4b2d13e35ebdd1a3d0b67e14717 refs/pull/541/head
|
||||
5e091e541bc88b91fc750bb908aab665a4f13334 refs/pull/541/merge
|
||||
1d63cdd629a5fc9e2b15a25b667f804d872f9e47 refs/pull/542/head
|
||||
a617f5e2b1e7bee60846a2033645f28015990d2b refs/pull/543/head
|
||||
92baa3289dee72e28b5add8cfd88c3a909d68f17 refs/pull/545/head
|
||||
cf642a237ea2c2c0e345fdb856e203d418aedc81 refs/pull/545/merge
|
||||
347825dd43e9c7f3b346aff777ae4a0cffe93ea0 refs/pull/547/head
|
||||
2b5cbd54cf8d59e4780dad338b31cf31c3ea4aa8 refs/pull/547/merge
|
||||
68c32ed80b138d1f8a6ec5dcf1b105f32fcaaf12 refs/pull/548/head
|
||||
218066a6698047a111ce5fe6c77999db3cfb11ad refs/pull/548/merge
|
||||
ad176827391e97cc1a919f38f3f6af655184facb refs/pull/549/head
|
||||
ff76bbdc775050687a8495f75122faa8fef37d84 refs/pull/55/head
|
||||
353496019475df6047027998d1cf69505fef172f refs/pull/550/head
|
||||
7f8a32c5a9c9b07f57ebef314a5a289c7eb51021 refs/pull/551/head
|
||||
a0e7df98638abbdaa452dc08b929538bda94ae18 refs/pull/552/head
|
||||
174b3135c3a20094b65edb2e2c4e3e1c13693d58 refs/pull/553/head
|
||||
c5d5d97c43f38162bb49fef37149ea6c4a136c50 refs/pull/554/head
|
||||
7c926083822b8eea2c51cf6c6f425b9101b5d2bf refs/pull/556/head
|
||||
5c119d9eb367474bd9cbca0e37481af4913d2db6 refs/pull/556/merge
|
||||
29b31e5e0d3ca3d85bc1c546aeb16ad2f510c6f3 refs/pull/557/head
|
||||
6274c2a3b1ed55f5227f54b37c1437b74a060b3c refs/pull/558/head
|
||||
81514112d770a2ceeddcbba2207204661f40c650 refs/pull/558/merge
|
||||
b7d2cf8908b42f35b5a3929e18ab63d3a321a3a1 refs/pull/58/head
|
||||
956ea437dfdfcc6b431315fe54a9388271f5b512 refs/pull/6/head
|
||||
175e1eb6b3395e3808218e72910235658819bdc5 refs/pull/60/head
|
||||
083102e1e2bad3bfc869f3072f134fc48a401550 refs/pull/61/head
|
||||
0b963fe790c694a35c34b2b31caa84a681f74945 refs/pull/62/head
|
||||
cfe64fa1f270ff99ae4c5bf36502656d5c77596f refs/pull/63/head
|
||||
787c4fac1492d4d877127ccf086195b5051b5c01 refs/pull/64/head
|
||||
478d3cc73fe173775883d35a2b0a073567da3b4b refs/pull/65/head
|
||||
2a60245369a3e88485ed4f8c92ca5c378ce77c06 refs/pull/76/head
|
||||
b70b6fec29949244914e7501725deb52370da0b0 refs/pull/77/head
|
||||
303e1990d6317fc39c5c072483d18e4f0235db60 refs/pull/78/head
|
||||
cfaab9a73140595755a5bcc138c45ad817dc4f44 refs/pull/79/head
|
||||
8de85365808b3d984148d0adb5dc36125a71c36f refs/pull/8/head
|
||||
976a8c276338a00a436f620f9cb8d3c0f74f6d81 refs/pull/80/head
|
||||
1146f2644c44ff629c5dfc8f5588d6d4cc734a22 refs/pull/80/merge
|
||||
07134a5bce472917a2fc2f2a19401861a688530b refs/pull/81/head
|
||||
3d4aca47308287244f2dd7b9c2085dea63c27b60 refs/pull/82/head
|
||||
140a1752fdfa9788db9e5b23ee32d8bdbed4c9f7 refs/pull/83/head
|
||||
40ab3405b25719a490abea591d80b7ce27ab8803 refs/pull/84/head
|
||||
52f77c4486ea96a3c5ed373932ee0220d5a7ebee refs/pull/85/head
|
||||
029dd258a1d19cbcd8e22523b0811c7dcb6d450a refs/pull/86/head
|
||||
8ef7b779cd17e95baeef138a612c48b063036aca refs/pull/87/head
|
||||
ace0073826e3e2bdc1b08d78e6fe6f1efc700aab refs/pull/9/head
|
||||
e78605942c7fb08c3e8812a166e85bcae2ddd15e refs/pull/91/head
|
||||
7c68b05ed94391100c1933770cd18e95533bd53d refs/pull/92/head
|
||||
d6774be62f7f857f0b30dae49a3a6f02b58e5679 refs/pull/93/head
|
||||
6192ad1fc8795b647f8fb9eec20257ae2cb4716d refs/pull/95/head
|
||||
dcdd7ebabbdcac6442e45db68f6e3d10b96f0c88 refs/pull/96/head
|
||||
41bfaaae0af3809b808405df0fab4a5e02ddd206 refs/pull/97/head
|
||||
462fb1d3fc318f4e1f81d6945b87f1dc32dd8079 refs/pull/98/head
|
||||
c1c9541a3b91ec076076ad8e9a4e28a00b80cb6b refs/pull/99/head
|
||||
bd924007a25488900d2e3f3437a0388a97636020 refs/tags/0.0.1
|
||||
2d719d75a2065f213e58a5164384a3d2fcf9b59a refs/tags/0.0.2
|
||||
d45e63421d3dff834949ac69d3c37691e994bd69 refs/tags/0.0.3
|
||||
3426dba9ee5c9f8e4981b0fc9d39a818d36eec28 refs/tags/0.0.4
|
||||
0959ba76a1d4a98fd11163aa83fd49c25b93bfae refs/tags/0.0.5
|
||||
9d8719c8bebdc79740b6969c912ac706eb721d7a refs/tags/0.0.7
|
||||
07e47b1e93e5a1e0ef0c50fcb2d6739fb6be4003 refs/tags/1.0.0
|
||||
2d33a0ea89c961dcb2b3da2157963d9c0370347e refs/tags/1.0.1
|
||||
48254824bb4248676bf7ce56014ff57b142b77eb refs/tags/1.0.2
|
||||
f504716c27d2e5d4144fa4794b12129301d17729 refs/tags/1.0.3
|
||||
937e904258d22af6e447a0b72c0bc67583ef64a2 refs/tags/1.0.4
|
||||
a902f1823a7ff3c9ab2fba0f992396b948eda307 refs/tags/1.0.5
|
||||
d029d9d39c87bed85b1c50adee7c41795261a192 refs/tags/1.0.6
|
||||
94cf62b3ba8d4bed62680a282d4c25f9c63c2efb refs/tags/1.1.0
|
||||
ee97538f5b81ae89698fd95938896dec5217b148 refs/tags/1.1.1
|
||||
3d2dc41a01f9e49d84f0a3925fb858bed64f702d refs/tags/1.1.2
|
||||
9bf03ff58ce34478e66aaee630e491823326fd06 refs/tags/1.1.3
|
||||
671108c96644956dddcd89dd59c203dcdb36cec7 refs/tags/1.1.4
|
||||
ad9f6723fd29591e6c0a19a9c4982cae51d65b1d refs/tags/1.1.5
|
||||
c11818f3cae0780656baa430b49e7f163f08dffd refs/tags/1.1.6
|
||||
c1805596154bb3a265fd91b8ac0c4433b4348fb0 refs/tags/1.2.0
|
||||
8c0c0a8b49e080e54e5e328cc552821ff07cd341 refs/tags/1.2.1
|
||||
7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e refs/tags/1.3.0
|
||||
@@ -0,0 +1 @@
|
||||
534c0cbbfef9d2f6e7a6519930967d75f7c60336
|
||||
@@ -0,0 +1 @@
|
||||
c35ca292f71bd0c2d7eb37e1dbac9318fae5bb68
|
||||
@@ -0,0 +1 @@
|
||||
b36804e15608a070213059cf803cc353ef88263a
|
||||
@@ -0,0 +1 @@
|
||||
80b8a6fb80ebb1ce7f5e918027b77a99fc57759c
|
||||
@@ -0,0 +1 @@
|
||||
fdaf3fe24c72ac54998e4d2361aaa5d9fedd12b5
|
||||
@@ -0,0 +1 @@
|
||||
59bb505b1a18e05342fd58d873a967b484f2f268
|
||||
@@ -0,0 +1 @@
|
||||
de54709ca9dffef94ee4f1b04f6a6483d620d1a3
|
||||
@@ -0,0 +1 @@
|
||||
d1efcb19db72befae31841116b43586350a60a72
|
||||
30
_spm/workspace-state.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"object" : {
|
||||
"artifacts" : [
|
||||
|
||||
],
|
||||
"dependencies" : [
|
||||
{
|
||||
"basedOn" : null,
|
||||
"packageRef" : {
|
||||
"identity" : "swift-collections",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/apple/swift-collections.git",
|
||||
"name" : "swift-collections"
|
||||
},
|
||||
"state" : {
|
||||
"checkoutState" : {
|
||||
"revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e",
|
||||
"version" : "1.3.0"
|
||||
},
|
||||
"name" : "sourceControlCheckout"
|
||||
},
|
||||
"subpath" : "swift-collections"
|
||||
}
|
||||
],
|
||||
"prebuilts" : [
|
||||
|
||||
]
|
||||
},
|
||||
"version" : 7
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
04122FAD2EC73C0100EF7AB3 /* KBVipSubscribeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04122FAC2EC73C0100EF7AB3 /* KBVipSubscribeCell.m */; };
|
||||
04122FB02EC73C0100EF7AB3 /* KBVipReviewItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04122FAF2EC73C0100EF7AB3 /* KBVipReviewItemCell.m */; };
|
||||
04122FB32EC73C0100EF7AB3 /* KBVipReviewListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04122FB22EC73C0100EF7AB3 /* KBVipReviewListCell.m */; };
|
||||
0419C9662F2C7693002E86D3 /* KBVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 0419C9652F2C7693002E86D3 /* KBVM.m */; };
|
||||
04286A002ECAEF2B00CE730C /* KBMoneyBtn.m in Sources */ = {isa = PBXBuildFile; fileRef = 042869FE2ECAEF2B00CE730C /* KBMoneyBtn.m */; };
|
||||
04286A032ECB0A1600CE730C /* KBSexSelVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04286A022ECB0A1600CE730C /* KBSexSelVC.m */; };
|
||||
04286A062ECC81B200CE730C /* KBSkinService.m in Sources */ = {isa = PBXBuildFile; fileRef = 04286A052ECC81B200CE730C /* KBSkinService.m */; };
|
||||
@@ -52,6 +53,29 @@
|
||||
0459D1B42EBA284C00F2D189 /* KBSkinCenterVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */; };
|
||||
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; };
|
||||
0459D1B82EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; };
|
||||
0460866B2F18D75500757C95 /* ai_test.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 0460866A2F18D75500757C95 /* ai_test.m4a */; };
|
||||
046086732F191B6900757C95 /* KBAiMainVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086722F191B6900757C95 /* KBAiMainVC.m */; };
|
||||
046086752F191CC700757C95 /* AI技术分析.txt in Resources */ = {isa = PBXBuildFile; fileRef = 046086742F191CC700757C95 /* AI技术分析.txt */; };
|
||||
0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086992F19238500757C95 /* KBAiWaveformView.m */; };
|
||||
0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086972F19238500757C95 /* KBAiRecordButton.m */; };
|
||||
046086B12F19239B00757C95 /* SubtitleSync.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086AC2F19239B00757C95 /* SubtitleSync.m */; };
|
||||
046086B22F19239B00757C95 /* TTSServiceClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086B02F19239B00757C95 /* TTSServiceClient.m */; };
|
||||
046086B32F19239B00757C95 /* AudioSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086A22F19239B00757C95 /* AudioSessionManager.m */; };
|
||||
046086B42F19239B00757C95 /* LLMStreamClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086A82F19239B00757C95 /* LLMStreamClient.m */; };
|
||||
046086B52F19239B00757C95 /* Segmenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086AA2F19239B00757C95 /* Segmenter.m */; };
|
||||
046086B62F19239B00757C95 /* TTSPlaybackPipeline.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086AE2F19239B00757C95 /* TTSPlaybackPipeline.m */; };
|
||||
046086B72F19239B00757C95 /* ConversationOrchestrator.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086A62F19239B00757C95 /* ConversationOrchestrator.m */; };
|
||||
046086B82F19239B00757C95 /* ASRStreamClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 0460869E2F19239B00757C95 /* ASRStreamClient.m */; };
|
||||
046086B92F19239B00757C95 /* AudioCaptureManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086A02F19239B00757C95 /* AudioCaptureManager.m */; };
|
||||
046086BA2F19239B00757C95 /* AudioStreamPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086A42F19239B00757C95 /* AudioStreamPlayer.m */; };
|
||||
046086BD2F1A039F00757C95 /* KBAICommentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086BC2F1A039F00757C95 /* KBAICommentView.m */; };
|
||||
046086CB2F1A092500757C95 /* comments_mock.json in Resources */ = {isa = PBXBuildFile; fileRef = 046086C62F1A092500757C95 /* comments_mock.json */; };
|
||||
046086CC2F1A092500757C95 /* KBAIReplyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086CA2F1A092500757C95 /* KBAIReplyModel.m */; };
|
||||
046086CD2F1A092500757C95 /* KBAICommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086C82F1A092500757C95 /* KBAICommentModel.m */; };
|
||||
046086D62F1A093400757C95 /* KBAICommentInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086D32F1A093400757C95 /* KBAICommentInputView.m */; };
|
||||
046086D72F1A093400757C95 /* KBAICommentFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086CF2F1A093400757C95 /* KBAICommentFooterView.m */; };
|
||||
046086D82F1A093400757C95 /* KBAIReplyCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086D52F1A093400757C95 /* KBAIReplyCell.m */; };
|
||||
046086D92F1A093400757C95 /* KBAICommentHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086D12F1A093400757C95 /* KBAICommentHeaderView.m */; };
|
||||
046131142ECF454500A6FADF /* KBKeyPreviewView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046131132ECF454500A6FADF /* KBKeyPreviewView.m */; };
|
||||
0477BDF02EBB76E30055D639 /* HomeSheetVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDEF2EBB76E30055D639 /* HomeSheetVC.m */; };
|
||||
0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0477BDF22EBB7B850055D639 /* KBDirectionIndicatorView.m */; };
|
||||
@@ -112,6 +136,32 @@
|
||||
04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A012EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m */; };
|
||||
04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */; };
|
||||
04890B122EC2F00000FABA60 /* KBMyHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04890B112EC2F00000FABA60 /* KBMyHeaderView.m */; };
|
||||
048FFD0B2F273BFC005D62AE /* KBAIHomeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0A2F273BFC005D62AE /* KBAIHomeVC.m */; };
|
||||
048FFD102F27432D005D62AE /* KBPersonaModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0D2F27432D005D62AE /* KBPersonaModel.m */; };
|
||||
048FFD112F27432D005D62AE /* KBPersonaPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0F2F27432D005D62AE /* KBPersonaPageModel.m */; };
|
||||
048FFD142F274342005D62AE /* KBPersonaChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD132F274342005D62AE /* KBPersonaChatCell.m */; };
|
||||
048FFD182F2763A5005D62AE /* KBVoiceInputBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD172F2763A5005D62AE /* KBVoiceInputBar.m */; };
|
||||
048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */; };
|
||||
048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */; };
|
||||
048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
|
||||
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
|
||||
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */; };
|
||||
048FFD302F29F3C3005D62AE /* KBAIMessageZanVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.m */; };
|
||||
048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD322F29F3D2005D62AE /* KBAIMessageChatingVC.m */; };
|
||||
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; };
|
||||
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.m */; };
|
||||
048FFD372F29F410005D62AE /* KBAIMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD392F29F410005D62AE /* KBAIMessageCell.m */; };
|
||||
048FFD392F2A24C5005D62AE /* KBAIChatMessageCacheManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */; };
|
||||
048FFD3C2F29F500005D62AE /* KBLikedCompanionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */; };
|
||||
048FFD3F2F29F600005D62AE /* KBChattedCompanionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */; };
|
||||
048FFD422F29F700005D62AE /* KBChatSessionResetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */; };
|
||||
048FFD472F2B45D4005D62AE /* AIPersonInfoVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD462F2B45D4005D62AE /* AIPersonInfoVC.m */; };
|
||||
048FFD4A2F2B4AE4005D62AE /* KBAICompanionDetailModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD492F2B4AE4005D62AE /* KBAICompanionDetailModel.m */; };
|
||||
048FFD502F2B52E7005D62AE /* AIReportVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD4F2F2B52E7005D62AE /* AIReportVC.m */; };
|
||||
048FFD512F2B68F7005D62AE /* KBPersonaModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0D2F27432D005D62AE /* KBPersonaModel.m */; };
|
||||
048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD532F2B9C3D005D62AE /* KBChatAssistantCell.m */; };
|
||||
048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD552F2B9C3D005D62AE /* KBChatUserCell.m */; };
|
||||
0498BD622EDFFC12006CC1D5 /* KBMyVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BD612EDFFC12006CC1D5 /* KBMyVM.m */; };
|
||||
0498BD652EE0116D006CC1D5 /* KBEmailLoginVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BD642EE0116D006CC1D5 /* KBEmailLoginVC.m */; };
|
||||
0498BD682EE01180006CC1D5 /* KBEmailRegistVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BD672EE01180006CC1D5 /* KBEmailRegistVC.m */; };
|
||||
@@ -170,6 +220,22 @@
|
||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 04C6EADC2EAF8CEB0089C901 /* KBToolBar.m */; };
|
||||
04D1F6B22EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */; };
|
||||
04D1F6B32EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */; };
|
||||
04E0383E2F1A7C30002CA5A0 /* KBCustomTabBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0383D2F1A7C30002CA5A0 /* KBCustomTabBar.m */; };
|
||||
04E038D82F20BFFB002CA5A0 /* websocket-api.md in Resources */ = {isa = PBXBuildFile; fileRef = 04E038D72F20BFFB002CA5A0 /* websocket-api.md */; };
|
||||
04E038DD2F20C420002CA5A0 /* VoiceChatStreamingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038DA2F20C420002CA5A0 /* VoiceChatStreamingManager.m */; };
|
||||
04E038DE2F20C420002CA5A0 /* VoiceChatWebSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038DC2F20C420002CA5A0 /* VoiceChatWebSocketClient.m */; };
|
||||
04E038E32F20E500002CA5A0 /* deepgramAPI.md in Resources */ = {isa = PBXBuildFile; fileRef = 04E038E22F20E500002CA5A0 /* deepgramAPI.md */; };
|
||||
04E038E82F20E877002CA5A0 /* DeepgramWebSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038E72F20E877002CA5A0 /* DeepgramWebSocketClient.m */; };
|
||||
04E038E92F20E877002CA5A0 /* DeepgramStreamingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038E52F20E877002CA5A0 /* DeepgramStreamingManager.m */; };
|
||||
04E038EF2F21F0EC002CA5A0 /* AiVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038EE2F21F0EC002CA5A0 /* AiVM.m */; };
|
||||
04E0394B2F236E75002CA5A0 /* KBChatUserMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0394A2F236E75002CA5A0 /* KBChatUserMessageCell.m */; };
|
||||
04E0394C2F236E75002CA5A0 /* KBChatTimeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039482F236E75002CA5A0 /* KBChatTimeCell.m */; };
|
||||
04E0394D2F236E75002CA5A0 /* KBChatAssistantMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039432F236E75002CA5A0 /* KBChatAssistantMessageCell.m */; };
|
||||
04E0394E2F236E75002CA5A0 /* KBChatTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039452F236E75002CA5A0 /* KBChatTableView.m */; };
|
||||
04E0394F2F236E75002CA5A0 /* KBChatTableView_Usage.md in Resources */ = {isa = PBXBuildFile; fileRef = 04E039462F236E75002CA5A0 /* KBChatTableView_Usage.md */; };
|
||||
04E039522F2387D2002CA5A0 /* KBAiChatMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039512F2387D2002CA5A0 /* KBAiChatMessage.m */; };
|
||||
04E0B1022F300001002CA5A0 /* KBVoiceToTextManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0B1012F300001002CA5A0 /* KBVoiceToTextManager.m */; };
|
||||
04E0B2022F300002002CA5A0 /* KBVoiceRecordManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0B2012F300002002CA5A0 /* KBVoiceRecordManager.m */; };
|
||||
04E161832F10E6470022C23B /* normal_hei_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161812F10E6470022C23B /* normal_hei_them.zip */; };
|
||||
04E161842F10E6470022C23B /* normal_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161822F10E6470022C23B /* normal_them.zip */; };
|
||||
04FC95672EB0546C007BD342 /* KBKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95652EB0546C007BD342 /* KBKey.m */; };
|
||||
@@ -182,7 +248,6 @@
|
||||
04FC95B22EB0B2CC007BD342 /* KBSettingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95B12EB0B2CC007BD342 /* KBSettingView.m */; };
|
||||
04FC95C92EB1E4C9007BD342 /* BaseNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95C82EB1E4C9007BD342 /* BaseNavigationController.m */; };
|
||||
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */; };
|
||||
04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95CE2EB1E7A1007BD342 /* HomeVC.m */; };
|
||||
04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D12EB1E7AE007BD342 /* MyVC.m */; };
|
||||
04FC95D72EB1EA16007BD342 /* BaseTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D62EB1EA16007BD342 /* BaseTableView.m */; };
|
||||
04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D42EB1EA16007BD342 /* BaseCell.m */; };
|
||||
@@ -224,6 +289,9 @@
|
||||
A1B2C9032FBD000100000001 /* KBBackspaceLongPressHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9022FBD000100000001 /* KBBackspaceLongPressHandler.m */; };
|
||||
A1B2C9052FBD000200000001 /* KBBackspaceUndoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9042FBD000200000001 /* KBBackspaceUndoManager.m */; };
|
||||
A1B2C9092FBD000200000005 /* KBInputBufferManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9082FBD000200000004 /* KBInputBufferManager.m */; };
|
||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9212FC9000100000001 /* KBChatMessage.m */; };
|
||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9232FC9000100000001 /* KBChatMessageCell.m */; };
|
||||
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9252FC9000100000001 /* KBChatPanelView.m */; };
|
||||
A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2D7012EB8C00100000001 /* KBLangTestVC.m */; };
|
||||
A1B2E1012EBC7AAA00000001 /* KBTopThreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0022EBC7AAA00000001 /* KBTopThreeView.m */; };
|
||||
A1B2E1022EBC7AAA00000001 /* HomeHotCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2E0042EBC7AAA00000001 /* HomeHotCell.m */; };
|
||||
@@ -290,6 +358,8 @@
|
||||
04122FAF2EC73C0100EF7AB3 /* KBVipReviewItemCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVipReviewItemCell.m; sourceTree = "<group>"; };
|
||||
04122FB12EC73C0100EF7AB3 /* KBVipReviewListCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBVipReviewListCell.h; sourceTree = "<group>"; };
|
||||
04122FB22EC73C0100EF7AB3 /* KBVipReviewListCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVipReviewListCell.m; sourceTree = "<group>"; };
|
||||
0419C9642F2C7693002E86D3 /* KBVM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBVM.h; sourceTree = "<group>"; };
|
||||
0419C9652F2C7693002E86D3 /* KBVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVM.m; sourceTree = "<group>"; };
|
||||
042869FD2ECAEF2B00CE730C /* KBMoneyBtn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMoneyBtn.h; sourceTree = "<group>"; };
|
||||
042869FE2ECAEF2B00CE730C /* KBMoneyBtn.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMoneyBtn.m; sourceTree = "<group>"; };
|
||||
04286A012ECB0A1600CE730C /* KBSexSelVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSexSelVC.h; sourceTree = "<group>"; };
|
||||
@@ -323,6 +393,49 @@
|
||||
0459D1B32EBA284C00F2D189 /* KBSkinCenterVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinCenterVC.m; sourceTree = "<group>"; };
|
||||
0459D1B52EBA287900F2D189 /* KBSkinManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinManager.h; sourceTree = "<group>"; };
|
||||
0459D1B62EBA287900F2D189 /* KBSkinManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinManager.m; sourceTree = "<group>"; };
|
||||
0460866A2F18D75500757C95 /* ai_test.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = ai_test.m4a; sourceTree = "<group>"; };
|
||||
046086712F191B6900757C95 /* KBAiMainVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAiMainVC.h; sourceTree = "<group>"; };
|
||||
046086722F191B6900757C95 /* KBAiMainVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAiMainVC.m; sourceTree = "<group>"; };
|
||||
046086742F191CC700757C95 /* AI技术分析.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "AI技术分析.txt"; sourceTree = "<group>"; };
|
||||
046086962F19238500757C95 /* KBAiRecordButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAiRecordButton.h; sourceTree = "<group>"; };
|
||||
046086972F19238500757C95 /* KBAiRecordButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAiRecordButton.m; sourceTree = "<group>"; };
|
||||
046086982F19238500757C95 /* KBAiWaveformView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAiWaveformView.h; sourceTree = "<group>"; };
|
||||
046086992F19238500757C95 /* KBAiWaveformView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAiWaveformView.m; sourceTree = "<group>"; };
|
||||
0460869D2F19239B00757C95 /* ASRStreamClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASRStreamClient.h; sourceTree = "<group>"; };
|
||||
0460869E2F19239B00757C95 /* ASRStreamClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASRStreamClient.m; sourceTree = "<group>"; };
|
||||
0460869F2F19239B00757C95 /* AudioCaptureManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioCaptureManager.h; sourceTree = "<group>"; };
|
||||
046086A02F19239B00757C95 /* AudioCaptureManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioCaptureManager.m; sourceTree = "<group>"; };
|
||||
046086A12F19239B00757C95 /* AudioSessionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioSessionManager.h; sourceTree = "<group>"; };
|
||||
046086A22F19239B00757C95 /* AudioSessionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioSessionManager.m; sourceTree = "<group>"; };
|
||||
046086A32F19239B00757C95 /* AudioStreamPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioStreamPlayer.h; sourceTree = "<group>"; };
|
||||
046086A42F19239B00757C95 /* AudioStreamPlayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioStreamPlayer.m; sourceTree = "<group>"; };
|
||||
046086A52F19239B00757C95 /* ConversationOrchestrator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConversationOrchestrator.h; sourceTree = "<group>"; };
|
||||
046086A62F19239B00757C95 /* ConversationOrchestrator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ConversationOrchestrator.m; sourceTree = "<group>"; };
|
||||
046086A72F19239B00757C95 /* LLMStreamClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LLMStreamClient.h; sourceTree = "<group>"; };
|
||||
046086A82F19239B00757C95 /* LLMStreamClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LLMStreamClient.m; sourceTree = "<group>"; };
|
||||
046086A92F19239B00757C95 /* Segmenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Segmenter.h; sourceTree = "<group>"; };
|
||||
046086AA2F19239B00757C95 /* Segmenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Segmenter.m; sourceTree = "<group>"; };
|
||||
046086AB2F19239B00757C95 /* SubtitleSync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SubtitleSync.h; sourceTree = "<group>"; };
|
||||
046086AC2F19239B00757C95 /* SubtitleSync.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SubtitleSync.m; sourceTree = "<group>"; };
|
||||
046086AD2F19239B00757C95 /* TTSPlaybackPipeline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TTSPlaybackPipeline.h; sourceTree = "<group>"; };
|
||||
046086AE2F19239B00757C95 /* TTSPlaybackPipeline.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TTSPlaybackPipeline.m; sourceTree = "<group>"; };
|
||||
046086AF2F19239B00757C95 /* TTSServiceClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TTSServiceClient.h; sourceTree = "<group>"; };
|
||||
046086B02F19239B00757C95 /* TTSServiceClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TTSServiceClient.m; sourceTree = "<group>"; };
|
||||
046086BB2F1A039F00757C95 /* KBAICommentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAICommentView.h; sourceTree = "<group>"; };
|
||||
046086BC2F1A039F00757C95 /* KBAICommentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAICommentView.m; sourceTree = "<group>"; };
|
||||
046086C62F1A092500757C95 /* comments_mock.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = comments_mock.json; sourceTree = "<group>"; };
|
||||
046086C72F1A092500757C95 /* KBAICommentModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAICommentModel.h; sourceTree = "<group>"; };
|
||||
046086C82F1A092500757C95 /* KBAICommentModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAICommentModel.m; sourceTree = "<group>"; };
|
||||
046086C92F1A092500757C95 /* KBAIReplyModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIReplyModel.h; sourceTree = "<group>"; };
|
||||
046086CA2F1A092500757C95 /* KBAIReplyModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIReplyModel.m; sourceTree = "<group>"; };
|
||||
046086CE2F1A093400757C95 /* KBAICommentFooterView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAICommentFooterView.h; sourceTree = "<group>"; };
|
||||
046086CF2F1A093400757C95 /* KBAICommentFooterView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAICommentFooterView.m; sourceTree = "<group>"; };
|
||||
046086D02F1A093400757C95 /* KBAICommentHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAICommentHeaderView.h; sourceTree = "<group>"; };
|
||||
046086D12F1A093400757C95 /* KBAICommentHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAICommentHeaderView.m; sourceTree = "<group>"; };
|
||||
046086D22F1A093400757C95 /* KBAICommentInputView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAICommentInputView.h; sourceTree = "<group>"; };
|
||||
046086D32F1A093400757C95 /* KBAICommentInputView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAICommentInputView.m; sourceTree = "<group>"; };
|
||||
046086D42F1A093400757C95 /* KBAIReplyCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIReplyCell.h; sourceTree = "<group>"; };
|
||||
046086D52F1A093400757C95 /* KBAIReplyCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIReplyCell.m; sourceTree = "<group>"; };
|
||||
046131122ECF454500A6FADF /* KBKeyPreviewView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyPreviewView.h; sourceTree = "<group>"; };
|
||||
046131132ECF454500A6FADF /* KBKeyPreviewView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyPreviewView.m; sourceTree = "<group>"; };
|
||||
0477BDEE2EBB76E30055D639 /* HomeSheetVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeSheetVC.h; sourceTree = "<group>"; };
|
||||
@@ -433,6 +546,56 @@
|
||||
04890A032EC0BBBB00FABA60 /* KBCategoryTitleImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCategoryTitleImageView.m; sourceTree = "<group>"; };
|
||||
04890B102EC2F00000FABA60 /* KBMyHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyHeaderView.h; sourceTree = "<group>"; };
|
||||
04890B112EC2F00000FABA60 /* KBMyHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyHeaderView.m; sourceTree = "<group>"; };
|
||||
048FFD092F273BFC005D62AE /* KBAIHomeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIHomeVC.h; sourceTree = "<group>"; };
|
||||
048FFD0A2F273BFC005D62AE /* KBAIHomeVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIHomeVC.m; sourceTree = "<group>"; };
|
||||
048FFD0C2F27432D005D62AE /* KBPersonaModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPersonaModel.h; sourceTree = "<group>"; };
|
||||
048FFD0D2F27432D005D62AE /* KBPersonaModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPersonaModel.m; sourceTree = "<group>"; };
|
||||
048FFD0E2F27432D005D62AE /* KBPersonaPageModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPersonaPageModel.h; sourceTree = "<group>"; };
|
||||
048FFD0F2F27432D005D62AE /* KBPersonaPageModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPersonaPageModel.m; sourceTree = "<group>"; };
|
||||
048FFD122F274342005D62AE /* KBPersonaChatCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPersonaChatCell.h; sourceTree = "<group>"; };
|
||||
048FFD132F274342005D62AE /* KBPersonaChatCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPersonaChatCell.m; sourceTree = "<group>"; };
|
||||
048FFD162F2763A5005D62AE /* KBVoiceInputBar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBVoiceInputBar.h; sourceTree = "<group>"; };
|
||||
048FFD172F2763A5005D62AE /* KBVoiceInputBar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVoiceInputBar.m; sourceTree = "<group>"; };
|
||||
048FFD192F277486005D62AE /* KBChatHistoryModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatHistoryModel.h; sourceTree = "<group>"; };
|
||||
048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatHistoryModel.m; sourceTree = "<group>"; };
|
||||
048FFD1B2F277486005D62AE /* KBChatHistoryPageModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatHistoryPageModel.h; sourceTree = "<group>"; };
|
||||
048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatHistoryPageModel.m; sourceTree = "<group>"; };
|
||||
048FFD222F28A836005D62AE /* KBChatLimitPopView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatLimitPopView.h; sourceTree = "<group>"; };
|
||||
048FFD232F28A836005D62AE /* KBChatLimitPopView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatLimitPopView.m; sourceTree = "<group>"; };
|
||||
048FFD252F28C6CF005D62AE /* KBImagePositionButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBImagePositionButton.h; sourceTree = "<group>"; };
|
||||
048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBImagePositionButton.m; sourceTree = "<group>"; };
|
||||
048FFD282F28E99A005D62AE /* KBCommentModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCommentModel.h; sourceTree = "<group>"; };
|
||||
048FFD292F28E99A005D62AE /* KBCommentModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCommentModel.m; sourceTree = "<group>"; };
|
||||
048FFD2B2F29F356005D62AE /* KBAIMessageVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageVC.h; sourceTree = "<group>"; };
|
||||
048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageVC.m; sourceTree = "<group>"; };
|
||||
048FFD2E2F29F3C3005D62AE /* KBAIMessageZanVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageZanVC.h; sourceTree = "<group>"; };
|
||||
048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageZanVC.m; sourceTree = "<group>"; };
|
||||
048FFD312F29F3D2005D62AE /* KBAIMessageChatingVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageChatingVC.h; sourceTree = "<group>"; };
|
||||
048FFD322F29F3D2005D62AE /* KBAIMessageChatingVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageChatingVC.m; sourceTree = "<group>"; };
|
||||
048FFD342F29F88E005D62AE /* AIMessageVM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIMessageVM.h; sourceTree = "<group>"; };
|
||||
048FFD352F29F400005D62AE /* KBAIMessageListVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageListVC.h; sourceTree = "<group>"; };
|
||||
048FFD352F29F88E005D62AE /* AIMessageVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIMessageVM.m; sourceTree = "<group>"; };
|
||||
048FFD362F29F400005D62AE /* KBAIMessageListVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageListVC.m; sourceTree = "<group>"; };
|
||||
048FFD372F2A24C5005D62AE /* KBAIChatMessageCacheManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIChatMessageCacheManager.h; sourceTree = "<group>"; };
|
||||
048FFD382F29F410005D62AE /* KBAIMessageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageCell.h; sourceTree = "<group>"; };
|
||||
048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIChatMessageCacheManager.m; sourceTree = "<group>"; };
|
||||
048FFD392F29F410005D62AE /* KBAIMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageCell.m; sourceTree = "<group>"; };
|
||||
048FFD3A2F29F500005D62AE /* KBLikedCompanionModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLikedCompanionModel.h; sourceTree = "<group>"; };
|
||||
048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLikedCompanionModel.m; sourceTree = "<group>"; };
|
||||
048FFD3D2F29F600005D62AE /* KBChattedCompanionModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChattedCompanionModel.h; sourceTree = "<group>"; };
|
||||
048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChattedCompanionModel.m; sourceTree = "<group>"; };
|
||||
048FFD402F29F700005D62AE /* KBChatSessionResetModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatSessionResetModel.h; sourceTree = "<group>"; };
|
||||
048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatSessionResetModel.m; sourceTree = "<group>"; };
|
||||
048FFD452F2B45D4005D62AE /* AIPersonInfoVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIPersonInfoVC.h; sourceTree = "<group>"; };
|
||||
048FFD462F2B45D4005D62AE /* AIPersonInfoVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIPersonInfoVC.m; sourceTree = "<group>"; };
|
||||
048FFD482F2B4AE4005D62AE /* KBAICompanionDetailModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAICompanionDetailModel.h; sourceTree = "<group>"; };
|
||||
048FFD492F2B4AE4005D62AE /* KBAICompanionDetailModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAICompanionDetailModel.m; sourceTree = "<group>"; };
|
||||
048FFD4E2F2B52E7005D62AE /* AIReportVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AIReportVC.h; sourceTree = "<group>"; };
|
||||
048FFD4F2F2B52E7005D62AE /* AIReportVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIReportVC.m; sourceTree = "<group>"; };
|
||||
048FFD522F2B9C3D005D62AE /* KBChatAssistantCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatAssistantCell.h; sourceTree = "<group>"; };
|
||||
048FFD532F2B9C3D005D62AE /* KBChatAssistantCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatAssistantCell.m; sourceTree = "<group>"; };
|
||||
048FFD542F2B9C3D005D62AE /* KBChatUserCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatUserCell.h; sourceTree = "<group>"; };
|
||||
048FFD552F2B9C3D005D62AE /* KBChatUserCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatUserCell.m; sourceTree = "<group>"; };
|
||||
0498BD5E2EDF2157006CC1D5 /* KBBizCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBBizCode.h; sourceTree = "<group>"; };
|
||||
0498BD602EDFFC12006CC1D5 /* KBMyVM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBMyVM.h; sourceTree = "<group>"; };
|
||||
0498BD612EDFFC12006CC1D5 /* KBMyVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyVM.m; sourceTree = "<group>"; };
|
||||
@@ -534,6 +697,35 @@
|
||||
04C6EAE12EAF940F0089C901 /* KBPermissionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPermissionViewController.m; sourceTree = "<group>"; };
|
||||
04D1F6B02EDFF10A00B12345 /* KBSkinInstallBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinInstallBridge.h; sourceTree = "<group>"; };
|
||||
04D1F6B12EDFF10A00B12345 /* KBSkinInstallBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinInstallBridge.m; sourceTree = "<group>"; };
|
||||
04E0383C2F1A7C30002CA5A0 /* KBCustomTabBar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCustomTabBar.h; sourceTree = "<group>"; };
|
||||
04E0383D2F1A7C30002CA5A0 /* KBCustomTabBar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBCustomTabBar.m; sourceTree = "<group>"; };
|
||||
04E038D72F20BFFB002CA5A0 /* websocket-api.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "websocket-api.md"; sourceTree = "<group>"; };
|
||||
04E038D92F20C420002CA5A0 /* VoiceChatStreamingManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VoiceChatStreamingManager.h; sourceTree = "<group>"; };
|
||||
04E038DA2F20C420002CA5A0 /* VoiceChatStreamingManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VoiceChatStreamingManager.m; sourceTree = "<group>"; };
|
||||
04E038DB2F20C420002CA5A0 /* VoiceChatWebSocketClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VoiceChatWebSocketClient.h; sourceTree = "<group>"; };
|
||||
04E038DC2F20C420002CA5A0 /* VoiceChatWebSocketClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VoiceChatWebSocketClient.m; sourceTree = "<group>"; };
|
||||
04E038E22F20E500002CA5A0 /* deepgramAPI.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = deepgramAPI.md; sourceTree = "<group>"; };
|
||||
04E038E42F20E877002CA5A0 /* DeepgramStreamingManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeepgramStreamingManager.h; sourceTree = "<group>"; };
|
||||
04E038E52F20E877002CA5A0 /* DeepgramStreamingManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DeepgramStreamingManager.m; sourceTree = "<group>"; };
|
||||
04E038E62F20E877002CA5A0 /* DeepgramWebSocketClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeepgramWebSocketClient.h; sourceTree = "<group>"; };
|
||||
04E038E72F20E877002CA5A0 /* DeepgramWebSocketClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DeepgramWebSocketClient.m; sourceTree = "<group>"; };
|
||||
04E038ED2F21F0EC002CA5A0 /* AiVM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AiVM.h; sourceTree = "<group>"; };
|
||||
04E038EE2F21F0EC002CA5A0 /* AiVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AiVM.m; sourceTree = "<group>"; };
|
||||
04E039422F236E75002CA5A0 /* KBChatAssistantMessageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatAssistantMessageCell.h; sourceTree = "<group>"; };
|
||||
04E039432F236E75002CA5A0 /* KBChatAssistantMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatAssistantMessageCell.m; sourceTree = "<group>"; };
|
||||
04E039442F236E75002CA5A0 /* KBChatTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatTableView.h; sourceTree = "<group>"; };
|
||||
04E039452F236E75002CA5A0 /* KBChatTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatTableView.m; sourceTree = "<group>"; };
|
||||
04E039462F236E75002CA5A0 /* KBChatTableView_Usage.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = KBChatTableView_Usage.md; sourceTree = "<group>"; };
|
||||
04E039472F236E75002CA5A0 /* KBChatTimeCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatTimeCell.h; sourceTree = "<group>"; };
|
||||
04E039482F236E75002CA5A0 /* KBChatTimeCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatTimeCell.m; sourceTree = "<group>"; };
|
||||
04E039492F236E75002CA5A0 /* KBChatUserMessageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatUserMessageCell.h; sourceTree = "<group>"; };
|
||||
04E0394A2F236E75002CA5A0 /* KBChatUserMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatUserMessageCell.m; sourceTree = "<group>"; };
|
||||
04E039502F2387D2002CA5A0 /* KBAiChatMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAiChatMessage.h; sourceTree = "<group>"; };
|
||||
04E039512F2387D2002CA5A0 /* KBAiChatMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAiChatMessage.m; sourceTree = "<group>"; };
|
||||
04E0B1002F300001002CA5A0 /* KBVoiceToTextManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBVoiceToTextManager.h; sourceTree = "<group>"; };
|
||||
04E0B1012F300001002CA5A0 /* KBVoiceToTextManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVoiceToTextManager.m; sourceTree = "<group>"; };
|
||||
04E0B2002F300002002CA5A0 /* KBVoiceRecordManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBVoiceRecordManager.h; sourceTree = "<group>"; };
|
||||
04E0B2012F300002002CA5A0 /* KBVoiceRecordManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVoiceRecordManager.m; sourceTree = "<group>"; };
|
||||
04E161812F10E6470022C23B /* normal_hei_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_hei_them.zip; sourceTree = "<group>"; };
|
||||
04E161822F10E6470022C23B /* normal_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_them.zip; sourceTree = "<group>"; };
|
||||
04FC953A2EAFAE56007BD342 /* KeyBoardPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyBoardPrefixHeader.pch; sourceTree = "<group>"; };
|
||||
@@ -557,8 +749,6 @@
|
||||
04FC95C82EB1E4C9007BD342 /* BaseNavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseNavigationController.m; sourceTree = "<group>"; };
|
||||
04FC95CA2EB1E780007BD342 /* BaseTabBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseTabBarController.h; sourceTree = "<group>"; };
|
||||
04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseTabBarController.m; sourceTree = "<group>"; };
|
||||
04FC95CD2EB1E7A1007BD342 /* HomeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeVC.h; sourceTree = "<group>"; };
|
||||
04FC95CE2EB1E7A1007BD342 /* HomeVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeVC.m; sourceTree = "<group>"; };
|
||||
04FC95D02EB1E7AE007BD342 /* MyVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyVC.h; sourceTree = "<group>"; };
|
||||
04FC95D12EB1E7AE007BD342 /* MyVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyVC.m; sourceTree = "<group>"; };
|
||||
04FC95D32EB1EA16007BD342 /* BaseCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseCell.h; sourceTree = "<group>"; };
|
||||
@@ -639,6 +829,12 @@
|
||||
A1B2C9042FBD000200000001 /* KBBackspaceUndoManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBBackspaceUndoManager.m; sourceTree = "<group>"; };
|
||||
A1B2C9072FBD000200000003 /* KBInputBufferManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBInputBufferManager.h; sourceTree = "<group>"; };
|
||||
A1B2C9082FBD000200000004 /* KBInputBufferManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBInputBufferManager.m; sourceTree = "<group>"; };
|
||||
A1B2C9202FC9000100000001 /* KBChatMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatMessage.h; sourceTree = "<group>"; };
|
||||
A1B2C9212FC9000100000001 /* KBChatMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatMessage.m; sourceTree = "<group>"; };
|
||||
A1B2C9222FC9000100000001 /* KBChatMessageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatMessageCell.h; sourceTree = "<group>"; };
|
||||
A1B2C9232FC9000100000001 /* KBChatMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatMessageCell.m; sourceTree = "<group>"; };
|
||||
A1B2C9242FC9000100000001 /* KBChatPanelView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatPanelView.h; sourceTree = "<group>"; };
|
||||
A1B2C9252FC9000100000001 /* KBChatPanelView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatPanelView.m; sourceTree = "<group>"; };
|
||||
A1B2D7002EB8C00100000001 /* KBLangTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLangTestVC.h; sourceTree = "<group>"; };
|
||||
A1B2D7012EB8C00100000001 /* KBLangTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLangTestVC.m; sourceTree = "<group>"; };
|
||||
A1B2E0012EBC7AAA00000001 /* KBTopThreeView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBTopThreeView.h; sourceTree = "<group>"; };
|
||||
@@ -686,6 +882,7 @@
|
||||
041007D02ECE010100D203BB /* Resource */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0460866A2F18D75500757C95 /* ai_test.m4a */,
|
||||
04E161812F10E6470022C23B /* normal_hei_them.zip */,
|
||||
04E161822F10E6470022C23B /* normal_them.zip */,
|
||||
A1B2C3EC2F20000000000001 /* kb_words.txt */,
|
||||
@@ -778,6 +975,28 @@
|
||||
path = WMDragView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0419C9632F2C7630002E86D3 /* VM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0419C9642F2C7693002E86D3 /* KBVM.h */,
|
||||
0419C9652F2C7693002E86D3 /* KBVM.m */,
|
||||
);
|
||||
path = VM;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0419C9672F2C78E4002E86D3 /* Chat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A1B2C9242FC9000100000001 /* KBChatPanelView.h */,
|
||||
A1B2C9252FC9000100000001 /* KBChatPanelView.m */,
|
||||
048FFD522F2B9C3D005D62AE /* KBChatAssistantCell.h */,
|
||||
048FFD532F2B9C3D005D62AE /* KBChatAssistantCell.m */,
|
||||
048FFD542F2B9C3D005D62AE /* KBChatUserCell.h */,
|
||||
048FFD552F2B9C3D005D62AE /* KBChatUserCell.m */,
|
||||
);
|
||||
path = Chat;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0450ABFB2EF11E4400B6AF06 /* Converts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -840,6 +1059,138 @@
|
||||
path = StoreKit2Manager;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0460866C2F191A5100757C95 /* M */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
046086C62F1A092500757C95 /* comments_mock.json */,
|
||||
046086C72F1A092500757C95 /* KBAICommentModel.h */,
|
||||
046086C82F1A092500757C95 /* KBAICommentModel.m */,
|
||||
046086C92F1A092500757C95 /* KBAIReplyModel.h */,
|
||||
046086CA2F1A092500757C95 /* KBAIReplyModel.m */,
|
||||
04E039502F2387D2002CA5A0 /* KBAiChatMessage.h */,
|
||||
04E039512F2387D2002CA5A0 /* KBAiChatMessage.m */,
|
||||
048FFD0C2F27432D005D62AE /* KBPersonaModel.h */,
|
||||
048FFD0D2F27432D005D62AE /* KBPersonaModel.m */,
|
||||
048FFD0E2F27432D005D62AE /* KBPersonaPageModel.h */,
|
||||
048FFD0F2F27432D005D62AE /* KBPersonaPageModel.m */,
|
||||
048FFD192F277486005D62AE /* KBChatHistoryModel.h */,
|
||||
048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */,
|
||||
048FFD1B2F277486005D62AE /* KBChatHistoryPageModel.h */,
|
||||
048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */,
|
||||
048FFD282F28E99A005D62AE /* KBCommentModel.h */,
|
||||
048FFD292F28E99A005D62AE /* KBCommentModel.m */,
|
||||
048FFD3A2F29F500005D62AE /* KBLikedCompanionModel.h */,
|
||||
048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */,
|
||||
048FFD3D2F29F600005D62AE /* KBChattedCompanionModel.h */,
|
||||
048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */,
|
||||
048FFD402F29F700005D62AE /* KBChatSessionResetModel.h */,
|
||||
048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */,
|
||||
048FFD372F2A24C5005D62AE /* KBAIChatMessageCacheManager.h */,
|
||||
048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */,
|
||||
048FFD482F2B4AE4005D62AE /* KBAICompanionDetailModel.h */,
|
||||
048FFD492F2B4AE4005D62AE /* KBAICompanionDetailModel.m */,
|
||||
);
|
||||
path = M;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0460866D2F191A5100757C95 /* V */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
048FFD3D2F2B2A14005D62AE /* PopView */,
|
||||
048FFD3C2F2B2905005D62AE /* Chat */,
|
||||
048FFD3B2F2B289C005D62AE /* Comment */,
|
||||
048FFD3A2F2B2869005D62AE /* Message */,
|
||||
046086962F19238500757C95 /* KBAiRecordButton.h */,
|
||||
046086972F19238500757C95 /* KBAiRecordButton.m */,
|
||||
046086982F19238500757C95 /* KBAiWaveformView.h */,
|
||||
046086992F19238500757C95 /* KBAiWaveformView.m */,
|
||||
04E039462F236E75002CA5A0 /* KBChatTableView_Usage.md */,
|
||||
048FFD162F2763A5005D62AE /* KBVoiceInputBar.h */,
|
||||
048FFD172F2763A5005D62AE /* KBVoiceInputBar.m */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0460866E2F191A5100757C95 /* VC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
046086712F191B6900757C95 /* KBAiMainVC.h */,
|
||||
046086722F191B6900757C95 /* KBAiMainVC.m */,
|
||||
048FFD092F273BFC005D62AE /* KBAIHomeVC.h */,
|
||||
048FFD0A2F273BFC005D62AE /* KBAIHomeVC.m */,
|
||||
048FFD2B2F29F356005D62AE /* KBAIMessageVC.h */,
|
||||
048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */,
|
||||
048FFD2E2F29F3C3005D62AE /* KBAIMessageZanVC.h */,
|
||||
048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.m */,
|
||||
048FFD312F29F3D2005D62AE /* KBAIMessageChatingVC.h */,
|
||||
048FFD322F29F3D2005D62AE /* KBAIMessageChatingVC.m */,
|
||||
048FFD352F29F400005D62AE /* KBAIMessageListVC.h */,
|
||||
048FFD362F29F400005D62AE /* KBAIMessageListVC.m */,
|
||||
048FFD452F2B45D4005D62AE /* AIPersonInfoVC.h */,
|
||||
048FFD462F2B45D4005D62AE /* AIPersonInfoVC.m */,
|
||||
048FFD4E2F2B52E7005D62AE /* AIReportVC.h */,
|
||||
048FFD4F2F2B52E7005D62AE /* AIReportVC.m */,
|
||||
);
|
||||
path = VC;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0460866F2F191A5100757C95 /* VM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0460869D2F19239B00757C95 /* ASRStreamClient.h */,
|
||||
0460869E2F19239B00757C95 /* ASRStreamClient.m */,
|
||||
0460869F2F19239B00757C95 /* AudioCaptureManager.h */,
|
||||
046086A02F19239B00757C95 /* AudioCaptureManager.m */,
|
||||
046086A12F19239B00757C95 /* AudioSessionManager.h */,
|
||||
046086A22F19239B00757C95 /* AudioSessionManager.m */,
|
||||
046086A32F19239B00757C95 /* AudioStreamPlayer.h */,
|
||||
046086A42F19239B00757C95 /* AudioStreamPlayer.m */,
|
||||
046086A52F19239B00757C95 /* ConversationOrchestrator.h */,
|
||||
046086A62F19239B00757C95 /* ConversationOrchestrator.m */,
|
||||
046086A72F19239B00757C95 /* LLMStreamClient.h */,
|
||||
046086A82F19239B00757C95 /* LLMStreamClient.m */,
|
||||
046086A92F19239B00757C95 /* Segmenter.h */,
|
||||
046086AA2F19239B00757C95 /* Segmenter.m */,
|
||||
046086AB2F19239B00757C95 /* SubtitleSync.h */,
|
||||
046086AC2F19239B00757C95 /* SubtitleSync.m */,
|
||||
046086AD2F19239B00757C95 /* TTSPlaybackPipeline.h */,
|
||||
046086AE2F19239B00757C95 /* TTSPlaybackPipeline.m */,
|
||||
046086AF2F19239B00757C95 /* TTSServiceClient.h */,
|
||||
046086B02F19239B00757C95 /* TTSServiceClient.m */,
|
||||
04E038D92F20C420002CA5A0 /* VoiceChatStreamingManager.h */,
|
||||
04E038DA2F20C420002CA5A0 /* VoiceChatStreamingManager.m */,
|
||||
04E038DB2F20C420002CA5A0 /* VoiceChatWebSocketClient.h */,
|
||||
04E038DC2F20C420002CA5A0 /* VoiceChatWebSocketClient.m */,
|
||||
04E038E42F20E877002CA5A0 /* DeepgramStreamingManager.h */,
|
||||
04E038E52F20E877002CA5A0 /* DeepgramStreamingManager.m */,
|
||||
04E0B1002F300001002CA5A0 /* KBVoiceToTextManager.h */,
|
||||
04E0B1012F300001002CA5A0 /* KBVoiceToTextManager.m */,
|
||||
04E0B2002F300002002CA5A0 /* KBVoiceRecordManager.h */,
|
||||
04E0B2012F300002002CA5A0 /* KBVoiceRecordManager.m */,
|
||||
04E038E62F20E877002CA5A0 /* DeepgramWebSocketClient.h */,
|
||||
04E038E72F20E877002CA5A0 /* DeepgramWebSocketClient.m */,
|
||||
04E038ED2F21F0EC002CA5A0 /* AiVM.h */,
|
||||
04E038EE2F21F0EC002CA5A0 /* AiVM.m */,
|
||||
048FFD342F29F88E005D62AE /* AIMessageVM.h */,
|
||||
048FFD352F29F88E005D62AE /* AIMessageVM.m */,
|
||||
);
|
||||
path = VM;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
046086702F191A5100757C95 /* AiTalk */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
046086742F191CC700757C95 /* AI技术分析.txt */,
|
||||
04E038D72F20BFFB002CA5A0 /* websocket-api.md */,
|
||||
04E038E22F20E500002CA5A0 /* deepgramAPI.md */,
|
||||
0460866C2F191A5100757C95 /* M */,
|
||||
0460866D2F191A5100757C95 /* V */,
|
||||
0460866E2F191A5100757C95 /* VC */,
|
||||
0460866F2F191A5100757C95 /* VM */,
|
||||
);
|
||||
path = AiTalk;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0477BD942EBAFF4E0055D639 /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -963,6 +1314,8 @@
|
||||
049FB20D2EC1CD2800FAB05D /* KBAlert.m */,
|
||||
042869FD2ECAEF2B00CE730C /* KBMoneyBtn.h */,
|
||||
042869FE2ECAEF2B00CE730C /* KBMoneyBtn.m */,
|
||||
048FFD252F28C6CF005D62AE /* KBImagePositionButton.h */,
|
||||
048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@@ -1043,6 +1396,58 @@
|
||||
path = UICollectionViewLeftAlignedLayout;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
048FFD3A2F2B2869005D62AE /* Message */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
048FFD382F29F410005D62AE /* KBAIMessageCell.h */,
|
||||
048FFD392F29F410005D62AE /* KBAIMessageCell.m */,
|
||||
);
|
||||
path = Message;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
048FFD3B2F2B289C005D62AE /* Comment */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
046086BB2F1A039F00757C95 /* KBAICommentView.h */,
|
||||
046086BC2F1A039F00757C95 /* KBAICommentView.m */,
|
||||
046086CE2F1A093400757C95 /* KBAICommentFooterView.h */,
|
||||
046086CF2F1A093400757C95 /* KBAICommentFooterView.m */,
|
||||
046086D02F1A093400757C95 /* KBAICommentHeaderView.h */,
|
||||
046086D12F1A093400757C95 /* KBAICommentHeaderView.m */,
|
||||
046086D22F1A093400757C95 /* KBAICommentInputView.h */,
|
||||
046086D32F1A093400757C95 /* KBAICommentInputView.m */,
|
||||
046086D42F1A093400757C95 /* KBAIReplyCell.h */,
|
||||
046086D52F1A093400757C95 /* KBAIReplyCell.m */,
|
||||
);
|
||||
path = Comment;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
048FFD3C2F2B2905005D62AE /* Chat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
048FFD122F274342005D62AE /* KBPersonaChatCell.h */,
|
||||
048FFD132F274342005D62AE /* KBPersonaChatCell.m */,
|
||||
04E039442F236E75002CA5A0 /* KBChatTableView.h */,
|
||||
04E039452F236E75002CA5A0 /* KBChatTableView.m */,
|
||||
04E039492F236E75002CA5A0 /* KBChatUserMessageCell.h */,
|
||||
04E0394A2F236E75002CA5A0 /* KBChatUserMessageCell.m */,
|
||||
04E039422F236E75002CA5A0 /* KBChatAssistantMessageCell.h */,
|
||||
04E039432F236E75002CA5A0 /* KBChatAssistantMessageCell.m */,
|
||||
04E039472F236E75002CA5A0 /* KBChatTimeCell.h */,
|
||||
04E039482F236E75002CA5A0 /* KBChatTimeCell.m */,
|
||||
);
|
||||
path = Chat;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
048FFD3D2F2B2A14005D62AE /* PopView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
048FFD222F28A836005D62AE /* KBChatLimitPopView.h */,
|
||||
048FFD232F28A836005D62AE /* KBChatLimitPopView.m */,
|
||||
);
|
||||
path = PopView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0498BD5F2EDFFBFC006CC1D5 /* VM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1158,6 +1563,7 @@
|
||||
04C6EAD72EAF870B0089C901 /* CustomKeyboard */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0419C9632F2C7630002E86D3 /* VM */,
|
||||
041007D02ECE010100D203BB /* Resource */,
|
||||
0477BD942EBAFF4E0055D639 /* Utils */,
|
||||
04A9FE122EB4D0D20020DB6D /* Manager */,
|
||||
@@ -1176,6 +1582,7 @@
|
||||
04C6EADA2EAF8C7B0089C901 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0419C9672F2C78E4002E86D3 /* Chat */,
|
||||
04DC5CEC2EF2D1D300F1AC80 /* Buy */,
|
||||
0498BDF62EEFF585006CC1D5 /* EmojiView */,
|
||||
04C6EADB2EAF8CEB0089C901 /* KBToolBar.h */,
|
||||
@@ -1203,6 +1610,8 @@
|
||||
A1B2C3F22EB35A9900000001 /* KBFullAccessGuideView.m */,
|
||||
04FC95B02EB0B2CC007BD342 /* KBSettingView.h */,
|
||||
04FC95B12EB0B2CC007BD342 /* KBSettingView.m */,
|
||||
A1B2C9222FC9000100000001 /* KBChatMessageCell.h */,
|
||||
A1B2C9232FC9000100000001 /* KBChatMessageCell.m */,
|
||||
049FB22D2EC34EB900FAB05D /* KBStreamTextView.h */,
|
||||
049FB22E2EC34EB900FAB05D /* KBStreamTextView.m */,
|
||||
049FB23A2EC4766700FAB05D /* Function */,
|
||||
@@ -1248,6 +1657,8 @@
|
||||
children = (
|
||||
04FC95642EB0546C007BD342 /* KBKey.h */,
|
||||
04FC95652EB0546C007BD342 /* KBKey.m */,
|
||||
A1B2C9202FC9000100000001 /* KBChatMessage.h */,
|
||||
A1B2C9212FC9000100000001 /* KBChatMessage.m */,
|
||||
04FEDC202F00020000999999 /* KBKeyboardSubscriptionProduct.h */,
|
||||
04FEDC212F00020000999999 /* KBKeyboardSubscriptionProduct.m */,
|
||||
04FEDC232F10000100000001 /* KBKeyboardLayoutConfig.h */,
|
||||
@@ -1293,8 +1704,6 @@
|
||||
04FC95B52EB1E3B1007BD342 /* VC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
04FC95CD2EB1E7A1007BD342 /* HomeVC.h */,
|
||||
04FC95CE2EB1E7A1007BD342 /* HomeVC.m */,
|
||||
0477BE022EBC83130055D639 /* HomeMainVC.h */,
|
||||
0477BE032EBC83130055D639 /* HomeMainVC.m */,
|
||||
0477BDEE2EBB76E30055D639 /* HomeSheetVC.h */,
|
||||
@@ -1437,6 +1846,7 @@
|
||||
04FC95BF2EB1E3B1007BD342 /* Class */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
046086702F191A5100757C95 /* AiTalk */,
|
||||
04122F612EC5F3DF00EF7AB3 /* Pay */,
|
||||
7276DDA22EC1B22500804C36 /* WebView */,
|
||||
048908D32EBF618E00FABA60 /* Vender */,
|
||||
@@ -1473,6 +1883,8 @@
|
||||
04FC95D62EB1EA16007BD342 /* BaseTableView.m */,
|
||||
048908FC2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.h */,
|
||||
048908FD2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m */,
|
||||
04E0383C2F1A7C30002CA5A0 /* KBCustomTabBar.h */,
|
||||
04E0383D2F1A7C30002CA5A0 /* KBCustomTabBar.m */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@@ -1818,6 +2230,7 @@
|
||||
04E161832F10E6470022C23B /* normal_hei_them.zip in Resources */,
|
||||
04E161842F10E6470022C23B /* normal_them.zip in Resources */,
|
||||
04A9FE202EB893F10020DB6D /* Localizable.strings in Resources */,
|
||||
0460866B2F18D75500757C95 /* ai_test.m4a in Resources */,
|
||||
041007D42ECE012500D203BB /* 002.zip in Resources */,
|
||||
041007D22ECE012000D203BB /* KBSkinIconMap.strings in Resources */,
|
||||
A1B2C3ED2F20000000000001 /* kb_words.txt in Resources */,
|
||||
@@ -1833,14 +2246,19 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
04286A0F2ECDA71B00CE730C /* 001.zip in Resources */,
|
||||
04E038D82F20BFFB002CA5A0 /* websocket-api.md in Resources */,
|
||||
0479200B2ED87CEE004E8522 /* permiss_video.mp4 in Resources */,
|
||||
04C6EABA2EAF86530089C901 /* Assets.xcassets in Resources */,
|
||||
04A9FE212EB893F10020DB6D /* Localizable.strings in Resources */,
|
||||
047920072ED86ABC004E8522 /* kb_guide_keyboard.gif in Resources */,
|
||||
046086752F191CC700757C95 /* AI技术分析.txt in Resources */,
|
||||
047920112ED98E7D004E8522 /* permiss_video_2.mp4 in Resources */,
|
||||
04C6EABC2EAF86530089C901 /* LaunchScreen.storyboard in Resources */,
|
||||
04E0394F2F236E75002CA5A0 /* KBChatTableView_Usage.md in Resources */,
|
||||
04286A132ECDEBF900CE730C /* KBSkinIconMap.strings in Resources */,
|
||||
04C6EABD2EAF86530089C901 /* Main.storyboard in Resources */,
|
||||
046086CB2F1A092500757C95 /* comments_mock.json in Resources */,
|
||||
04E038E32F20E500002CA5A0 /* deepgramAPI.md in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1923,8 +2341,15 @@
|
||||
04791FFC2ED71D17004E8522 /* UIColor+Extension.m in Sources */,
|
||||
0450AC4A2EF2C3ED00B6AF06 /* KBKeyboardSubscriptionOptionCell.m in Sources */,
|
||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */,
|
||||
048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */,
|
||||
048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */,
|
||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
|
||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
|
||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */,
|
||||
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */,
|
||||
A1B2C3EB2F20000000000001 /* KBSuggestionBarView.m in Sources */,
|
||||
0419C9662F2C7693002E86D3 /* KBVM.m in Sources */,
|
||||
048FFD512F2B68F7005D62AE /* KBPersonaModel.m in Sources */,
|
||||
04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */,
|
||||
04FEDAB32EEDB05000123456 /* KBEmojiPanelView.m in Sources */,
|
||||
04050ECB2F10FB8F008051EB /* UIImage+KBColor.m in Sources */,
|
||||
@@ -1983,23 +2408,43 @@
|
||||
04122F622EC5F41D00EF7AB3 /* KBUser.m in Sources */,
|
||||
04122F8B2EC6F7C800EF7AB3 /* IAPVerifyTransactionObj.m in Sources */,
|
||||
04B5A1A22EEFA12300AAAAAA /* KBPayProductModel.m in Sources */,
|
||||
046086D62F1A093400757C95 /* KBAICommentInputView.m in Sources */,
|
||||
046086D72F1A093400757C95 /* KBAICommentFooterView.m in Sources */,
|
||||
046086D82F1A093400757C95 /* KBAIReplyCell.m in Sources */,
|
||||
046086D92F1A093400757C95 /* KBAICommentHeaderView.m in Sources */,
|
||||
04E0394B2F236E75002CA5A0 /* KBChatUserMessageCell.m in Sources */,
|
||||
04E0394C2F236E75002CA5A0 /* KBChatTimeCell.m in Sources */,
|
||||
04E0394D2F236E75002CA5A0 /* KBChatAssistantMessageCell.m in Sources */,
|
||||
04E0394E2F236E75002CA5A0 /* KBChatTableView.m in Sources */,
|
||||
04286A062ECC81B200CE730C /* KBSkinService.m in Sources */,
|
||||
0479204A2EDDCE25004E8522 /* KBUserSessionManager.m in Sources */,
|
||||
04122FAD2EC73C0100EF7AB3 /* KBVipSubscribeCell.m in Sources */,
|
||||
049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */,
|
||||
048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */,
|
||||
046086732F191B6900757C95 /* KBAiMainVC.m in Sources */,
|
||||
048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */,
|
||||
048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */,
|
||||
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */,
|
||||
048FFD372F29F410005D62AE /* KBAIMessageCell.m in Sources */,
|
||||
048FFD3C2F29F500005D62AE /* KBLikedCompanionModel.m in Sources */,
|
||||
048FFD3F2F29F600005D62AE /* KBChattedCompanionModel.m in Sources */,
|
||||
048FFD422F29F700005D62AE /* KBChatSessionResetModel.m in Sources */,
|
||||
04791F952ED48028004E8522 /* KBFeedBackVC.m in Sources */,
|
||||
04890A042EC0BBBB00FABA60 /* KBCategoryTitleImageCell.m in Sources */,
|
||||
04890A052EC0BBBB00FABA60 /* KBCategoryTitleImageView.m in Sources */,
|
||||
04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */,
|
||||
04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */,
|
||||
04286A032ECB0A1600CE730C /* KBSexSelVC.m in Sources */,
|
||||
048FFD0B2F273BFC005D62AE /* KBAIHomeVC.m in Sources */,
|
||||
048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */,
|
||||
046086CC2F1A092500757C95 /* KBAIReplyModel.m in Sources */,
|
||||
046086CD2F1A092500757C95 /* KBAICommentModel.m in Sources */,
|
||||
04791F8F2ED469C0004E8522 /* KBHostAppLauncher.m in Sources */,
|
||||
047C65582EBCC06D0035E841 /* HomeRankCardCell.m in Sources */,
|
||||
04D1F6B32EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */,
|
||||
04122F912EC73AF700EF7AB3 /* KBVipPay.m in Sources */,
|
||||
0477BE002EBC6A330055D639 /* HomeRankVC.m in Sources */,
|
||||
048FFD472F2B45D4005D62AE /* AIPersonInfoVC.m in Sources */,
|
||||
047C650D2EBC8A840035E841 /* KBPanModalView.m in Sources */,
|
||||
0450AC0A2EF11E4400B6AF06 /* StoreKitManager.swift in Sources */,
|
||||
0450AC0B2EF11E4400B6AF06 /* StoreKitStateConverter.swift in Sources */,
|
||||
@@ -2010,14 +2455,19 @@
|
||||
0450AC102EF11E4400B6AF06 /* StoreKitDelegate.swift in Sources */,
|
||||
0450AC112EF11E4400B6AF06 /* StoreKitService.swift in Sources */,
|
||||
0450AC122EF11E4400B6AF06 /* TransactionConverter.swift in Sources */,
|
||||
048FFD4A2F2B4AE4005D62AE /* KBAICompanionDetailModel.m in Sources */,
|
||||
0450AC132EF11E4400B6AF06 /* SubscriptionConverter.swift in Sources */,
|
||||
0450AC142EF11E4400B6AF06 /* ProductConverter.swift in Sources */,
|
||||
0450AC152EF11E4400B6AF06 /* TransactionHistory.swift in Sources */,
|
||||
0450AC162EF11E4400B6AF06 /* StoreKitServiceDelegate.swift in Sources */,
|
||||
048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */,
|
||||
048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */,
|
||||
048FFD302F29F3C3005D62AE /* KBAIMessageZanVC.m in Sources */,
|
||||
0450AC172EF11E4400B6AF06 /* StoreKitState.swift in Sources */,
|
||||
0450AC1B2EF11E4400B6AF06 /* KBStoreKitBridge.swift in Sources */,
|
||||
043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */,
|
||||
049FB20E2EC1CD2800FAB05D /* KBAlert.m in Sources */,
|
||||
046086BD2F1A039F00757C95 /* KBAICommentView.m in Sources */,
|
||||
04A9FE162EB873C80020DB6D /* UIViewController+Extension.m in Sources */,
|
||||
04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */,
|
||||
04791FFF2ED830FA004E8522 /* KBKeyboardMaskView.m in Sources */,
|
||||
@@ -2029,6 +2479,7 @@
|
||||
A1F0C1C32FABCDEF12345678 /* KBInviteCodeModel.m in Sources */,
|
||||
A1F0C1D32FACAD0012345678 /* KBMaiPointReporter.m in Sources */,
|
||||
471CAD3574798685B72ADD55 /* KBMyTheme.m in Sources */,
|
||||
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */,
|
||||
A1F0C1B12F1234567890ABCD /* KBConsumptionRecord.m in Sources */,
|
||||
A1F0C1B22F1234567890ABCD /* KBConsumptionRecordCell.m in Sources */,
|
||||
A1F0C1B32F1234567890ABCD /* KBConsumptionRecordVC.m in Sources */,
|
||||
@@ -2036,8 +2487,13 @@
|
||||
0498BD712EE02A41006CC1D5 /* KBForgetPwdNewPwdVC.m in Sources */,
|
||||
048908EF2EBF861800FABA60 /* KBSkinSectionTitleCell.m in Sources */,
|
||||
0450AAE22EF03D5100B6AF06 /* KBPerson.swift in Sources */,
|
||||
04E038E82F20E877002CA5A0 /* DeepgramWebSocketClient.m in Sources */,
|
||||
04E038E92F20E877002CA5A0 /* DeepgramStreamingManager.m in Sources */,
|
||||
04E0B1022F300001002CA5A0 /* KBVoiceToTextManager.m in Sources */,
|
||||
04E0B2022F300002002CA5A0 /* KBVoiceRecordManager.m in Sources */,
|
||||
048908E32EBF821700FABA60 /* KBSkinDetailVC.m in Sources */,
|
||||
0477BDF32EBB7B850055D639 /* KBDirectionIndicatorView.m in Sources */,
|
||||
048FFD142F274342005D62AE /* KBPersonaChatCell.m in Sources */,
|
||||
049FB21A2EC20A9E00FAB05D /* KBMyKeyBoardVC.m in Sources */,
|
||||
049FB22C2EC31F8800FAB05D /* KBGenderPickerPopView.m in Sources */,
|
||||
048908D22EBF611D00FABA60 /* KBHistoryMoreCell.m in Sources */,
|
||||
@@ -2045,6 +2501,7 @@
|
||||
0498BD852EE1B255006CC1D5 /* KBSignUtils.m in Sources */,
|
||||
0477BDF72EBC63A80055D639 /* KBTestVC.m in Sources */,
|
||||
04122F7E2EC5FC5500EF7AB3 /* KBJfPayCell.m in Sources */,
|
||||
048FFD502F2B52E7005D62AE /* AIReportVC.m in Sources */,
|
||||
049FB2402EC4B6EF00FAB05D /* KBULBridgeNotification.m in Sources */,
|
||||
04FC95C92EB1E4C9007BD342 /* BaseNavigationController.m in Sources */,
|
||||
048908DD2EBF67EB00FABA60 /* KBSearchResultVC.m in Sources */,
|
||||
@@ -2052,6 +2509,8 @@
|
||||
05A1B2D22F5B1A2B3C4D5E60 /* KBSearchThemeModel.m in Sources */,
|
||||
047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */,
|
||||
047C655C2EBCD0F80035E841 /* UIView+KBShadow.m in Sources */,
|
||||
04E038DD2F20C420002CA5A0 /* VoiceChatStreamingManager.m in Sources */,
|
||||
04E038DE2F20C420002CA5A0 /* VoiceChatWebSocketClient.m in Sources */,
|
||||
049FB2262EC3136D00FAB05D /* KBPersonInfoItemCell.m in Sources */,
|
||||
048908C32EBE32B800FABA60 /* KBSearchVC.m in Sources */,
|
||||
049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */,
|
||||
@@ -2059,6 +2518,7 @@
|
||||
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */,
|
||||
04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */,
|
||||
048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */,
|
||||
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */,
|
||||
048908F22EC047FD00FABA60 /* KBShopHeadView.m in Sources */,
|
||||
0498BD742EE02E3D006CC1D5 /* KBRegistVerEmailVC.m in Sources */,
|
||||
049FB2292EC31BB000FAB05D /* KBChangeNicknamePopView.m in Sources */,
|
||||
@@ -2076,20 +2536,35 @@
|
||||
04FC97092EB31B14007BD342 /* KBHUD.m in Sources */,
|
||||
04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */,
|
||||
049FB2232EC311F900FAB05D /* KBPersonInfoVC.m in Sources */,
|
||||
04E038EF2F21F0EC002CA5A0 /* AiVM.m in Sources */,
|
||||
048FFD102F27432D005D62AE /* KBPersonaModel.m in Sources */,
|
||||
048FFD112F27432D005D62AE /* KBPersonaPageModel.m in Sources */,
|
||||
0498BD6B2EE025FC006CC1D5 /* KBForgetPwdVC.m in Sources */,
|
||||
048FFD182F2763A5005D62AE /* KBVoiceInputBar.m in Sources */,
|
||||
046086B12F19239B00757C95 /* SubtitleSync.m in Sources */,
|
||||
046086B22F19239B00757C95 /* TTSServiceClient.m in Sources */,
|
||||
046086B32F19239B00757C95 /* AudioSessionManager.m in Sources */,
|
||||
046086B42F19239B00757C95 /* LLMStreamClient.m in Sources */,
|
||||
046086B52F19239B00757C95 /* Segmenter.m in Sources */,
|
||||
046086B62F19239B00757C95 /* TTSPlaybackPipeline.m in Sources */,
|
||||
046086B72F19239B00757C95 /* ConversationOrchestrator.m in Sources */,
|
||||
046086B82F19239B00757C95 /* ASRStreamClient.m in Sources */,
|
||||
046086B92F19239B00757C95 /* AudioCaptureManager.m in Sources */,
|
||||
046086BA2F19239B00757C95 /* AudioStreamPlayer.m in Sources */,
|
||||
048908FE2EC0CC2400FABA60 /* UIScrollView+KBEmptyView.m in Sources */,
|
||||
0498BD7E2EE04F9C006CC1D5 /* KBTag.m in Sources */,
|
||||
04791F922ED48010004E8522 /* KBNoticeVC.m in Sources */,
|
||||
04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */,
|
||||
04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */,
|
||||
0498BDDE2EE81508006CC1D5 /* KBShopVM.m in Sources */,
|
||||
049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */,
|
||||
048FFD392F2A24C5005D62AE /* KBAIChatMessageCacheManager.m in Sources */,
|
||||
A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */,
|
||||
0498BD7B2EE04518006CC1D5 /* KBCharacter.m in Sources */,
|
||||
04122FB32EC73C0100EF7AB3 /* KBVipReviewListCell.m in Sources */,
|
||||
048908DA2EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m in Sources */,
|
||||
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
||||
0498BD6E2EE0285D006CC1D5 /* KBForgetVerPwdVC.m in Sources */,
|
||||
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */,
|
||||
0498BDE12EEA87C9006CC1D5 /* KBShopStyleModel.m in Sources */,
|
||||
49B63DBAEE9076C591E13D68 /* KBShopThemeTagModel.m in Sources */,
|
||||
EB72B60040437E3C0A4890FC /* KBShopThemeDetailModel.m in Sources */,
|
||||
@@ -2104,6 +2579,9 @@
|
||||
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */,
|
||||
0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */,
|
||||
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */,
|
||||
04E039522F2387D2002CA5A0 /* KBAiChatMessage.m in Sources */,
|
||||
0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */,
|
||||
0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */,
|
||||
04122FAA2EC73C0100EF7AB3 /* KBVipPayHeaderView.m in Sources */,
|
||||
0498BD622EDFFC12006CC1D5 /* KBMyVM.m in Sources */,
|
||||
049FB2432EC4BBB700FAB05D /* KBLoginPopView.m in Sources */,
|
||||
@@ -2117,11 +2595,13 @@
|
||||
0477BEA22EBCF0000055D639 /* KBTopImageButton.m in Sources */,
|
||||
A1B2E1012EBC7AAA00000001 /* KBTopThreeView.m in Sources */,
|
||||
A1B2E1022EBC7AAA00000001 /* HomeHotCell.m in Sources */,
|
||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */,
|
||||
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */,
|
||||
04286A002ECAEF2B00CE730C /* KBMoneyBtn.m in Sources */,
|
||||
048908F52EC0496400FABA60 /* KBShopItemVC.m in Sources */,
|
||||
04FC95F42EB339C1007BD342 /* AppleSignInManager.m in Sources */,
|
||||
04C6EAC12EAF86530089C901 /* ViewController.m in Sources */,
|
||||
04E0383E2F1A7C30002CA5A0 /* KBCustomTabBar.m in Sources */,
|
||||
A1B2C4002EB4A0A100000004 /* KBAuthManager.m in Sources */,
|
||||
A1B2C4212EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */,
|
||||
0498BD682EE01180006CC1D5 /* KBEmailRegistVC.m in Sources */,
|
||||
@@ -2263,6 +2743,9 @@
|
||||
INFOPLIST_FILE = keyBoard/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Key of Love";
|
||||
INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.loveKey.nyx.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboardAppExtension\n );\n}";
|
||||
INFOPLIST_KEY_NSMicrophoneUsageDescription = "需要使用麦克风进行语音输入";
|
||||
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "保存图片需要写入您的相册";
|
||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "更换头像需要访问您的相册";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||
@@ -2311,6 +2794,9 @@
|
||||
INFOPLIST_FILE = keyBoard/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Key of Love";
|
||||
INFOPLIST_KEY_CFBundleURLTypes = "{\n CFBundleURLName = \"com.loveKey.nyx.keyboard\";\n CFBundleURLSchemes = (\n kbkeyboardAppExtension\n );\n}";
|
||||
INFOPLIST_KEY_NSMicrophoneUsageDescription = "需要使用麦克风进行语音输入";
|
||||
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "保存图片需要写入您的相册";
|
||||
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "更换头像需要访问您的相册";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||
|
||||
@@ -190,7 +190,7 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
||||
} else if ([host isEqualToString:@"settings"]) { // kbkeyboard://settings
|
||||
[self kb_openAppSettings];
|
||||
return YES;
|
||||
}else if ([host isEqualToString:@"recharge"]) { // kbkeyboard://recharge
|
||||
} else if ([host isEqualToString:@"recharge"]) { // kbkeyboard://recharge
|
||||
NSDictionary<NSString *, NSString *> *params = [self kb_queryParametersFromURL:url];
|
||||
NSString *productId = params[@"productId"];
|
||||
BOOL autoPay = NO;
|
||||
|
||||
6
keyBoard/Assets.xcassets/AI/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
22
keyBoard/Assets.xcassets/AI/ai_close_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_close_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_close_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_close_icon.imageset/ai_close_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_close_icon.imageset/ai_close_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
22
keyBoard/Assets.xcassets/AI/ai_comment_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_comment_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_comment_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_comment_icon.imageset/ai_comment_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 847 B |
BIN
keyBoard/Assets.xcassets/AI/ai_comment_icon.imageset/ai_comment_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
22
keyBoard/Assets.xcassets/AI/ai_jianpan_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_jianpan_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_jianpan_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_jianpan_icon.imageset/ai_jianpan_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_jianpan_icon.imageset/ai_jianpan_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
22
keyBoard/Assets.xcassets/AI/ai_live_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_live_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_live_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_live_icon.imageset/ai_live_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_live_icon.imageset/ai_live_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
22
keyBoard/Assets.xcassets/AI/ai_livesel_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_livesel_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_livesel_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_livesel_icon.imageset/ai_livesel_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_livesel_icon.imageset/ai_livesel_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
22
keyBoard/Assets.xcassets/AI/ai_luyining_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_luyining_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_luyining_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_luyining_icon.imageset/ai_luyining_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_luyining_icon.imageset/ai_luyining_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
22
keyBoard/Assets.xcassets/AI/ai_maikefeng_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_maikefeng_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_maikefeng_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_maikefeng_icon.imageset/ai_maikefeng_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_maikefeng_icon.imageset/ai_maikefeng_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
22
keyBoard/Assets.xcassets/AI/ai_message_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_message_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_message_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_message_icon.imageset/ai_message_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_message_icon.imageset/ai_message_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
22
keyBoard/Assets.xcassets/AI/ai_report_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_report_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_report_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_report_icon.imageset/ai_report_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_report_icon.imageset/ai_report_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
22
keyBoard/Assets.xcassets/AI/ai_sendmessage_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_sendmessage_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_sendmessage_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_sendmessage_icon.imageset/ai_sendmessage_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_sendmessage_icon.imageset/ai_sendmessage_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.2 KiB |