23 Commits

Author SHA1 Message Date
3cb02d5b76 处理键盘ai功能 2026-02-05 16:01:21 +08:00
750b391100 处理键盘语音svip权限弹窗,跳转主app充值 2026-02-05 14:10:24 +08:00
faccf6f10f 1 2026-02-04 23:40:06 +08:00
35b1fc0f1e 处理vip逻辑 2026-02-04 21:49:28 +08:00
b73f225d15 语音vip限制ai弹窗 2026-02-04 20:23:20 +08:00
dd59094a16 处理了评论新增评论,在聊天里的评论数也一同改变 2026-02-04 19:31:30 +08:00
bacaf537f3 调用删除接口 2026-02-04 19:01:58 +08:00
619d356d31 新增接口 2026-02-04 18:45:57 +08:00
db9f07d199 优化长按聊天记录 如果是自己 不要显示举报 2026-02-04 18:39:25 +08:00
3ed120106e 处理二级评论回复用户名称显示问题 2026-02-04 18:29:12 +08:00
ff4edab820 1 2026-02-04 18:10:39 +08:00
3e30f619b9 新增删除弹窗,修改bug 2026-02-04 16:57:19 +08:00
533e23ebfe 1 2026-02-04 16:03:39 +08:00
85fb407717 处理支付 2026-02-04 15:57:22 +08:00
c1b50b407d 2 2026-02-04 15:40:45 +08:00
7c7e2477cb 1 2026-02-04 15:20:53 +08:00
faae0297cb 1 2026-02-04 15:09:03 +08:00
e50eaecbd9 1 2026-02-04 14:59:02 +08:00
879dbb860c 2 2026-02-04 13:14:26 +08:00
b4e4b7b606 处理svip 2026-02-04 12:48:18 +08:00
68a610e0a8 处理kbpayvip 2026-02-04 12:33:01 +08:00
305326aa9a 添加placehold颜色 2026-02-03 20:51:48 +08:00
61095a379f 处理网络 2026-02-03 20:22:28 +08:00
126 changed files with 3109 additions and 462 deletions

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ai_limit_close@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ai_limit_close@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ai_limit_goto@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ai_limit_goto@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ai_limit_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ai_limit_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 KiB

View File

@@ -20,6 +20,7 @@
#import "KBSettingView.h" #import "KBSettingView.h"
#import "KBChatMessage.h" #import "KBChatMessage.h"
#import "KBChatPanelView.h" #import "KBChatPanelView.h"
#import "KBChatLimitPopView.h"
#import "KBSkinInstallBridge.h" #import "KBSkinInstallBridge.h"
#import "KBSkinManager.h" #import "KBSkinManager.h"
#import "KBSuggestionEngine.h" #import "KBSuggestionEngine.h"
@@ -66,7 +67,8 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
@interface KeyboardViewController () <KBKeyBoardMainViewDelegate, @interface KeyboardViewController () <KBKeyBoardMainViewDelegate,
KBFunctionViewDelegate, KBFunctionViewDelegate,
KBKeyboardSubscriptionViewDelegate, KBKeyboardSubscriptionViewDelegate,
KBChatPanelViewDelegate> KBChatPanelViewDelegate,
KBChatLimitPopViewDelegate>
@property(nonatomic, strong) @property(nonatomic, strong)
UIButton *nextKeyboardButton; // UIButton *nextKeyboardButton; //
@property(nonatomic, strong) UIView *contentView; @property(nonatomic, strong) UIView *contentView;
@@ -85,6 +87,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
@property(nonatomic, strong) KBSuggestionEngine *suggestionEngine; @property(nonatomic, strong) KBSuggestionEngine *suggestionEngine;
@property(nonatomic, copy) NSString *currentWord; @property(nonatomic, copy) NSString *currentWord;
@property(nonatomic, assign) BOOL suppressSuggestions; @property(nonatomic, assign) BOOL suppressSuggestions;
@property(nonatomic, strong) UIControl *chatLimitMaskView;
@property(nonatomic, strong) MASConstraint *contentWidthConstraint; @property(nonatomic, strong) MASConstraint *contentWidthConstraint;
@property(nonatomic, strong) MASConstraint *contentHeightConstraint; @property(nonatomic, strong) MASConstraint *contentHeightConstraint;
@property(nonatomic, strong) MASConstraint *keyBoardMainHeightConstraint; @property(nonatomic, strong) MASConstraint *keyBoardMainHeightConstraint;
@@ -867,14 +870,66 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
[KBHUD showInfo:KBLocalized(@"请开启完全访问后使用")]; [KBHUD showInfo:KBLocalized(@"请开启完全访问后使用")];
return; return;
} }
// loading // loading
[self.chatPanelView kb_addLoadingAssistantMessage]; [self.chatPanelView kb_addLoadingAssistantMessage];
// //
[self kb_requestChatMessageWithContent:text]; [self kb_requestChatMessageWithContent:text];
} }
#pragma mark - Chat Limit Pop
- (void)kb_showChatLimitPopWithMessage:(NSString *)message {
[self kb_dismissChatLimitPop];
UIControl *mask = [[UIControl alloc] init];
mask.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
mask.alpha = 0.0;
[mask addTarget:self
action:@selector(kb_dismissChatLimitPop)
forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:mask];
[mask mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.contentView);
}];
CGFloat width = 252.0;
CGFloat height = 252.0 + 18.0 + 53.0 + 18.0 + 28.0;
KBChatLimitPopView *content =
[[KBChatLimitPopView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
content.message = message ?: @"";
content.delegate = self;
[mask addSubview:content];
[content mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(mask);
make.width.mas_equalTo(width);
make.height.mas_equalTo(height);
}];
self.chatLimitMaskView = mask;
[self.contentView bringSubviewToFront:mask];
[UIView animateWithDuration:0.18
animations:^{
mask.alpha = 1.0;
}];
}
- (void)kb_dismissChatLimitPop {
if (!self.chatLimitMaskView) {
return;
}
UIControl *mask = self.chatLimitMaskView;
self.chatLimitMaskView = nil;
[UIView animateWithDuration:0.15
animations:^{
mask.alpha = 0.0;
}
completion:^(__unused BOOL finished) {
[mask removeFromSuperview];
}];
}
- (void)kb_clearHostInputForText:(NSString *)text { - (void)kb_clearHostInputForText:(NSString *)text {
if (text.length == 0) { if (text.length == 0) {
return; return;
@@ -1018,16 +1073,22 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
__strong typeof(weakSelf) self = weakSelf; __strong typeof(weakSelf) self = weakSelf;
if (!self) return; if (!self) return;
if (!response.success) { if (response.code != 0) {
NSLog(@"[KB] ❌ 请求失败: %@", response.errorMessage); if (response.code == 50030) {
NSLog(@"[KB] ⚠️ 次数用尽: %@", response.message);
[self.chatPanelView kb_removeLoadingAssistantMessage];
[self kb_showChatLimitPopWithMessage:response.message];
return;
}
NSLog(@"[KB] ❌ 请求失败: %@", response.message);
[self.chatPanelView kb_removeLoadingAssistantMessage]; [self.chatPanelView kb_removeLoadingAssistantMessage];
[KBHUD showInfo:response.errorMessage ?: KBLocalized(@"请求失败")]; [KBHUD showInfo:response.message ?: KBLocalized(@"请求失败")];
return; return;
} }
NSLog(@"[KB] ✅ 收到回复: %@", response.text); NSLog(@"[KB] ✅ 收到回复: %@", response.data.aiResponse);
if (response.text.length == 0) { if (response.data.aiResponse.length == 0) {
[self.chatPanelView kb_removeLoadingAssistantMessage]; [self.chatPanelView kb_removeLoadingAssistantMessage];
[KBHUD showInfo:KBLocalized(@"未获取到回复内容")]; [KBHUD showInfo:KBLocalized(@"未获取到回复内容")];
return; return;
@@ -1035,12 +1096,12 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
// AI // AI
NSLog(@"[KB] 准备添加 AI 消息"); NSLog(@"[KB] 准备添加 AI 消息");
[self.chatPanelView kb_addAssistantMessage:response.text audioId:response.audioId]; [self.chatPanelView kb_addAssistantMessage:response.data.aiResponse audioId:response.data.audioId];
NSLog(@"[KB] AI 消息添加完成"); NSLog(@"[KB] AI 消息添加完成");
// audioId // audioId
if (response.audioId.length > 0) { if (response.data.audioId.length > 0) {
[self kb_preloadAudioWithAudioId:response.audioId]; [self kb_preloadAudioWithAudioId:response.data.audioId];
} }
}]; }];
} }
@@ -1352,6 +1413,25 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
[self kb_openRechargeForProduct:product]; [self kb_openRechargeForProduct:product];
} }
#pragma mark - KBChatLimitPopViewDelegate
- (void)chatLimitPopViewDidTapCancel:(KBChatLimitPopView *)view {
[self kb_dismissChatLimitPop];
}
- (void)chatLimitPopViewDidTapRecharge:(KBChatLimitPopView *)view {
[self kb_dismissChatLimitPop];
NSString *urlString =
[NSString stringWithFormat:@"%@://recharge?src=keyboard&vipType=svip",
KB_APP_SCHEME];
NSURL *scheme = [NSURL URLWithString:urlString];
BOOL success = [KBHostAppLauncher openHostAppURL:scheme
fromResponder:self.view];
if (!success) {
[KBHUD showInfo:KBLocalized(@"Please open the App to finish purchase")];
}
}
#pragma mark - lazy #pragma mark - lazy
- (KBKeyBoardMainView *)keyBoardMainView { - (KBKeyBoardMainView *)keyBoardMainView {
if (!_keyBoardMainView) { if (!_keyBoardMainView) {

View File

@@ -7,15 +7,25 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@class KBChatDataModel;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
/// 聊天响应模型 /// 聊天响应模型
@interface KBChatResponse : NSObject @interface KBChatResponse : NSObject
@property (nonatomic, copy, nullable) NSString *text; @property (nonatomic, strong, nullable) KBChatDataModel *data;
@property (nonatomic, copy, nullable) NSString *audioId; //@property (nonatomic, copy, nullable) NSString *audioId;
@property (nonatomic, copy, nullable) NSString *errorMessage; @property (nonatomic, copy, nullable) NSString *message;
@property (nonatomic, assign) BOOL success; @property (nonatomic, assign) BOOL success;
@property (nonatomic, assign) NSInteger code;
@end
@interface KBChatDataModel : NSObject
@property (nonatomic, copy, nullable) NSString *aiResponse;
@property (nonatomic, copy, nullable) NSString *audioId;
@property (nonatomic, copy, nullable) NSString *llmDuration;
@end @end
/// 音频响应模型 /// 音频响应模型

View File

@@ -7,10 +7,14 @@
#import "KBNetworkManager.h" #import "KBNetworkManager.h"
#import "KBConfig.h" #import "KBConfig.h"
#import <AVFoundation/AVFoundation.h> #import <AVFoundation/AVFoundation.h>
#import <MJExtension/MJExtension.h>
@implementation KBChatResponse @implementation KBChatResponse
@end @end
@implementation KBChatDataModel
@end
@implementation KBAudioResponse @implementation KBAudioResponse
@end @end
@@ -46,7 +50,7 @@
if (completion) { if (completion) {
KBChatResponse *response = [[KBChatResponse alloc] init]; KBChatResponse *response = [[KBChatResponse alloc] init];
response.success = NO; response.success = NO;
response.errorMessage = @"内容为空"; response.message = @"内容为空";
completion(response); completion(response);
} }
return; return;
@@ -66,24 +70,23 @@
headers:nil headers:nil
completion:^(NSDictionary *json, NSURLResponse *response, NSError *error) { completion:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
KBChatResponse *chatResponse = [[KBChatResponse alloc] init]; KBChatResponse *chatResponse = [KBChatResponse mj_objectWithKeyValues:json];
if (chatResponse.code != 0) {
if (error) {
chatResponse.success = NO; chatResponse.success = NO;
chatResponse.errorMessage = error.localizedDescription ?: @"请求失败"; // chatResponse.errorMessage = error.localizedDescription ?: @"请求失败";
if (completion) completion(chatResponse); if (completion) completion(chatResponse);
return; return;
} }
// // //
chatResponse.text = [self p_parseTextFromJSON:json]; // chatResponse.text = [self p_parseTextFromJSON:json];
// audioId // // audioId
chatResponse.audioId = [self p_parseAudioIdFromJSON:json]; // chatResponse.audioId = [self p_parseAudioIdFromJSON:json];
chatResponse.success = (chatResponse.text.length > 0); // chatResponse.success = (chatResponse.text.length > 0);
if (!chatResponse.success) { // if (!chatResponse.success) {
chatResponse.errorMessage = @"未获取到回复内容"; // chatResponse.errorMessage = @"未获取到回复内容";
} // }
if (completion) completion(chatResponse); if (completion) completion(chatResponse);
}); });

View File

@@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, weak, nullable) id<KBToolBarDelegate> delegate; @property (nonatomic, weak, nullable) id<KBToolBarDelegate> delegate;
/// 左侧按钮的标题(数量由数组决定)。默认值:@[@"AI", @"语音"]。 /// 左侧按钮的标题(数量由数组决定)。默认值:@[@"AI"]。
@property (nonatomic, copy) NSArray<NSString *> *leftButtonTitles; @property (nonatomic, copy) NSArray<NSString *> *leftButtonTitles;
/// 暴露按钮以便外部定制(只读;首次访问时懒加载创建) /// 暴露按钮以便外部定制(只读;首次访问时懒加载创建)

View File

@@ -15,23 +15,25 @@
@property (nonatomic, strong) NSArray<UIButton *> *leftButtonsInternal; @property (nonatomic, strong) NSArray<UIButton *> *leftButtonsInternal;
//@property (nonatomic, strong) UIButton *settingsButtonInternal; //@property (nonatomic, strong) UIButton *settingsButtonInternal;
@property (nonatomic, strong) UIButton *globeButtonInternal; // @property (nonatomic, strong) UIButton *globeButtonInternal; //
@property (nonatomic, strong) UIImageView *avatarImageView; // AppGroup persona_cover.jpg
@property (nonatomic, strong) UIButton *undoButtonInternal; // @property (nonatomic, strong) UIButton *undoButtonInternal; //
@property (nonatomic, assign) BOOL kbNeedsInputModeSwitchKey; @property (nonatomic, assign) BOOL kbNeedsInputModeSwitchKey;
@property (nonatomic, assign) BOOL kbUndoVisible; @property (nonatomic, assign) BOOL kbUndoVisible;
@property (nonatomic, assign) BOOL kbAvatarVisible;
@end @end
@implementation KBToolBar @implementation KBToolBar
static NSString * const kKBAIKeyIdentifier = @"ai"; static NSString * const kKBAIKeyIdentifier = @"ai";
static NSString * const kKBUndoKeyIdentifier = @"key_revoke"; static NSString * const kKBUndoKeyIdentifier = @"key_revoke";
static const CGFloat kKBAIButtonWidth = 40; static const CGFloat kKBAIButtonWidth = 40;
static const CGFloat kKBAIButtonHeight = 40; static const CGFloat kKBAIButtonHeight = 40;
static const NSInteger kKBVoiceButtonIndex = 1; static const CGFloat kKBAvatarSize = 40;
- (instancetype)initWithFrame:(CGRect)frame{ - (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor]; self.backgroundColor = [UIColor clearColor];
_leftButtonTitles = @[@"AI", KBLocalized(@"语音")]; // _leftButtonTitles = @[@"AI"]; //
[self setupUI]; [self setupUI];
[[NSNotificationCenter defaultCenter] addObserver:self [[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(kb_undoStateChanged) selector:@selector(kb_undoStateChanged)
@@ -69,7 +71,6 @@ static const NSInteger kKBVoiceButtonIndex = 1;
} }
}]; }];
[self kb_updateAIButtonAppearance]; [self kb_updateAIButtonAppearance];
[self kb_updateVoiceButtonAppearance];
} }
#pragma mark - #pragma mark -
@@ -79,6 +80,7 @@ static const NSInteger kKBVoiceButtonIndex = 1;
// [self addSubview:self.settingsButtonInternal]; // [self addSubview:self.settingsButtonInternal];
[self addSubview:self.globeButtonInternal]; [self addSubview:self.globeButtonInternal];
[self addSubview:self.undoButtonInternal]; [self addSubview:self.undoButtonInternal];
[self addSubview:self.avatarImageView];
// //
// [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { // [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -94,13 +96,7 @@ static const NSInteger kKBVoiceButtonIndex = 1;
make.width.height.mas_equalTo(32); make.width.height.mas_equalTo(32);
}]; }];
// [self kb_updateRightControlsConstraints];
[self.undoButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.mas_right).offset(-12);
make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(32);
make.width.mas_equalTo(84);
}];
[self kb_updateLeftContainerConstraints]; [self kb_updateLeftContainerConstraints];
@@ -173,8 +169,8 @@ static const NSInteger kKBVoiceButtonIndex = 1;
- (void)kb_applyTheme { - (void)kb_applyTheme {
[self kb_updateAIButtonAppearance]; [self kb_updateAIButtonAppearance];
[self kb_updateVoiceButtonAppearance];
[self kb_updateUndoButtonAppearance]; [self kb_updateUndoButtonAppearance];
[self kb_updateAvatarAppearance];
} }
- (void)kb_updateAIButtonAppearance { - (void)kb_updateAIButtonAppearance {
@@ -211,16 +207,6 @@ static const NSInteger kKBVoiceButtonIndex = 1;
} }
} }
- (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 { - (void)kb_updateUndoButtonAppearance {
if (!self.undoButtonInternal) { return; } if (!self.undoButtonInternal) { return; }
@@ -241,6 +227,41 @@ static const NSInteger kKBVoiceButtonIndex = 1;
} }
} }
#pragma mark - Avatar
- (void)kb_updateAvatarAppearance {
UIImage *img = [self kb_personaCoverImageFromAppGroup];
BOOL shouldShow = (img != nil);
self.avatarImageView.image = img;
if (self.kbAvatarVisible == shouldShow) {
self.avatarImageView.hidden = !shouldShow;
return;
}
self.kbAvatarVisible = shouldShow;
self.avatarImageView.hidden = !shouldShow;
[self kb_updateRightControlsConstraints];
[self kb_updateLeftContainerConstraints];
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (nullable UIImage *)kb_personaCoverImageFromAppGroup {
NSURL *containerURL = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:AppGroup];
if (!containerURL) {
return nil;
}
NSString *imagePath =
[[containerURL path] stringByAppendingPathComponent:@"persona_cover.jpg"];
if (imagePath.length == 0 ||
![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
return nil;
}
return [UIImage imageWithContentsOfFile:imagePath];
}
#pragma mark - Actions #pragma mark - Actions
- (void)onLeftAction:(UIButton *)sender { - (void)onLeftAction:(UIButton *)sender {
@@ -261,6 +282,16 @@ static const NSInteger kKBVoiceButtonIndex = 1;
} }
} }
- (void)onAvatarTap {
if (!self.kbAvatarVisible || self.avatarImageView.hidden) {
return;
}
// index=1 index
if ([self.delegate respondsToSelector:@selector(toolBar:didTapActionAtIndex:)]) {
[self.delegate toolBar:self didTapActionAtIndex:1];
}
}
#pragma mark - Lazy #pragma mark - Lazy
- (UIView *)leftContainer { - (UIView *)leftContainer {
@@ -271,6 +302,23 @@ static const NSInteger kKBVoiceButtonIndex = 1;
return _leftContainer; return _leftContainer;
} }
- (UIImageView *)avatarImageView {
if (!_avatarImageView) {
_avatarImageView = [[UIImageView alloc] init];
_avatarImageView.hidden = YES;
_avatarImageView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
_avatarImageView.contentMode = UIViewContentModeScaleAspectFill;
_avatarImageView.layer.cornerRadius = kKBAvatarSize * 0.5;
_avatarImageView.layer.masksToBounds = YES;
_avatarImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(onAvatarTap)];
[_avatarImageView addGestureRecognizer:tap];
}
return _avatarImageView;
}
//- (UIButton *)settingsButtonInternal { //- (UIButton *)settingsButtonInternal {
// if (!_settingsButtonInternal) { // if (!_settingsButtonInternal) {
// _settingsButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; // _settingsButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem];
@@ -319,11 +367,6 @@ static const NSInteger kKBVoiceButtonIndex = 1;
return self.leftButtonsInternal[0]; return self.leftButtonsInternal[0];
} }
- (UIButton *)kb_voiceButton {
if (self.leftButtonsInternal.count <= kKBVoiceButtonIndex) { return nil; }
return self.leftButtonsInternal[kKBVoiceButtonIndex];
}
#pragma mark - Globe (Input Mode Switch) #pragma mark - Globe (Input Mode Switch)
// 宿 // 宿
@@ -362,6 +405,8 @@ static const NSInteger kKBVoiceButtonIndex = 1;
} }
if (self.kbUndoVisible) { if (self.kbUndoVisible) {
make.right.equalTo(self.undoButtonInternal.mas_left).offset(-8); make.right.equalTo(self.undoButtonInternal.mas_left).offset(-8);
} else if (self.kbAvatarVisible) {
make.right.equalTo(self.avatarImageView.mas_left).offset(-8);
} else { } else {
make.right.equalTo(self).offset(-12); make.right.equalTo(self).offset(-12);
} }
@@ -371,6 +416,24 @@ static const NSInteger kKBVoiceButtonIndex = 1;
}]; }];
} }
- (void)kb_updateRightControlsConstraints {
[self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self).offset(-12);
make.centerY.equalTo(self).offset(5);
make.width.height.mas_equalTo(kKBAvatarSize);
}];
[self.undoButtonInternal mas_remakeConstraints:^(MASConstraintMaker *make) {
if (self.kbAvatarVisible) {
make.right.equalTo(self.avatarImageView.mas_left).offset(-8);
} else {
make.right.equalTo(self).offset(-12);
}
make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(32);
make.width.mas_equalTo(84);
}];
}
- (void)kb_undoStateChanged { - (void)kb_undoStateChanged {
[self kb_updateUndoVisibilityAnimated:YES]; [self kb_updateUndoVisibilityAnimated:YES];
} }
@@ -405,6 +468,7 @@ static const NSInteger kKBVoiceButtonIndex = 1;
- (void)didMoveToWindow { - (void)didMoveToWindow {
[super didMoveToWindow]; [super didMoveToWindow];
[self kb_refreshGlobeVisibility]; [self kb_refreshGlobeVisibility];
[self kb_updateAvatarAppearance];
} }
@end @end

View File

@@ -20,6 +20,10 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params + (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
secret:(NSString *)secret; secret:(NSString *)secret;
/// 获取签名原始拼接字符串HMAC 前的明文)
+ (NSString *)signSourceStringWithParams:(NSDictionary<NSString *, NSString *> *)params
secret:(NSString *)secret;
/// 秒级时间戳(字符串) /// 秒级时间戳(字符串)
+ (NSString *)currentTimestamp; + (NSString *)currentTimestamp;
@@ -29,4 +33,3 @@ NS_ASSUME_NONNULL_BEGIN
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -12,10 +12,16 @@
+ (NSString *)urlEncode:(NSString *)value { + (NSString *)urlEncode:(NSString *)value {
if (!value) return @""; if (!value) return @"";
// Swift .urlQueryAllowed // application/x-www-form-urlencoded
NSCharacterSet *allowed = [NSCharacterSet URLQueryAllowedCharacterSet]; NSMutableCharacterSet *allowed = [NSMutableCharacterSet alphanumericCharacterSet];
[allowed addCharactersInString:@"-._*"];
NSString *encoded = [value stringByAddingPercentEncodingWithAllowedCharacters:allowed]; NSString *encoded = [value stringByAddingPercentEncodingWithAllowedCharacters:allowed];
return encoded ?: value; if (!encoded) {
return value;
}
// +URLEncoder
encoded = [encoded stringByReplacingOccurrencesOfString:@"%20" withString:@"+"];
return encoded;
} }
+ (NSString *)hmacSHA256:(NSString *)data secret:(NSString *)secret { + (NSString *)hmacSHA256:(NSString *)data secret:(NSString *)secret {
@@ -41,6 +47,12 @@
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params + (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
secret:(NSString *)secret { secret:(NSString *)secret {
NSString *dataString = [self signSourceStringWithParams:params secret:secret];
return [self hmacSHA256:dataString secret:secret];
}
+ (NSString *)signSourceStringWithParams:(NSDictionary<NSString *, NSString *> *)params
secret:(NSString *)secret {
// 1. & sign // 1. & sign
NSMutableDictionary<NSString *, NSString *> *filtered = [NSMutableDictionary dictionary]; NSMutableDictionary<NSString *, NSString *> *filtered = [NSMutableDictionary dictionary];
@@ -62,15 +74,11 @@
[components addObject:part]; [components addObject:part];
} }
NSString *encodedSecret = [self urlEncode:secret]; NSString *encodedSecret = [self urlEncode:secret ?: @""];
NSString *secretPart = [NSString stringWithFormat:@"secret=%@", encodedSecret]; NSString *secretPart = [NSString stringWithFormat:@"secret=%@", encodedSecret];
[components addObject:secretPart]; [components addObject:secretPart];
NSString *dataString = [components componentsJoinedByString:@"&"]; return [components componentsJoinedByString:@"&"];
// 4. HMAC-SHA256
NSString *sign = [self hmacSHA256:dataString secret:secret];
return sign;
} }
+ (NSString *)currentTimestamp { + (NSString *)currentTimestamp {
@@ -89,4 +97,3 @@
} }
@end @end

View File

@@ -54,7 +54,6 @@
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; }; 0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; };
0459D1B82EBA287900F2D189 /* 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 */; }; 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 */; }; 046086752F191CC700757C95 /* AI技术分析.txt in Resources */ = {isa = PBXBuildFile; fileRef = 046086742F191CC700757C95 /* AI技术分析.txt */; };
0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086992F19238500757C95 /* KBAiWaveformView.m */; }; 0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086992F19238500757C95 /* KBAiWaveformView.m */; };
0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086972F19238500757C95 /* KBAiRecordButton.m */; }; 0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086972F19238500757C95 /* KBAiRecordButton.m */; };
@@ -141,13 +140,14 @@
048FFD112F27432D005D62AE /* KBPersonaPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0F2F27432D005D62AE /* KBPersonaPageModel.m */; }; 048FFD112F27432D005D62AE /* KBPersonaPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0F2F27432D005D62AE /* KBPersonaPageModel.m */; };
048FFD142F274342005D62AE /* KBPersonaChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD132F274342005D62AE /* KBPersonaChatCell.m */; }; 048FFD142F274342005D62AE /* KBPersonaChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD132F274342005D62AE /* KBPersonaChatCell.m */; };
048FFD182F2763A5005D62AE /* KBVoiceInputBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD172F2763A5005D62AE /* KBVoiceInputBar.m */; }; 048FFD182F2763A5005D62AE /* KBVoiceInputBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD172F2763A5005D62AE /* KBVoiceInputBar.m */; };
048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */; }; 048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */; };
048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */; }; 048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */; };
048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; }; 048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; }; A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; }; 048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */; }; 048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
048FFD302F29F3C3005D62AE /* KBAIMessageZanVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.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 */; }; 048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD322F29F3D2005D62AE /* KBAIMessageChatingVC.m */; };
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; }; 048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; };
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.m */; }; 048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.m */; };
@@ -229,8 +229,6 @@
04E038E92F20E877002CA5A0 /* DeepgramStreamingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038E52F20E877002CA5A0 /* DeepgramStreamingManager.m */; }; 04E038E92F20E877002CA5A0 /* DeepgramStreamingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038E52F20E877002CA5A0 /* DeepgramStreamingManager.m */; };
04E038EF2F21F0EC002CA5A0 /* AiVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038EE2F21F0EC002CA5A0 /* AiVM.m */; }; 04E038EF2F21F0EC002CA5A0 /* AiVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E038EE2F21F0EC002CA5A0 /* AiVM.m */; };
04E0394B2F236E75002CA5A0 /* KBChatUserMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0394A2F236E75002CA5A0 /* KBChatUserMessageCell.m */; }; 04E0394B2F236E75002CA5A0 /* KBChatUserMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0394A2F236E75002CA5A0 /* KBChatUserMessageCell.m */; };
0F2A10032F3C0001002CA5A0 /* KBChatMessageActionPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F2A10022F3C0001002CA5A0 /* KBChatMessageActionPopView.m */; };
0F2A10132F3C0002002CA5A0 /* KBAIPersonaSidebarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F2A10122F3C0002002CA5A0 /* KBAIPersonaSidebarView.m */; };
04E0394C2F236E75002CA5A0 /* KBChatTimeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039482F236E75002CA5A0 /* KBChatTimeCell.m */; }; 04E0394C2F236E75002CA5A0 /* KBChatTimeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039482F236E75002CA5A0 /* KBChatTimeCell.m */; };
04E0394D2F236E75002CA5A0 /* KBChatAssistantMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039432F236E75002CA5A0 /* KBChatAssistantMessageCell.m */; }; 04E0394D2F236E75002CA5A0 /* KBChatAssistantMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039432F236E75002CA5A0 /* KBChatAssistantMessageCell.m */; };
04E0394E2F236E75002CA5A0 /* KBChatTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039452F236E75002CA5A0 /* KBChatTableView.m */; }; 04E0394E2F236E75002CA5A0 /* KBChatTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E039452F236E75002CA5A0 /* KBChatTableView.m */; };
@@ -240,6 +238,14 @@
04E0B2022F300002002CA5A0 /* KBVoiceRecordManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0B2012F300002002CA5A0 /* KBVoiceRecordManager.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 */; }; 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 */; }; 04E161842F10E6470022C23B /* normal_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161822F10E6470022C23B /* normal_them.zip */; };
04F4C0AA2F32274000E8F08C /* KBPayMainVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0A92F32274000E8F08C /* KBPayMainVC.m */; };
04F4C0AD2F32288600E8F08C /* KBPaySvipVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0AC2F32288600E8F08C /* KBPaySvipVC.m */; };
04F4C0B02F322EF200E8F08C /* PagingViewTableHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0AF2F322EF200E8F08C /* PagingViewTableHeaderView.m */; };
04F4C0B52F33053800E8F08C /* KBSvipBenefitCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0B22F33053800E8F08C /* KBSvipBenefitCell.m */; };
04F4C0B62F33053800E8F08C /* KBSvipSubscribeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0B42F33053800E8F08C /* KBSvipSubscribeCell.m */; };
04F4C0BB2F3306CF00E8F08C /* KBSvipFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0BA2F3306CF00E8F08C /* KBSvipFlowLayout.m */; };
04F4C0BC2F3306CF00E8F08C /* KBSvipBenefitBgView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0B82F3306CF00E8F08C /* KBSvipBenefitBgView.m */; };
04F4C0BF2F33369900E8F08C /* KBAIChatDeleteConfirmView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04F4C0BE2F33369900E8F08C /* KBAIChatDeleteConfirmView.m */; };
04FC95672EB0546C007BD342 /* KBKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95652EB0546C007BD342 /* KBKey.m */; }; 04FC95672EB0546C007BD342 /* KBKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95652EB0546C007BD342 /* KBKey.m */; };
04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95692EB05497007BD342 /* KBKeyButton.m */; }; 04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95692EB05497007BD342 /* KBKeyButton.m */; };
04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; }; 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; };
@@ -273,6 +279,8 @@
04FEDC422F00040000999999 /* KBKeyboardSubscriptionFeatureMarqueeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FEDC412F00040000999999 /* KBKeyboardSubscriptionFeatureMarqueeView.m */; }; 04FEDC422F00040000999999 /* KBKeyboardSubscriptionFeatureMarqueeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FEDC412F00040000999999 /* KBKeyboardSubscriptionFeatureMarqueeView.m */; };
05A1B2D12F5B1A2B3C4D5E60 /* KBSearchVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A1B2C52F5B1A2B3C4D5E60 /* KBSearchVM.m */; }; 05A1B2D12F5B1A2B3C4D5E60 /* KBSearchVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A1B2C52F5B1A2B3C4D5E60 /* KBSearchVM.m */; };
05A1B2D22F5B1A2B3C4D5E60 /* KBSearchThemeModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A1B2C72F5B1A2B3C4D5E60 /* KBSearchThemeModel.m */; }; 05A1B2D22F5B1A2B3C4D5E60 /* KBSearchThemeModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A1B2C72F5B1A2B3C4D5E60 /* KBSearchThemeModel.m */; };
0F2A10032F3C0001002CA5A0 /* KBChatMessageActionPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F2A10022F3C0001002CA5A0 /* KBChatMessageActionPopView.m */; };
0F2A10132F3C0002002CA5A0 /* KBAIPersonaSidebarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F2A10122F3C0002002CA5A0 /* KBAIPersonaSidebarView.m */; };
471CAD3574798685B72ADD55 /* KBMyTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 180D662EC4DB3A7FFF83FF18 /* KBMyTheme.m */; }; 471CAD3574798685B72ADD55 /* KBMyTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 180D662EC4DB3A7FFF83FF18 /* KBMyTheme.m */; };
49B63DBAEE9076C591E13D68 /* KBShopThemeTagModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A844CD2D8584596DBE6316 /* KBShopThemeTagModel.m */; }; 49B63DBAEE9076C591E13D68 /* KBShopThemeTagModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A844CD2D8584596DBE6316 /* KBShopThemeTagModel.m */; };
550CB2630FA4A7B4B9782EFA /* KBMyTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 180D662EC4DB3A7FFF83FF18 /* KBMyTheme.m */; }; 550CB2630FA4A7B4B9782EFA /* KBMyTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 180D662EC4DB3A7FFF83FF18 /* KBMyTheme.m */; };
@@ -396,8 +404,6 @@
0459D1B52EBA287900F2D189 /* KBSkinManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinManager.h; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 046086972F19238500757C95 /* KBAiRecordButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAiRecordButton.m; sourceTree = "<group>"; };
@@ -564,8 +570,6 @@
048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatHistoryPageModel.m; 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>"; }; 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>"; }; 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatLimitPopView.m; sourceTree = "<group>"; };
0F2A10112F3C0002002CA5A0 /* KBAIPersonaSidebarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIPersonaSidebarView.h; sourceTree = "<group>"; };
0F2A10122F3C0002002CA5A0 /* KBAIPersonaSidebarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIPersonaSidebarView.m; sourceTree = "<group>"; };
048FFD252F28C6CF005D62AE /* KBImagePositionButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBImagePositionButton.h; 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>"; }; 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>"; }; 048FFD282F28E99A005D62AE /* KBCommentModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBCommentModel.h; sourceTree = "<group>"; };
@@ -724,8 +728,6 @@
04E039482F236E75002CA5A0 /* KBChatTimeCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatTimeCell.m; 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>"; }; 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>"; }; 04E0394A2F236E75002CA5A0 /* KBChatUserMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatUserMessageCell.m; sourceTree = "<group>"; };
0F2A10012F3C0001002CA5A0 /* KBChatMessageActionPopView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatMessageActionPopView.h; sourceTree = "<group>"; };
0F2A10022F3C0001002CA5A0 /* KBChatMessageActionPopView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatMessageActionPopView.m; sourceTree = "<group>"; };
04E039502F2387D2002CA5A0 /* KBAiChatMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAiChatMessage.h; 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>"; }; 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>"; }; 04E0B1002F300001002CA5A0 /* KBVoiceToTextManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBVoiceToTextManager.h; sourceTree = "<group>"; };
@@ -734,6 +736,22 @@
04E0B2012F300002002CA5A0 /* KBVoiceRecordManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVoiceRecordManager.m; 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>"; }; 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>"; }; 04E161822F10E6470022C23B /* normal_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_them.zip; sourceTree = "<group>"; };
04F4C0A82F32274000E8F08C /* KBPayMainVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPayMainVC.h; sourceTree = "<group>"; };
04F4C0A92F32274000E8F08C /* KBPayMainVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPayMainVC.m; sourceTree = "<group>"; };
04F4C0AB2F32288600E8F08C /* KBPaySvipVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPaySvipVC.h; sourceTree = "<group>"; };
04F4C0AC2F32288600E8F08C /* KBPaySvipVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPaySvipVC.m; sourceTree = "<group>"; };
04F4C0AE2F322EF200E8F08C /* PagingViewTableHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PagingViewTableHeaderView.h; sourceTree = "<group>"; };
04F4C0AF2F322EF200E8F08C /* PagingViewTableHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PagingViewTableHeaderView.m; sourceTree = "<group>"; };
04F4C0B12F33053800E8F08C /* KBSvipBenefitCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSvipBenefitCell.h; sourceTree = "<group>"; };
04F4C0B22F33053800E8F08C /* KBSvipBenefitCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSvipBenefitCell.m; sourceTree = "<group>"; };
04F4C0B32F33053800E8F08C /* KBSvipSubscribeCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSvipSubscribeCell.h; sourceTree = "<group>"; };
04F4C0B42F33053800E8F08C /* KBSvipSubscribeCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSvipSubscribeCell.m; sourceTree = "<group>"; };
04F4C0B72F3306CF00E8F08C /* KBSvipBenefitBgView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSvipBenefitBgView.h; sourceTree = "<group>"; };
04F4C0B82F3306CF00E8F08C /* KBSvipBenefitBgView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSvipBenefitBgView.m; sourceTree = "<group>"; };
04F4C0B92F3306CF00E8F08C /* KBSvipFlowLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSvipFlowLayout.h; sourceTree = "<group>"; };
04F4C0BA2F3306CF00E8F08C /* KBSvipFlowLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSvipFlowLayout.m; sourceTree = "<group>"; };
04F4C0BD2F33369900E8F08C /* KBAIChatDeleteConfirmView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIChatDeleteConfirmView.h; sourceTree = "<group>"; };
04F4C0BE2F33369900E8F08C /* KBAIChatDeleteConfirmView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIChatDeleteConfirmView.m; sourceTree = "<group>"; };
04FC953A2EAFAE56007BD342 /* KeyBoardPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyBoardPrefixHeader.pch; sourceTree = "<group>"; }; 04FC953A2EAFAE56007BD342 /* KeyBoardPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyBoardPrefixHeader.pch; sourceTree = "<group>"; };
04FC95642EB0546C007BD342 /* KBKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKey.h; sourceTree = "<group>"; }; 04FC95642EB0546C007BD342 /* KBKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKey.h; sourceTree = "<group>"; };
04FC95652EB0546C007BD342 /* KBKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKey.m; sourceTree = "<group>"; }; 04FC95652EB0546C007BD342 /* KBKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKey.m; sourceTree = "<group>"; };
@@ -803,6 +821,10 @@
05A1B2C52F5B1A2B3C4D5E60 /* KBSearchVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchVM.m; sourceTree = "<group>"; }; 05A1B2C52F5B1A2B3C4D5E60 /* KBSearchVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchVM.m; sourceTree = "<group>"; };
05A1B2C62F5B1A2B3C4D5E60 /* KBSearchThemeModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSearchThemeModel.h; sourceTree = "<group>"; }; 05A1B2C62F5B1A2B3C4D5E60 /* KBSearchThemeModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSearchThemeModel.h; sourceTree = "<group>"; };
05A1B2C72F5B1A2B3C4D5E60 /* KBSearchThemeModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchThemeModel.m; sourceTree = "<group>"; }; 05A1B2C72F5B1A2B3C4D5E60 /* KBSearchThemeModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSearchThemeModel.m; sourceTree = "<group>"; };
0F2A10012F3C0001002CA5A0 /* KBChatMessageActionPopView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBChatMessageActionPopView.h; sourceTree = "<group>"; };
0F2A10022F3C0001002CA5A0 /* KBChatMessageActionPopView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBChatMessageActionPopView.m; sourceTree = "<group>"; };
0F2A10112F3C0002002CA5A0 /* KBAIPersonaSidebarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIPersonaSidebarView.h; sourceTree = "<group>"; };
0F2A10122F3C0002002CA5A0 /* KBAIPersonaSidebarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIPersonaSidebarView.m; sourceTree = "<group>"; };
180D662EC4DB3A7FFF83FF18 /* KBMyTheme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyTheme.m; sourceTree = "<group>"; }; 180D662EC4DB3A7FFF83FF18 /* KBMyTheme.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBMyTheme.m; sourceTree = "<group>"; };
2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CustomKeyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CustomKeyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; };
35E2B1C590E060D912A4E7F4 /* KBShopThemeTagModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopThemeTagModel.h; sourceTree = "<group>"; }; 35E2B1C590E060D912A4E7F4 /* KBShopThemeTagModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopThemeTagModel.h; sourceTree = "<group>"; };
@@ -957,6 +979,16 @@
04122FAF2EC73C0100EF7AB3 /* KBVipReviewItemCell.m */, 04122FAF2EC73C0100EF7AB3 /* KBVipReviewItemCell.m */,
04122FB12EC73C0100EF7AB3 /* KBVipReviewListCell.h */, 04122FB12EC73C0100EF7AB3 /* KBVipReviewListCell.h */,
04122FB22EC73C0100EF7AB3 /* KBVipReviewListCell.m */, 04122FB22EC73C0100EF7AB3 /* KBVipReviewListCell.m */,
04F4C0AE2F322EF200E8F08C /* PagingViewTableHeaderView.h */,
04F4C0AF2F322EF200E8F08C /* PagingViewTableHeaderView.m */,
04F4C0B12F33053800E8F08C /* KBSvipBenefitCell.h */,
04F4C0B22F33053800E8F08C /* KBSvipBenefitCell.m */,
04F4C0B32F33053800E8F08C /* KBSvipSubscribeCell.h */,
04F4C0B42F33053800E8F08C /* KBSvipSubscribeCell.m */,
04F4C0B72F3306CF00E8F08C /* KBSvipBenefitBgView.h */,
04F4C0B82F3306CF00E8F08C /* KBSvipBenefitBgView.m */,
04F4C0B92F3306CF00E8F08C /* KBSvipFlowLayout.h */,
04F4C0BA2F3306CF00E8F08C /* KBSvipFlowLayout.m */,
); );
path = V; path = V;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -968,6 +1000,10 @@
04122F802EC5FC6F00EF7AB3 /* KBJfPay.m */, 04122F802EC5FC6F00EF7AB3 /* KBJfPay.m */,
04122F8F2EC73AF700EF7AB3 /* KBVipPay.h */, 04122F8F2EC73AF700EF7AB3 /* KBVipPay.h */,
04122F902EC73AF700EF7AB3 /* KBVipPay.m */, 04122F902EC73AF700EF7AB3 /* KBVipPay.m */,
04F4C0A82F32274000E8F08C /* KBPayMainVC.h */,
04F4C0A92F32274000E8F08C /* KBPayMainVC.m */,
04F4C0AB2F32288600E8F08C /* KBPaySvipVC.h */,
04F4C0AC2F32288600E8F08C /* KBPaySvipVC.m */,
); );
path = VC; path = VC;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1120,8 +1156,6 @@
0460866E2F191A5100757C95 /* VC */ = { 0460866E2F191A5100757C95 /* VC */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
046086712F191B6900757C95 /* KBAiMainVC.h */,
046086722F191B6900757C95 /* KBAiMainVC.m */,
048FFD092F273BFC005D62AE /* KBAIHomeVC.h */, 048FFD092F273BFC005D62AE /* KBAIHomeVC.h */,
048FFD0A2F273BFC005D62AE /* KBAIHomeVC.m */, 048FFD0A2F273BFC005D62AE /* KBAIHomeVC.m */,
048FFD2B2F29F356005D62AE /* KBAIMessageVC.h */, 048FFD2B2F29F356005D62AE /* KBAIMessageVC.h */,
@@ -1454,6 +1488,8 @@
048FFD232F28A836005D62AE /* KBChatLimitPopView.m */, 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */,
0F2A10112F3C0002002CA5A0 /* KBAIPersonaSidebarView.h */, 0F2A10112F3C0002002CA5A0 /* KBAIPersonaSidebarView.h */,
0F2A10122F3C0002002CA5A0 /* KBAIPersonaSidebarView.m */, 0F2A10122F3C0002002CA5A0 /* KBAIPersonaSidebarView.m */,
04F4C0BD2F33369900E8F08C /* KBAIChatDeleteConfirmView.h */,
04F4C0BE2F33369900E8F08C /* KBAIChatDeleteConfirmView.m */,
); );
path = PopView; path = PopView;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2350,14 +2386,15 @@
0498BD862EE1BEC9006CC1D5 /* KBSignUtils.m in Sources */, 0498BD862EE1BEC9006CC1D5 /* KBSignUtils.m in Sources */,
04791FFC2ED71D17004E8522 /* UIColor+Extension.m in Sources */, 04791FFC2ED71D17004E8522 /* UIColor+Extension.m in Sources */,
0450AC4A2EF2C3ED00B6AF06 /* KBKeyboardSubscriptionOptionCell.m in Sources */, 0450AC4A2EF2C3ED00B6AF06 /* KBKeyboardSubscriptionOptionCell.m in Sources */,
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */, 04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */,
048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */, 048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */,
048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */, 048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */,
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */, A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */,
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */, 04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */, A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */, A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */,
A1B2C3EB2F20000000000001 /* KBSuggestionBarView.m in Sources */, A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */,
A1B2C3EB2F20000000000001 /* KBSuggestionBarView.m in Sources */,
0419C9662F2C7693002E86D3 /* KBVM.m in Sources */, 0419C9662F2C7693002E86D3 /* KBVM.m in Sources */,
048FFD512F2B68F7005D62AE /* KBPersonaModel.m in Sources */, 048FFD512F2B68F7005D62AE /* KBPersonaModel.m in Sources */,
04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */, 04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */,
@@ -2418,6 +2455,7 @@
04122F622EC5F41D00EF7AB3 /* KBUser.m in Sources */, 04122F622EC5F41D00EF7AB3 /* KBUser.m in Sources */,
04122F8B2EC6F7C800EF7AB3 /* IAPVerifyTransactionObj.m in Sources */, 04122F8B2EC6F7C800EF7AB3 /* IAPVerifyTransactionObj.m in Sources */,
04B5A1A22EEFA12300AAAAAA /* KBPayProductModel.m in Sources */, 04B5A1A22EEFA12300AAAAAA /* KBPayProductModel.m in Sources */,
04F4C0AD2F32288600E8F08C /* KBPaySvipVC.m in Sources */,
046086D62F1A093400757C95 /* KBAICommentInputView.m in Sources */, 046086D62F1A093400757C95 /* KBAICommentInputView.m in Sources */,
046086D72F1A093400757C95 /* KBAICommentFooterView.m in Sources */, 046086D72F1A093400757C95 /* KBAICommentFooterView.m in Sources */,
046086D82F1A093400757C95 /* KBAIReplyCell.m in Sources */, 046086D82F1A093400757C95 /* KBAIReplyCell.m in Sources */,
@@ -2433,7 +2471,6 @@
04122FAD2EC73C0100EF7AB3 /* KBVipSubscribeCell.m in Sources */, 04122FAD2EC73C0100EF7AB3 /* KBVipSubscribeCell.m in Sources */,
049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */, 049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */,
048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */, 048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */,
046086732F191B6900757C95 /* KBAiMainVC.m in Sources */,
048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */, 048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */,
048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */, 048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */,
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */, 048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */,
@@ -2452,6 +2489,7 @@
046086CC2F1A092500757C95 /* KBAIReplyModel.m in Sources */, 046086CC2F1A092500757C95 /* KBAIReplyModel.m in Sources */,
046086CD2F1A092500757C95 /* KBAICommentModel.m in Sources */, 046086CD2F1A092500757C95 /* KBAICommentModel.m in Sources */,
04791F8F2ED469C0004E8522 /* KBHostAppLauncher.m in Sources */, 04791F8F2ED469C0004E8522 /* KBHostAppLauncher.m in Sources */,
04F4C0BF2F33369900E8F08C /* KBAIChatDeleteConfirmView.m in Sources */,
047C65582EBCC06D0035E841 /* HomeRankCardCell.m in Sources */, 047C65582EBCC06D0035E841 /* HomeRankCardCell.m in Sources */,
04D1F6B32EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */, 04D1F6B32EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */,
04122F912EC73AF700EF7AB3 /* KBVipPay.m in Sources */, 04122F912EC73AF700EF7AB3 /* KBVipPay.m in Sources */,
@@ -2487,6 +2525,7 @@
048908E92EBF843000FABA60 /* KBSkinDetailHeaderCell.m in Sources */, 048908E92EBF843000FABA60 /* KBSkinDetailHeaderCell.m in Sources */,
04A9FE1B2EB892460020DB6D /* KBLocalizationManager.m in Sources */, 04A9FE1B2EB892460020DB6D /* KBLocalizationManager.m in Sources */,
048908BC2EBE1FCB00FABA60 /* BaseViewController.m in Sources */, 048908BC2EBE1FCB00FABA60 /* BaseViewController.m in Sources */,
04F4C0B02F322EF200E8F08C /* PagingViewTableHeaderView.m in Sources */,
0498BD902EE6A3BD006CC1D5 /* KBMyMainModel.m in Sources */, 0498BD902EE6A3BD006CC1D5 /* KBMyMainModel.m in Sources */,
A1F0C1C32FABCDEF12345678 /* KBInviteCodeModel.m in Sources */, A1F0C1C32FABCDEF12345678 /* KBInviteCodeModel.m in Sources */,
A1F0C1D32FACAD0012345678 /* KBMaiPointReporter.m in Sources */, A1F0C1D32FACAD0012345678 /* KBMaiPointReporter.m in Sources */,
@@ -2523,6 +2562,8 @@
047C655C2EBCD0F80035E841 /* UIView+KBShadow.m in Sources */, 047C655C2EBCD0F80035E841 /* UIView+KBShadow.m in Sources */,
04E038DD2F20C420002CA5A0 /* VoiceChatStreamingManager.m in Sources */, 04E038DD2F20C420002CA5A0 /* VoiceChatStreamingManager.m in Sources */,
04E038DE2F20C420002CA5A0 /* VoiceChatWebSocketClient.m in Sources */, 04E038DE2F20C420002CA5A0 /* VoiceChatWebSocketClient.m in Sources */,
04F4C0B52F33053800E8F08C /* KBSvipBenefitCell.m in Sources */,
04F4C0B62F33053800E8F08C /* KBSvipSubscribeCell.m in Sources */,
049FB2262EC3136D00FAB05D /* KBPersonInfoItemCell.m in Sources */, 049FB2262EC3136D00FAB05D /* KBPersonInfoItemCell.m in Sources */,
048908C32EBE32B800FABA60 /* KBSearchVC.m in Sources */, 048908C32EBE32B800FABA60 /* KBSearchVC.m in Sources */,
049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */, 049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */,
@@ -2530,6 +2571,7 @@
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */, 04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */,
04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */, 04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */,
048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */, 048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */,
04F4C0AA2F32274000E8F08C /* KBPayMainVC.m in Sources */,
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */, 048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */,
048908F22EC047FD00FABA60 /* KBShopHeadView.m in Sources */, 048908F22EC047FD00FABA60 /* KBShopHeadView.m in Sources */,
0498BD742EE02E3D006CC1D5 /* KBRegistVerEmailVC.m in Sources */, 0498BD742EE02E3D006CC1D5 /* KBRegistVerEmailVC.m in Sources */,
@@ -2591,6 +2633,8 @@
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */, 047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */,
0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */, 0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */,
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */, 0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */,
04F4C0BB2F3306CF00E8F08C /* KBSvipFlowLayout.m in Sources */,
04F4C0BC2F3306CF00E8F08C /* KBSvipBenefitBgView.m in Sources */,
04E039522F2387D2002CA5A0 /* KBAiChatMessage.m in Sources */, 04E039522F2387D2002CA5A0 /* KBAiChatMessage.m in Sources */,
0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */, 0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */,
0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */, 0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */,

View File

@@ -21,7 +21,7 @@
#import "KBLoginPopView.h" #import "KBLoginPopView.h"
#import "KBSexSelVC.h" #import "KBSexSelVC.h"
#import "KBKeyboardPermissionManager.h" #import "KBKeyboardPermissionManager.h"
#import "KBVipPay.h" #import "KBPayMainVC.h"
#import "KBUserSessionManager.h" #import "KBUserSessionManager.h"
#import "KBLoginVC.h" #import "KBLoginVC.h"
#import "KBConfig.h" #import "KBConfig.h"
@@ -192,6 +192,9 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
return YES; return YES;
} else if ([host isEqualToString:@"recharge"]) { // kbkeyboard://recharge } else if ([host isEqualToString:@"recharge"]) { // kbkeyboard://recharge
NSDictionary<NSString *, NSString *> *params = [self kb_queryParametersFromURL:url]; NSDictionary<NSString *, NSString *> *params = [self kb_queryParametersFromURL:url];
NSString *vipType = [params[@"vipType"] lowercaseString];
BOOL preferSvip = ([vipType isKindOfClass:NSString.class] && vipType.length > 0 &&
([vipType isEqualToString:@"svip"] || [vipType isEqualToString:@"1"]));
NSString *productId = params[@"productId"]; NSString *productId = params[@"productId"];
BOOL autoPay = NO; BOOL autoPay = NO;
NSString *autoFlag = params[@"autoPay"]; NSString *autoFlag = params[@"autoPay"];
@@ -203,34 +206,37 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
autoPay = YES; autoPay = YES;
} }
BOOL wantsPrefill = NO; KBPayMainVC *vc = [[KBPayMainVC alloc] init];
NSString *prefillFlag = params[@"prefill"]; vc.initialSelectedIndex = preferSvip ? 1 : 0;
if ([prefillFlag respondsToSelector:@selector(boolValue)] && prefillFlag.boolValue) { if (!preferSvip) {
wantsPrefill = YES; BOOL wantsPrefill = NO;
} NSString *prefillFlag = params[@"prefill"];
NSString *src = params[@"src"]; if ([prefillFlag respondsToSelector:@selector(boolValue)] && prefillFlag.boolValue) {
if ([src isKindOfClass:NSString.class] && [src.lowercaseString isEqualToString:@"keyboard"]) { wantsPrefill = YES;
wantsPrefill = YES; }
} NSString *src = params[@"src"];
NSDictionary *prefillPayload = wantsPrefill ? [self kb_consumeSubscriptionPrefillPayloadIfValid] : nil; if ([src isKindOfClass:NSString.class] && [src.lowercaseString isEqualToString:@"keyboard"]) {
if ([prefillPayload isKindOfClass:NSDictionary.class]) { wantsPrefill = YES;
NSString *payloadProductId = prefillPayload[@"productId"]; }
if (productId.length == 0 && [payloadProductId isKindOfClass:NSString.class]) { NSDictionary *prefillPayload = wantsPrefill ? [self kb_consumeSubscriptionPrefillPayloadIfValid] : nil;
productId = payloadProductId; if ([prefillPayload isKindOfClass:NSDictionary.class]) {
NSString *payloadProductId = prefillPayload[@"productId"];
if (productId.length == 0 && [payloadProductId isKindOfClass:NSString.class]) {
productId = payloadProductId;
}
} }
}
KBVipPay *vc = [[KBVipPay alloc] init]; if ([prefillPayload isKindOfClass:NSDictionary.class]) {
if ([prefillPayload isKindOfClass:NSDictionary.class]) { NSArray *productsJSON = prefillPayload[@"products"];
NSArray *productsJSON = prefillPayload[@"products"]; NSNumber *selectedIndexNumber = prefillPayload[@"selectedIndex"];
NSNumber *selectedIndexNumber = prefillPayload[@"selectedIndex"]; NSInteger selectedIndex = [selectedIndexNumber respondsToSelector:@selector(integerValue)] ? selectedIndexNumber.integerValue : NSNotFound;
NSInteger selectedIndex = [selectedIndexNumber respondsToSelector:@selector(integerValue)] ? selectedIndexNumber.integerValue : NSNotFound; [vc configureWithProductId:productId
[vc configureWithProductId:productId autoPurchase:autoPay
autoPurchase:autoPay prefillProductsJSON:productsJSON
prefillProductsJSON:productsJSON selectedIndex:selectedIndex];
selectedIndex:selectedIndex]; } else {
} else { [vc configureWithProductId:productId autoPurchase:autoPay];
[vc configureWithProductId:productId autoPurchase:autoPay]; }
} }
[KB_CURRENT_NAV pushViewController:vc animated:true]; [KB_CURRENT_NAV pushViewController:vc animated:true];
return YES; return YES;

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ai_limit_close@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ai_limit_close@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ai_limit_goto@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ai_limit_goto@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ai_limit_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ai_limit_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_del_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_del_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "SVIP_Normal_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "SVIP_Normal_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "SVIP_Selected_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "SVIP_Selected_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "VIP_Normal_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "VIP_Normal_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "VIP_Selected_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "VIP_Selected_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_ai_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_ai_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_chat_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_chat_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_colorbg_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_colorbg_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_graybg_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_graybg_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_history_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_history_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_keyboard_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_keyboard_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_leftline_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_leftline_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 B

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_oks_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_oks_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 B

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_person_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_person_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_phone_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_phone_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_rightline_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_rightline_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_soon_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_soon_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "pay_speed_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "pay_speed_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -43,6 +43,10 @@ typedef NS_ENUM(NSInteger, KBAIReplyFooterState) {
/// 是否已点赞 /// 是否已点赞
@property(nonatomic, assign) BOOL liked; @property(nonatomic, assign) BOOL liked;
@property(nonatomic, assign) NSString *replyToUserId;
@property(nonatomic, assign) NSString *replyToUserName;
/// 创建时间(时间戳) /// 创建时间(时间戳)
@property(nonatomic, assign) NSTimeInterval createTime; @property(nonatomic, assign) NSTimeInterval createTime;

View File

@@ -59,6 +59,9 @@
if (!_content) { if (!_content) {
_content = @""; _content = @"";
} }
if (!_replyToUserName) {
_replyToUserName = @"";
}
} }
- (instancetype)init { - (instancetype)init {

View File

@@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, copy) NSString *content; @property(nonatomic, copy) NSString *content;
/// 被回复的用户名(@xxx /// 被回复的用户名(@xxx
@property(nonatomic, copy, nullable) NSString *replyToUserName; @property(nonatomic, copy) NSString *replyToUserName;
/// 点赞数 /// 点赞数
@property(nonatomic, assign) NSInteger likeCount; @property(nonatomic, assign) NSInteger likeCount;

View File

@@ -55,6 +55,9 @@
if (!_content) { if (!_content) {
_content = @""; _content = @"";
} }
// if ([_content isEqualToString:@"78910"]) {
// NSLog(@"===");
// }
if (!_replyToUserName) { if (!_replyToUserName) {
_replyToUserName = @""; _replyToUserName = @"";
} }

View File

@@ -22,6 +22,9 @@ typedef NS_ENUM(NSInteger, KBAiChatMessageType) {
/// 消息类型 /// 消息类型
@property (nonatomic, assign) KBAiChatMessageType type; @property (nonatomic, assign) KBAiChatMessageType type;
/// 聊天记录 ID服务端返回的 id用于删除等操作0 表示本地临时消息)
@property (nonatomic, assign) NSInteger historyId;
/// 文本内容 /// 文本内容
@property (nonatomic, copy) NSString *text; @property (nonatomic, copy) NSString *text;

View File

@@ -33,6 +33,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, nullable) NSArray<KBCommentItem *> *replies; @property (nonatomic, strong, nullable) NSArray<KBCommentItem *> *replies;
/// 回复数量 /// 回复数量
@property (nonatomic, assign) NSInteger replyCount; @property (nonatomic, assign) NSInteger replyCount;
/// 被回复的用户 ID仅二级回复场景可能存在
@property (nonatomic, strong, nullable) NSNumber *replyToUserId;
/// 被回复的用户名(@xxx仅二级回复场景可能存在
@property (nonatomic, copy, nullable) NSString *replyToUserName;
/// 用户头像 /// 用户头像
@property (nonatomic, copy, nullable) NSString *userAvatar; @property (nonatomic, copy, nullable) NSString *userAvatar;
/// 用户 ID /// 用户 ID

View File

@@ -28,6 +28,13 @@ typedef NS_ENUM(NSInteger, KBChatMessageActionType) {
@property (nonatomic, weak) id<KBChatMessageActionPopViewDelegate> delegate; @property (nonatomic, weak) id<KBChatMessageActionPopViewDelegate> delegate;
/// 是否显示 “Report” 操作(默认 YES
/// - 当长按的是右侧用户消息KBChatUserMessageCell可设置为 NO。
@property (nonatomic, assign) BOOL showsReportAction;
/// 根据是否显示 Report 计算推荐高度
+ (CGFloat)preferredHeightWithShowsReportAction:(BOOL)showsReportAction;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -22,10 +22,20 @@ static CGFloat const kKBChatActionRowHeight = 52.0;
@implementation KBChatMessageActionPopView @implementation KBChatMessageActionPopView
+ (CGFloat)preferredHeightWithShowsReportAction:(BOOL)showsReportAction {
// 2 Copy + Delete
// 3 Copy + Delete + Report
NSInteger rows = showsReportAction ? 3 : 2;
NSInteger lines = showsReportAction ? 2 : 1;
return kKBChatActionRowHeight * rows + 0.5 * lines;
}
- (instancetype)initWithFrame:(CGRect)frame { - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self) { if (self) {
_showsReportAction = YES;
[self setupUI]; [self setupUI];
[self applyReportVisibility];
} }
return self; return self;
} }
@@ -73,6 +83,32 @@ static CGFloat const kKBChatActionRowHeight = 52.0;
}]; }];
} }
- (void)setShowsReportAction:(BOOL)showsReportAction {
if (_showsReportAction == showsReportAction) {
return;
}
_showsReportAction = showsReportAction;
[self applyReportVisibility];
}
- (void)applyReportVisibility {
BOOL show = self.showsReportAction;
self.reportRow.hidden = !show;
self.reportRow.userInteractionEnabled = show;
self.line2.hidden = !show;
// frame
[self.line2 mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(show ? 0.5 : 0.0);
}];
[self.reportRow mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(show ? kKBChatActionRowHeight : 0.0);
}];
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (UIControl *)buildRowWithTitle:(NSString *)title - (UIControl *)buildRowWithTitle:(NSString *)title
iconName:(NSString *)iconName iconName:(NSString *)iconName
action:(KBChatMessageActionType)action { action:(KBChatMessageActionType)action {

View File

@@ -22,7 +22,7 @@
/// ///
static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification"; static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification";
@interface KBPersonaChatCell () <KBChatTableViewDelegate, KBChatMessageActionPopViewDelegate> @interface KBPersonaChatCell () <KBChatTableViewDelegate, KBChatMessageActionPopViewDelegate, KBAICommentViewDelegate>
/// ///
@property (nonatomic, strong) UIImageView *backgroundImageView; @property (nonatomic, strong) UIImageView *backgroundImageView;
@@ -354,6 +354,7 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
message.isComplete = YES; message.isComplete = YES;
message.needsTypewriterEffect = NO; message.needsTypewriterEffect = NO;
message.historyId = item.messageId;
[newMessages addObject:message]; [newMessages addObject:message];
// [newMessages insertObject:message atIndex:0]; // [newMessages insertObject:message atIndex:0];
} }
@@ -931,7 +932,13 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
} break; } break;
case KBChatMessageActionTypeDelete: { case KBChatMessageActionTypeDelete: {
NSInteger idx = [self.messages indexOfObjectIdenticalTo:message]; NSInteger idx = [self.messages indexOfObjectIdenticalTo:message];
if (idx != NSNotFound) { if (idx == NSNotFound) {
return;
}
NSInteger historyId = message.historyId;
// id /
if (historyId <= 0) {
[self.messages removeObjectAtIndex:idx]; [self.messages removeObjectAtIndex:idx];
[self.chatView reloadWithMessages:self.messages [self.chatView reloadWithMessages:self.messages
keepOffset:YES keepOffset:YES
@@ -944,7 +951,44 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
[[KBAIChatMessageCacheManager shared] clearMessagesForCompanionId:self.persona.personaId]; [[KBAIChatMessageCacheManager shared] clearMessagesForCompanionId:self.persona.personaId];
} }
} }
return;
} }
[KBHUD show];
__weak typeof(self) weakSelf = self;
[self.aiVM deleteChatHistoryWithId:historyId completion:^(BOOL success, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
[KBHUD dismiss];
if (!success || error) {
NSString *msg = error.localizedDescription ?: KBLocalized(@"删除失败,请重试");
[KBHUD showError:msg];
return;
}
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
NSInteger idx2 = [strongSelf.messages indexOfObjectIdenticalTo:message];
if (idx2 == NSNotFound) {
return;
}
[strongSelf.messages removeObjectAtIndex:idx2];
[strongSelf.chatView reloadWithMessages:strongSelf.messages
keepOffset:YES
scrollToBottom:NO];
if (strongSelf.persona.personaId > 0) {
if (strongSelf.messages.count > 0) {
[[KBAIChatMessageCacheManager shared] saveMessages:strongSelf.messages
forCompanionId:strongSelf.persona.personaId];
} else {
[[KBAIChatMessageCacheManager shared] clearMessagesForCompanionId:strongSelf.persona.personaId];
}
}
});
}];
} break; } break;
case KBChatMessageActionTypeReport: { case KBChatMessageActionTypeReport: {
if (self.persona.personaId <= 0) { if (self.persona.personaId <= 0) {
@@ -970,10 +1014,13 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
self.selectedActionMessage = message; self.selectedActionMessage = message;
CGFloat width = 240; CGFloat width = 240;
CGFloat height = 156; BOOL isUserMessage = (message.type == KBAiChatMessageTypeUser);
BOOL showsReport = !isUserMessage;
CGFloat height = [KBChatMessageActionPopView preferredHeightWithShowsReportAction:showsReport];
KBChatMessageActionPopView *content = [[KBChatMessageActionPopView alloc] KBChatMessageActionPopView *content = [[KBChatMessageActionPopView alloc]
initWithFrame:CGRectMake(0, 0, width, height)]; initWithFrame:CGRectMake(0, 0, width, height)];
content.delegate = self; content.delegate = self;
content.showsReportAction = showsReport;
UIWindow *window = [UIApplication sharedApplication].keyWindow; UIWindow *window = [UIApplication sharedApplication].keyWindow;
if (!window) { if (!window) {
@@ -988,7 +1035,6 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
[window addSubview:mask]; [window addSubview:mask];
self.messageActionMaskView = mask; self.messageActionMaskView = mask;
BOOL isUserMessage = (message.type == KBAiChatMessageTypeUser);
CGFloat margin = 12.0; CGFloat margin = 12.0;
CGFloat spacing = 8.0; CGFloat spacing = 8.0;
CGFloat topSafe = 0.0; CGFloat topSafe = 0.0;
@@ -1204,6 +1250,7 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
CGFloat customViewHeight = KB_SCREEN_HEIGHT * 0.75; CGFloat customViewHeight = KB_SCREEN_HEIGHT * 0.75;
KBAICommentView *customView = [[KBAICommentView alloc] KBAICommentView *customView = [[KBAICommentView alloc]
initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, customViewHeight)]; initWithFrame:CGRectMake(0, 0, KB_SCREEN_WIDTH, customViewHeight)];
customView.delegate = self;
NSString *commentCount = self.persona.commentCount; NSString *commentCount = self.persona.commentCount;
NSInteger totalCommentCount = [commentCount integerValue];; NSInteger totalCommentCount = [commentCount integerValue];;
@@ -1235,6 +1282,18 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
[popView pop]; [popView pop];
} }
#pragma mark - KBAICommentViewDelegate
- (void)commentView:(KBAICommentView *)view didUpdateTotalCommentCount:(NSInteger)totalCommentCount {
// cell
if (view.companionId <= 0 || view.companionId != self.persona.personaId) {
return;
}
self.persona.commentCount = [NSString stringWithFormat:@"%ld", (long)totalCommentCount];
[self.commentButton setTitle:self.persona.commentCount forState:UIControlStateNormal];
}
- (AiVM *)aiVM{ - (AiVM *)aiVM{

View File

@@ -99,8 +99,14 @@
- (void)sendButtonTapped { - (void)sendButtonTapped {
NSString *text = self.textField.text; NSString *text = self.textField.text;
if (text.length > 0 && self.onSend) { if (text.length > 0) {
self.onSend(text); if (self.onSend) {
self.onSend(text);
}
//
[self clearText];
//
[self.textField resignFirstResponder];
} }
} }

View File

@@ -10,9 +10,19 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@class KBAICommentView;
@protocol KBAICommentViewDelegate <NSObject>
@optional
/// 评论总数变化回调(例如发送评论/回复成功后)
- (void)commentView:(KBAICommentView *)view didUpdateTotalCommentCount:(NSInteger)totalCommentCount;
@end
/// 抖音风格评论视图 /// 抖音风格评论视图
@interface KBAICommentView : UIView @interface KBAICommentView : UIView
@property(nonatomic, weak, nullable) id<KBAICommentViewDelegate> delegate;
/// AI 陪聊角色 ID /// AI 陪聊角色 ID
@property(nonatomic, assign) NSInteger companionId; @property(nonatomic, assign) NSInteger companionId;

View File

@@ -940,6 +940,9 @@ static NSInteger const kRepliesLoadCount = 5;
strongSelf.totalCommentCount += 1; strongSelf.totalCommentCount += 1;
[strongSelf updateTitle]; [strongSelf updateTitle];
[strongSelf hideEmptyState]; [strongSelf hideEmptyState];
if ([strongSelf.delegate respondsToSelector:@selector(commentView:didUpdateTotalCommentCount:)]) {
[strongSelf.delegate commentView:strongSelf didUpdateTotalCommentCount:strongSelf.totalCommentCount];
}
[strongSelf.tableView beginUpdates]; [strongSelf.tableView beginUpdates];
[strongSelf.tableView [strongSelf.tableView
@@ -1044,6 +1047,9 @@ static NSInteger const kRepliesLoadCount = 5;
strongSelf.totalCommentCount += 1; strongSelf.totalCommentCount += 1;
[strongSelf updateTitle]; [strongSelf updateTitle];
if ([strongSelf.delegate respondsToSelector:@selector(commentView:didUpdateTotalCommentCount:)]) {
[strongSelf.delegate commentView:strongSelf didUpdateTotalCommentCount:strongSelf.totalCommentCount];
}
// displayedReplies loadMoreReplies // displayedReplies loadMoreReplies
if (wasFullyExpanded) { if (wasFullyExpanded) {

View File

@@ -98,7 +98,7 @@
NSDictionary *nameAttrs = @{ NSDictionary *nameAttrs = @{
NSFontAttributeName : [UIFont systemFontOfSize:13 weight:UIFontWeightMedium], NSFontAttributeName : [UIFont systemFontOfSize:13 weight:UIFontWeightMedium],
NSForegroundColorAttributeName : [UIColor secondaryLabelColor] NSForegroundColorAttributeName : [UIColor whiteColor]
}; };
[attrName appendAttributedString:[[NSAttributedString alloc] [attrName appendAttributedString:[[NSAttributedString alloc]
initWithString:reply.userName initWithString:reply.userName
@@ -106,7 +106,7 @@
NSDictionary *replyAttrs = @{ NSDictionary *replyAttrs = @{
NSFontAttributeName : [UIFont systemFontOfSize:13], NSFontAttributeName : [UIFont systemFontOfSize:13],
NSForegroundColorAttributeName : [UIColor secondaryLabelColor] NSForegroundColorAttributeName : [UIColor whiteColor]
}; };
[attrName appendAttributedString:[[NSAttributedString alloc] [attrName appendAttributedString:[[NSAttributedString alloc]
initWithString:@" 回复 " initWithString:@" 回复 "
@@ -114,7 +114,7 @@
NSDictionary *toUserAttrs = @{ NSDictionary *toUserAttrs = @{
NSFontAttributeName : [UIFont systemFontOfSize:13], NSFontAttributeName : [UIFont systemFontOfSize:13],
NSForegroundColorAttributeName : [UIColor systemBlueColor] NSForegroundColorAttributeName : [UIColor whiteColor]
}; };
[attrName appendAttributedString:[[NSAttributedString alloc] [attrName appendAttributedString:[[NSAttributedString alloc]
initWithString:[NSString stringWithFormat:@"@%@", reply.replyToUserName] initWithString:[NSString stringWithFormat:@"@%@", reply.replyToUserName]

View File

@@ -0,0 +1,27 @@
//
// KBAIChatDeleteConfirmView.h
// keyBoard
//
// Created by Codex on 2026/02/03.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@class KBAIChatDeleteConfirmView;
@protocol KBAIChatDeleteConfirmViewDelegate <NSObject>
- (void)chatDeleteConfirmViewDidTapDelete:(KBAIChatDeleteConfirmView *)view;
- (void)chatDeleteConfirmViewDidTapCancel:(KBAIChatDeleteConfirmView *)view;
@end
@interface KBAIChatDeleteConfirmView : UIView
@property (nonatomic, weak) id<KBAIChatDeleteConfirmViewDelegate> delegate;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,172 @@
//
// KBAIChatDeleteConfirmView.m
// keyBoard
//
// Created by Codex on 2026/02/03.
//
#import "KBAIChatDeleteConfirmView.h"
#import <Masonry/Masonry.h>
@interface KBAIChatDeleteConfirmView ()
@property (nonatomic, strong) UIView *coverView;
@property (nonatomic, strong) UIImageView *iconView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *messageLabel;
@property (nonatomic, strong) UIButton *deleteButton;
@property (nonatomic, strong) UIButton *cancelButton;
@end
@implementation KBAIChatDeleteConfirmView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
self.layer.cornerRadius = 16.0;
self.layer.masksToBounds = YES;
[self setupUI];
}
return self;
}
#pragma mark - UI
- (void)setupUI {
[self addSubview:self.coverView];
[self addSubview:self.iconView];
[self.coverView addSubview:self.titleLabel];
[self.coverView addSubview:self.messageLabel];
[self.coverView addSubview:self.deleteButton];
[self.coverView addSubview:self.cancelButton];
[self.coverView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(216);
make.bottom.left.right.bottom.equalTo(self);
}];
[self.iconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(5);
make.centerX.equalTo(self);
make.width.height.mas_equalTo(64);
}];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.coverView).offset(50);
make.left.equalTo(self.coverView).offset(16);
make.right.equalTo(self.coverView).offset(-16);
}];
[self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.titleLabel.mas_bottom).offset(16);
make.left.equalTo(self.coverView).offset(20);
make.right.equalTo(self.coverView).offset(-20);
}];
[self.deleteButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.coverView).offset(24);
make.bottom.equalTo(self.coverView).offset(-20);
make.height.mas_equalTo(40);
make.right.equalTo(self.coverView.mas_centerX).offset(-15);
}];
[self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.coverView).offset(-24);
make.bottom.equalTo(self.coverView).offset(-20);
make.height.mas_equalTo(40);
make.left.equalTo(self.coverView.mas_centerX).offset(15);
}];
}
#pragma mark - Actions
- (void)onTapDelete {
if ([self.delegate respondsToSelector:@selector(chatDeleteConfirmViewDidTapDelete:)]) {
[self.delegate chatDeleteConfirmViewDidTapDelete:self];
}
}
- (void)onTapCancel {
if ([self.delegate respondsToSelector:@selector(chatDeleteConfirmViewDidTapCancel:)]) {
[self.delegate chatDeleteConfirmViewDidTapCancel:self];
}
}
#pragma mark - Lazy
- (UIImageView *)iconView {
if (!_iconView) {
_iconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"chat_del_icon"]];
_iconView.contentMode = UIViewContentModeScaleAspectFit;
}
return _iconView;
}
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] init];
_titleLabel.text = KBLocalized(@"Are you sure to delete?");
_titleLabel.font = [UIFont boldSystemFontOfSize:18];
_titleLabel.textColor = [UIColor colorWithWhite:0.1 alpha:1.0];
_titleLabel.textAlignment = NSTextAlignmentCenter;
}
return _titleLabel;
}
- (UILabel *)messageLabel {
if (!_messageLabel) {
_messageLabel = [[UILabel alloc] init];
_messageLabel.text = KBLocalized(@"The existing conversation history will be cleared.");
_messageLabel.font = [UIFont systemFontOfSize:14];
_messageLabel.textColor = [UIColor colorWithWhite:0.45 alpha:1.0];
_messageLabel.textAlignment = NSTextAlignmentCenter;
_messageLabel.numberOfLines = 0;
}
return _messageLabel;
}
- (UIButton *)deleteButton {
if (!_deleteButton) {
_deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_deleteButton setTitle:KBLocalized(@"Delete") forState:UIControlStateNormal];
[_deleteButton setTitleColor:[UIColor colorWithWhite:0.2 alpha:1.0] forState:UIControlStateNormal];
_deleteButton.titleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold];
_deleteButton.backgroundColor = [UIColor colorWithWhite:0.93 alpha:1.0];
_deleteButton.layer.cornerRadius = 20;
_deleteButton.layer.masksToBounds = YES;
[_deleteButton addTarget:self action:@selector(onTapDelete) forControlEvents:UIControlEventTouchUpInside];
}
return _deleteButton;
}
- (UIButton *)cancelButton {
if (!_cancelButton) {
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_cancelButton setTitle:KBLocalized(@"Think Again") forState:UIControlStateNormal];
[_cancelButton setTitleColor:[UIColor colorWithWhite:0.15 alpha:1.0] forState:UIControlStateNormal];
_cancelButton.titleLabel.font = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold];
_cancelButton.backgroundColor = [UIColor colorWithRed:0.80 green:0.94 blue:0.72 alpha:1.0];
_cancelButton.layer.cornerRadius = 20;
_cancelButton.layer.masksToBounds = YES;
[_cancelButton addTarget:self action:@selector(onTapCancel) forControlEvents:UIControlEventTouchUpInside];
}
return _cancelButton;
}
- (UIView *)coverView{
if (!_coverView) {
_coverView = [[UIView alloc] init];
_coverView.backgroundColor = [UIColor whiteColor];
_coverView.layer.cornerRadius = 30;
_coverView.layer.masksToBounds = true;
}
return _coverView;
}
@end

View File

@@ -458,6 +458,8 @@
if (!_searchField) { if (!_searchField) {
_searchField = [[UITextField alloc] init]; _searchField = [[UITextField alloc] init];
_searchField.placeholder = KBLocalized(@"Search Role"); _searchField.placeholder = KBLocalized(@"Search Role");
_searchField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:KBLocalized(@"Search Role")
attributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
_searchField.textColor = [UIColor whiteColor]; _searchField.textColor = [UIColor whiteColor];
_searchField.font = [UIFont systemFontOfSize:14]; _searchField.font = [UIFont systemFontOfSize:14];
_searchField.clearButtonMode = UITextFieldViewModeWhileEditing; _searchField.clearButtonMode = UITextFieldViewModeWhileEditing;

View File

@@ -8,21 +8,25 @@
#import "KBChatLimitPopView.h" #import "KBChatLimitPopView.h"
#import <Masonry/Masonry.h> #import <Masonry/Masonry.h>
static CGFloat const kKBChatLimitIconSize = 252.0;
static CGFloat const kKBChatLimitGotoWidth = 251.0;
static CGFloat const kKBChatLimitGotoHeight = 53.0;
static CGFloat const kKBChatLimitCloseSize = 28.0;
static CGFloat const kKBChatLimitSpacing1 = 18.0;
static CGFloat const kKBChatLimitSpacing2 = 18.0;
@interface KBChatLimitPopView () @interface KBChatLimitPopView ()
@property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, strong) UIImageView *iconImageView;
@property (nonatomic, strong) UILabel *messageLabel; @property (nonatomic, strong) UILabel *messageLabel;
@property (nonatomic, strong) UIButton *cancelButton; @property (nonatomic, strong) UIButton *gotoButton;
@property (nonatomic, strong) UIButton *rechargeButton; @property (nonatomic, strong) UIButton *closeButton;
@property (nonatomic, strong) UIView *buttonDivider;
@end @end
@implementation KBChatLimitPopView @implementation KBChatLimitPopView
- (instancetype)initWithFrame:(CGRect)frame { - (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor whiteColor]; self.backgroundColor = [UIColor clearColor];
self.layer.cornerRadius = 16.0;
self.layer.masksToBounds = YES;
[self setupUI]; [self setupUI];
} }
return self; return self;
@@ -31,51 +35,37 @@
#pragma mark - UI #pragma mark - UI
- (void)setupUI { - (void)setupUI {
[self addSubview:self.titleLabel]; [self addSubview:self.iconImageView];
[self addSubview:self.messageLabel]; [self.iconImageView addSubview:self.messageLabel];
[self addSubview:self.buttonDivider]; [self addSubview:self.gotoButton];
[self addSubview:self.cancelButton]; [self addSubview:self.closeButton];
[self addSubview:self.rechargeButton];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { [self.iconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(20); make.top.equalTo(self);
make.left.equalTo(self).offset(20);
make.right.equalTo(self).offset(-20);
}];
[self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.titleLabel.mas_bottom).offset(8);
make.left.equalTo(self).offset(20);
make.right.equalTo(self).offset(-20);
}];
[self.buttonDivider mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
make.height.mas_equalTo(1);
make.top.greaterThanOrEqualTo(self.messageLabel.mas_bottom).offset(16);
make.bottom.equalTo(self).offset(-48);
}];
[self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.bottom.equalTo(self);
make.top.equalTo(self.buttonDivider.mas_bottom);
make.right.equalTo(self.mas_centerX);
}];
[self.rechargeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.bottom.equalTo(self);
make.top.equalTo(self.buttonDivider.mas_bottom);
make.left.equalTo(self.mas_centerX);
}];
UIView *verticalLine = [[UIView alloc] init];
verticalLine.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
[self addSubview:verticalLine];
[verticalLine mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self); make.centerX.equalTo(self);
make.top.equalTo(self.buttonDivider.mas_bottom); make.width.height.mas_equalTo(kKBChatLimitIconSize);
}];
//
[self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
// make.centerX.equalTo(self.iconImageView);
make.centerY.equalTo(self.iconImageView).offset(10);
make.left.equalTo(self.iconImageView).offset(26);
make.right.equalTo(self.iconImageView).offset(-46);
}];
[self.gotoButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.iconImageView.mas_bottom).offset(kKBChatLimitSpacing1);
make.centerX.equalTo(self);
make.width.mas_equalTo(kKBChatLimitGotoWidth);
make.height.mas_equalTo(kKBChatLimitGotoHeight);
}];
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.gotoButton.mas_bottom).offset(kKBChatLimitSpacing2);
make.centerX.equalTo(self);
make.width.height.mas_equalTo(kKBChatLimitCloseSize);
make.bottom.equalTo(self); make.bottom.equalTo(self);
make.width.mas_equalTo(1);
}]; }];
} }
@@ -102,56 +92,46 @@
#pragma mark - Lazy #pragma mark - Lazy
- (UILabel *)titleLabel { - (UIImageView *)iconImageView {
if (!_titleLabel) { if (!_iconImageView) {
_titleLabel = [[UILabel alloc] init]; _iconImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ai_limit_icon"]];
_titleLabel.text = KBLocalized(@"提示"); _iconImageView.contentMode = UIViewContentModeScaleAspectFit;
_titleLabel.font = [UIFont boldSystemFontOfSize:18]; _iconImageView.userInteractionEnabled = YES;
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.textAlignment = NSTextAlignmentCenter;
} }
return _titleLabel; return _iconImageView;
} }
- (UILabel *)messageLabel { - (UILabel *)messageLabel {
if (!_messageLabel) { if (!_messageLabel) {
_messageLabel = [[UILabel alloc] init]; _messageLabel = [[UILabel alloc] init];
_messageLabel.font = [UIFont systemFontOfSize:14]; _messageLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
_messageLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0]; _messageLabel.textColor = [UIColor colorWithWhite:0.18 alpha:1.0];
_messageLabel.textAlignment = NSTextAlignmentCenter; _messageLabel.textAlignment = NSTextAlignmentCenter;
_messageLabel.numberOfLines = 0; _messageLabel.numberOfLines = 0;
} }
return _messageLabel; return _messageLabel;
} }
- (UIButton *)cancelButton { - (UIButton *)gotoButton {
if (!_cancelButton) { if (!_gotoButton) {
_cancelButton = [UIButton buttonWithType:UIButtonTypeSystem]; _gotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_cancelButton setTitle:KBLocalized(@"取消") forState:UIControlStateNormal]; [_gotoButton setBackgroundImage:[UIImage imageNamed:@"ai_limit_goto"] forState:UIControlStateNormal];
_cancelButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; [_gotoButton setTitle:KBLocalized(@"Go To Recharge") forState:UIControlStateNormal];
[_cancelButton setTitleColor:[UIColor colorWithWhite:0.2 alpha:1.0] forState:UIControlStateNormal]; [_gotoButton setTitleColor:[UIColor colorWithWhite:0.1 alpha:1.0] forState:UIControlStateNormal];
[_cancelButton addTarget:self action:@selector(onTapCancel) forControlEvents:UIControlEventTouchUpInside]; _gotoButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
[_gotoButton addTarget:self action:@selector(onTapRecharge) forControlEvents:UIControlEventTouchUpInside];
} }
return _cancelButton; return _gotoButton;
} }
- (UIButton *)rechargeButton { - (UIButton *)closeButton {
if (!_rechargeButton) { if (!_closeButton) {
_rechargeButton = [UIButton buttonWithType:UIButtonTypeSystem]; _closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_rechargeButton setTitle:KBLocalized(@"去充值") forState:UIControlStateNormal]; [_closeButton setImage:[UIImage imageNamed:@"ai_limit_close"] forState:UIControlStateNormal];
_rechargeButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; [_closeButton addTarget:self action:@selector(onTapCancel) forControlEvents:UIControlEventTouchUpInside];
[_rechargeButton setTitleColor:[UIColor colorWithRed:0.28 green:0.45 blue:0.94 alpha:1.0] forState:UIControlStateNormal];
[_rechargeButton addTarget:self action:@selector(onTapRecharge) forControlEvents:UIControlEventTouchUpInside];
} }
return _rechargeButton; return _closeButton;
}
- (UIView *)buttonDivider {
if (!_buttonDivider) {
_buttonDivider = [[UIView alloc] init];
_buttonDivider.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
}
return _buttonDivider;
} }
@end @end

View File

@@ -14,7 +14,7 @@
#import "AiVM.h" #import "AiVM.h"
#import "KBHUD.h" #import "KBHUD.h"
#import "KBChatLimitPopView.h" #import "KBChatLimitPopView.h"
#import "KBVipPay.h" #import "KBPayMainVC.h"
#import "KBUserSessionManager.h" #import "KBUserSessionManager.h"
#import "LSTPopView.h" #import "LSTPopView.h"
#import "KBAIMessageVC.h" #import "KBAIMessageVC.h"
@@ -764,8 +764,9 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
[self.chatLimitPopView dismiss]; [self.chatLimitPopView dismiss];
} }
CGFloat width = KB_SCREEN_WIDTH - 60; CGFloat width = 252.0;
KBChatLimitPopView *content = [[KBChatLimitPopView alloc] initWithFrame:CGRectMake(0, 0, width, 180)]; CGFloat height = 252.0 + 18.0 + 53.0 + 18.0 + 28.0;
KBChatLimitPopView *content = [[KBChatLimitPopView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
content.message = message; content.message = message;
content.delegate = self; content.delegate = self;
@@ -841,7 +842,8 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
[[KBUserSessionManager shared] goLoginVC]; [[KBUserSessionManager shared] goLoginVC];
return; return;
} }
KBVipPay *vc = [[KBVipPay alloc] init]; KBPayMainVC *vc = [[KBPayMainVC alloc] init];
vc.initialSelectedIndex = 1; // SVIP
[KB_CURRENT_NAV pushViewController:vc animated:true]; [KB_CURRENT_NAV pushViewController:vc animated:true];
} }
@@ -1051,8 +1053,21 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
KBPersonaChatCell *cell = [strongSelf currentPersonaCell]; KBPersonaChatCell *cell = [strongSelf currentPersonaCell];
//
if (error) { if (error) {
NSInteger bizCode = [error.userInfo[@"code"] integerValue];
NSString *messageError = error.localizedDescription;
if (bizCode == 50030) {
if (cell) {
[cell removeLoadingUserMessage];
}
NSString *message = messageError ?: @"";
strongSelf.isVoiceProcessing = NO;
[strongSelf updateCollectionViewScrollState];
[strongSelf showChatLimitPopWithMessage:message];
return;
}
NSLog(@"[KBAIHomeVC] 语音转文字失败:%@", error.localizedDescription); NSLog(@"[KBAIHomeVC] 语音转文字失败:%@", error.localizedDescription);
[KBHUD showError:KBLocalized(@"语音转文字失败,请重试")]; [KBHUD showError:KBLocalized(@"语音转文字失败,请重试")];
if (cell) { if (cell) {

View File

@@ -10,12 +10,14 @@
#import "KBChattedCompanionModel.h" #import "KBChattedCompanionModel.h"
#import "KBHUD.h" #import "KBHUD.h"
#import "KBAIChatMessageCacheManager.h" #import "KBAIChatMessageCacheManager.h"
#import "KBAIChatDeleteConfirmView.h"
#import "LSTPopView.h"
#import <Masonry/Masonry.h> #import <Masonry/Masonry.h>
/// ///
static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification"; static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification";
@interface KBAIMessageChatingVC () @interface KBAIMessageChatingVC () <KBAIChatDeleteConfirmViewDelegate, UIGestureRecognizerDelegate>
@property (nonatomic, strong) AiVM *viewModel; @property (nonatomic, strong) AiVM *viewModel;
@property (nonatomic, strong) NSMutableArray<KBChattedCompanionModel *> *chattedList; @property (nonatomic, strong) NSMutableArray<KBChattedCompanionModel *> *chattedList;
@@ -24,6 +26,16 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
@property (nonatomic, strong) UIButton *deleteButton; @property (nonatomic, strong) UIButton *deleteButton;
/// indexPath /// indexPath
@property (nonatomic, strong) NSIndexPath *longPressIndexPath; @property (nonatomic, strong) NSIndexPath *longPressIndexPath;
///
@property (nonatomic, strong) UILongPressGestureRecognizer *longPressGesture;
///
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
/// completion
@property (nonatomic, assign) NSInteger deleteButtonGeneration;
/// indexPath使
@property (nonatomic, strong) NSIndexPath *pendingDeleteIndexPath;
///
@property (nonatomic, weak) LSTPopView *deleteConfirmPopView;
@end @end
@@ -39,23 +51,53 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
[self setupLongPressGesture]; [self setupLongPressGesture];
// //
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; self.tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
tapGesture.cancelsTouchesInView = NO; // cell self.tapGesture.cancelsTouchesInView = NO; // cell
[self.tableView addGestureRecognizer:tapGesture]; self.tapGesture.delegate = self;
if (self.longPressGesture) {
[self.tapGesture requireGestureRecognizerToFail:self.longPressGesture];
}
[self.tableView addGestureRecognizer:self.tapGesture];
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// tableView tap
if (gestureRecognizer == self.tapGesture) {
if (self.deleteButton && !self.deleteButton.hidden) {
CGPoint p = [touch locationInView:self.deleteButton];
if (CGRectContainsPoint(self.deleteButton.bounds, p)) {
return NO;
}
}
}
return YES;
} }
#pragma mark - #pragma mark -
- (void)setupLongPressGesture { - (void)setupLongPressGesture {
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; self.longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
longPress.minimumPressDuration = 0.5; // 0.5 self.longPressGesture.minimumPressDuration = 0.5; // 0.5
[self.tableView addGestureRecognizer:longPress]; self.longPressGesture.delegate = self;
[self.tableView addGestureRecognizer:self.longPressGesture];
} }
- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture { - (void)handleLongPress:(UILongPressGestureRecognizer *)gesture {
CGPoint point = [gesture locationInView:self.tableView];
NSLog(@"[KBAIMessageChatingVC] longPress state=%ld point=(%.1f, %.1f)",
(long)gesture.state, point.x, point.y);
if (gesture.state == UIGestureRecognizerStateBegan) { if (gesture.state == UIGestureRecognizerStateBegan) {
CGPoint point = [gesture locationInView:self.tableView]; // tap tap
if (self.tapGesture.enabled) {
self.tapGesture.enabled = NO;
NSLog(@"[KBAIMessageChatingVC] tapGesture disabled for longPress");
}
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
NSLog(@"[KBAIMessageChatingVC] longPress began indexPath=%@",
indexPath);
if (indexPath) { if (indexPath) {
// //
@@ -64,12 +106,23 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
// showDeleteButtonAtPoint hideDeleteButton // showDeleteButtonAtPoint hideDeleteButton
self.longPressIndexPath = indexPath; self.longPressIndexPath = indexPath;
} }
} else if (gesture.state == UIGestureRecognizerStateEnded ||
gesture.state == UIGestureRecognizerStateCancelled ||
gesture.state == UIGestureRecognizerStateFailed) {
if (!self.tapGesture.enabled) {
self.tapGesture.enabled = YES;
NSLog(@"[KBAIMessageChatingVC] tapGesture re-enabled after longPress");
}
} }
} }
- (void)handleTapGesture:(UITapGestureRecognizer *)gesture { - (void)handleTapGesture:(UITapGestureRecognizer *)gesture {
// //
if (self.deleteButton && !self.deleteButton.hidden) { if (self.deleteButton && !self.deleteButton.hidden) {
CGPoint pointInView = [gesture locationInView:self.tableView];
NSLog(@"[KBAIMessageChatingVC] tap state=%ld point=(%.1f, %.1f)",
(long)gesture.state, pointInView.x, pointInView.y);
CGPoint pointInButton = [gesture locationInView:self.deleteButton]; CGPoint pointInButton = [gesture locationInView:self.deleteButton];
// //
@@ -83,8 +136,10 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
} }
- (void)showDeleteButtonAtPoint:(CGPoint)point { - (void)showDeleteButtonAtPoint:(CGPoint)point {
// // 使 completion
[self hideDeleteButton]; self.deleteButtonGeneration += 1;
NSLog(@"[KBAIMessageChatingVC] showDeleteButtonAtPoint=(%.1f, %.1f) generation=%ld",
point.x, point.y, (long)self.deleteButtonGeneration);
// //
if (!self.deleteButton) { if (!self.deleteButton) {
@@ -105,7 +160,14 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
} }
// //
[self.view addSubview:self.deleteButton]; if (self.deleteButton.superview != self.view) {
[self.view addSubview:self.deleteButton];
} else {
[self.view bringSubviewToFront:self.deleteButton];
}
//
[self.deleteButton.layer removeAllAnimations];
// //
CGSize buttonSize = CGSizeMake(110, 40); CGSize buttonSize = CGSizeMake(110, 40);
@@ -138,6 +200,9 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
}]; }];
self.deleteButton.hidden = NO; self.deleteButton.hidden = NO;
self.deleteButton.alpha = 1.0;
self.deleteButton.transform = CGAffineTransformIdentity;
NSLog(@"[KBAIMessageChatingVC] deleteButton shown");
// //
self.deleteButton.transform = CGAffineTransformMakeScale(0.3, 0.3); self.deleteButton.transform = CGAffineTransformMakeScale(0.3, 0.3);
@@ -150,10 +215,20 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
- (void)hideDeleteButton { - (void)hideDeleteButton {
if (self.deleteButton) { if (self.deleteButton) {
NSInteger generation = self.deleteButtonGeneration;
NSLog(@"[KBAIMessageChatingVC] hideDeleteButton generation=%ld", (long)generation);
//
[self.deleteButton.layer removeAllAnimations];
[UIView animateWithDuration:0.15 animations:^{ [UIView animateWithDuration:0.15 animations:^{
self.deleteButton.alpha = 0; self.deleteButton.alpha = 0;
self.deleteButton.transform = CGAffineTransformMakeScale(0.8, 0.8); self.deleteButton.transform = CGAffineTransformMakeScale(0.8, 0.8);
} completion:^(BOOL finished) { } completion:^(BOOL finished) {
//
if (generation != self.deleteButtonGeneration) {
NSLog(@"[KBAIMessageChatingVC] hide completion ignored (generation changed: %ld -> %ld)",
(long)generation, (long)self.deleteButtonGeneration);
return;
}
self.deleteButton.hidden = YES; self.deleteButton.hidden = YES;
[self.deleteButton removeFromSuperview]; [self.deleteButton removeFromSuperview];
}]; }];
@@ -166,26 +241,69 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
return; return;
} }
// indexPath // indexPath hideDeleteButton
NSIndexPath *indexPath = self.longPressIndexPath; self.pendingDeleteIndexPath = self.longPressIndexPath;
[self hideDeleteButton];
[self showDeleteConfirmPopView];
}
#pragma mark -
- (void)showDeleteConfirmPopView {
if (self.deleteConfirmPopView) {
[self.deleteConfirmPopView dismiss];
}
CGFloat width = KB_SCREEN_WIDTH - 80;
KBAIChatDeleteConfirmView *content = [[KBAIChatDeleteConfirmView alloc] initWithFrame:CGRectMake(0, 0, width, 260)];
content.delegate = self;
LSTPopView *popView = [LSTPopView initWithCustomView:content
parentView:nil
popStyle:LSTPopStyleFade
dismissStyle:LSTDismissStyleFade];
popView.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
popView.hemStyle = LSTHemStyleCenter;
popView.isClickBgDismiss = YES;
popView.isAvoidKeyboard = NO;
self.deleteConfirmPopView = popView;
[popView pop];
}
#pragma mark - KBAIChatDeleteConfirmViewDelegate
- (void)chatDeleteConfirmViewDidTapDelete:(KBAIChatDeleteConfirmView *)view {
[self.deleteConfirmPopView dismiss];
NSIndexPath *indexPath = self.pendingDeleteIndexPath;
self.pendingDeleteIndexPath = nil;
[self performDeleteAtIndexPath:indexPath];
}
- (void)chatDeleteConfirmViewDidTapCancel:(KBAIChatDeleteConfirmView *)view {
[self.deleteConfirmPopView dismiss];
self.pendingDeleteIndexPath = nil;
}
#pragma mark -
- (void)performDeleteAtIndexPath:(NSIndexPath *)indexPath {
if (!indexPath) {
return;
}
// //
if (indexPath.row >= self.chattedList.count) { if (indexPath.row >= self.chattedList.count) {
NSLog(@"[KBAIMessageChatingVC] 错误索引越界row=%ld, count=%ld", NSLog(@"[KBAIMessageChatingVC] 错误索引越界row=%ld, count=%ld",
(long)indexPath.row, (long)self.chattedList.count); (long)indexPath.row, (long)self.chattedList.count);
[self hideDeleteButton];
return; return;
} }
KBChattedCompanionModel *model = self.chattedList[indexPath.row]; KBChattedCompanionModel *model = self.chattedList[indexPath.row];
NSInteger companionId = model.companionId; NSInteger companionId = model.companionId;
NSLog(@"[KBAIMessageChatingVC] 开始删除聊天记录companionId=%ld, name=%@", NSLog(@"[KBAIMessageChatingVC] 开始删除聊天记录companionId=%ld, name=%@",
(long)companionId, model.name); (long)companionId, model.name);
//
[self hideDeleteButton];
// //
[KBHUD show]; [KBHUD show];
@@ -214,7 +332,7 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
} }
// 2. TableView // 2. TableView
[weakSelf.tableView deleteRowsAtIndexPaths:@[indexPath] [weakSelf.tableView deleteRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationLeft]; withRowAnimation:UITableViewRowAnimationLeft];
// 3. // 3.

Some files were not shown because too many files have changed in this diff Show More