Compare commits
22 Commits
822a814f85
...
dev_st
| Author | SHA1 | Date | |
|---|---|---|---|
| 750b391100 | |||
| faccf6f10f | |||
| 35b1fc0f1e | |||
| b73f225d15 | |||
| dd59094a16 | |||
| bacaf537f3 | |||
| 619d356d31 | |||
| db9f07d199 | |||
| 3ed120106e | |||
| ff4edab820 | |||
| 3e30f619b9 | |||
| 533e23ebfe | |||
| 85fb407717 | |||
| c1b50b407d | |||
| 7c7e2477cb | |||
| faae0297cb | |||
| e50eaecbd9 | |||
| 879dbb860c | |||
| b4e4b7b606 | |||
| 68a610e0a8 | |||
| 305326aa9a | |||
| 61095a379f |
22
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_close.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_close.imageset/ai_limit_close@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_close.imageset/ai_limit_close@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
22
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_goto.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_goto.imageset/ai_limit_goto@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_goto.imageset/ai_limit_goto@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
22
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_icon.imageset/ai_limit_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 358 KiB |
BIN
CustomKeyboard/KeyboardAssets.xcassets/ai_limit_icon.imageset/ai_limit_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 733 KiB |
@@ -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;
|
||||||
@@ -875,6 +878,58 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
|||||||
[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;
|
||||||
@@ -1019,9 +1074,15 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
|||||||
if (!self) return;
|
if (!self) return;
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
NSLog(@"[KB] ❌ 请求失败: %@", response.errorMessage);
|
if (response.code == 50030) {
|
||||||
|
NSLog(@"[KB] ⚠️ 次数用尽: %@", response.message);
|
||||||
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||||
[KBHUD showInfo:response.errorMessage ?: KBLocalized(@"请求失败")];
|
[self kb_showChatLimitPopWithMessage:response.message];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSLog(@"[KB] ❌ 请求失败: %@", response.message);
|
||||||
|
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||||
|
[KBHUD showInfo:response.message ?: KBLocalized(@"请求失败")];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@interface KBChatResponse : NSObject
|
@interface KBChatResponse : NSObject
|
||||||
@property (nonatomic, copy, nullable) NSString *text;
|
@property (nonatomic, copy, nullable) NSString *text;
|
||||||
@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
|
@end
|
||||||
|
|
||||||
/// 音频响应模型
|
/// 音频响应模型
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#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
|
||||||
@@ -46,7 +47,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 +67,24 @@
|
|||||||
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 (error) {
|
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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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 */; };
|
||||||
@@ -144,6 +143,7 @@
|
|||||||
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 */; };
|
||||||
|
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
|
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
|
||||||
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
|
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
|
||||||
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */; };
|
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.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>";
|
||||||
@@ -2353,6 +2389,7 @@
|
|||||||
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 */,
|
||||||
|
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */,
|
||||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
|
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
|
||||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
|
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
|
||||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */,
|
A1B2C9272FC9000100000001 /* KBChatMessageCell.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 */,
|
||||||
|
|||||||
@@ -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,6 +206,9 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
|||||||
autoPay = YES;
|
autoPay = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KBPayMainVC *vc = [[KBPayMainVC alloc] init];
|
||||||
|
vc.initialSelectedIndex = preferSvip ? 1 : 0;
|
||||||
|
if (!preferSvip) {
|
||||||
BOOL wantsPrefill = NO;
|
BOOL wantsPrefill = NO;
|
||||||
NSString *prefillFlag = params[@"prefill"];
|
NSString *prefillFlag = params[@"prefill"];
|
||||||
if ([prefillFlag respondsToSelector:@selector(boolValue)] && prefillFlag.boolValue) {
|
if ([prefillFlag respondsToSelector:@selector(boolValue)] && prefillFlag.boolValue) {
|
||||||
@@ -220,7 +226,6 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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"];
|
||||||
@@ -232,6 +237,7 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
|||||||
} 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;
|
||||||
}
|
}
|
||||||
|
|||||||
22
keyBoard/Assets.xcassets/AI/ai_limit_close.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/AI/ai_limit_close.imageset/ai_limit_close@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_limit_close.imageset/ai_limit_close@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
22
keyBoard/Assets.xcassets/AI/ai_limit_goto.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/AI/ai_limit_goto.imageset/ai_limit_goto@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_limit_goto.imageset/ai_limit_goto@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
22
keyBoard/Assets.xcassets/AI/ai_limit_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/AI/ai_limit_icon.imageset/ai_limit_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 358 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_limit_icon.imageset/ai_limit_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 733 KiB |
22
keyBoard/Assets.xcassets/AI/chat_del_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/AI/chat_del_icon.imageset/chat_del_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
keyBoard/Assets.xcassets/AI/chat_del_icon.imageset/chat_del_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 105 KiB |
22
keyBoard/Assets.xcassets/Pay/SVIP_Normal_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/SVIP_Normal_icon.imageset/SVIP_Normal_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
keyBoard/Assets.xcassets/Pay/SVIP_Normal_icon.imageset/SVIP_Normal_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
22
keyBoard/Assets.xcassets/Pay/SVIP_Selected_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/SVIP_Selected_icon.imageset/SVIP_Selected_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
keyBoard/Assets.xcassets/Pay/SVIP_Selected_icon.imageset/SVIP_Selected_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 27 KiB |
22
keyBoard/Assets.xcassets/Pay/VIP_Normal_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/VIP_Normal_icon.imageset/VIP_Normal_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
keyBoard/Assets.xcassets/Pay/VIP_Normal_icon.imageset/VIP_Normal_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
22
keyBoard/Assets.xcassets/Pay/VIP_Selected_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/VIP_Selected_icon.imageset/VIP_Selected_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
keyBoard/Assets.xcassets/Pay/VIP_Selected_icon.imageset/VIP_Selected_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 27 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_ais_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_ais_icon.imageset/pay_ai_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_ais_icon.imageset/pay_ai_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_chats_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_chats_icon.imageset/pay_chat_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_chats_icon.imageset/pay_chat_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_colorbg_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_colorbg_icon.imageset/pay_colorbg_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_colorbg_icon.imageset/pay_colorbg_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 47 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_graybg_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_graybg_icon.imageset/pay_graybg_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_graybg_icon.imageset/pay_graybg_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_history_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_history_icon.imageset/pay_history_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_history_icon.imageset/pay_history_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 22 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_keyboards_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_keyboards_icon.imageset/pay_keyboard_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_keyboards_icon.imageset/pay_keyboard_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 570 B |
BIN
keyBoard/Assets.xcassets/Pay/pay_leftline_icon.imageset/pay_leftline_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 841 B |
22
keyBoard/Assets.xcassets/Pay/pay_oks_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_oks_icon.imageset/pay_oks_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 518 B |
BIN
keyBoard/Assets.xcassets/Pay/pay_oks_icon.imageset/pay_oks_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 999 B |
22
keyBoard/Assets.xcassets/Pay/pay_person_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_person_icon.imageset/pay_person_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_person_icon.imageset/pay_person_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_phone_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_phone_icon.imageset/pay_phone_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_phone_icon.imageset/pay_phone_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 580 B |
BIN
keyBoard/Assets.xcassets/Pay/pay_rightline_icon.imageset/pay_rightline_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 846 B |
22
keyBoard/Assets.xcassets/Pay/pay_soon_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_soon_icon.imageset/pay_soon_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_soon_icon.imageset/pay_soon_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
22
keyBoard/Assets.xcassets/Pay/pay_speed_icon.imageset/Contents.json
vendored
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Pay/pay_speed_icon.imageset/pay_speed_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
keyBoard/Assets.xcassets/Pay/pay_speed_icon.imageset/pay_speed_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 32 KiB |
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,9 @@
|
|||||||
if (!_content) {
|
if (!_content) {
|
||||||
_content = @"";
|
_content = @"";
|
||||||
}
|
}
|
||||||
|
if (!_replyToUserName) {
|
||||||
|
_replyToUserName = @"";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -55,6 +55,9 @@
|
|||||||
if (!_content) {
|
if (!_content) {
|
||||||
_content = @"";
|
_content = @"";
|
||||||
}
|
}
|
||||||
|
// if ([_content isEqualToString:@"78910"]) {
|
||||||
|
// NSLog(@"===");
|
||||||
|
// }
|
||||||
if (!_replyToUserName) {
|
if (!_replyToUserName) {
|
||||||
_replyToUserName = @"";
|
_replyToUserName = @"";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
@@ -99,9 +99,15 @@
|
|||||||
|
|
||||||
- (void)sendButtonTapped {
|
- (void)sendButtonTapped {
|
||||||
NSString *text = self.textField.text;
|
NSString *text = self.textField.text;
|
||||||
if (text.length > 0 && self.onSend) {
|
if (text.length > 0) {
|
||||||
|
if (self.onSend) {
|
||||||
self.onSend(text);
|
self.onSend(text);
|
||||||
}
|
}
|
||||||
|
// 点击发送后清空输入
|
||||||
|
[self clearText];
|
||||||
|
// 发送后收起键盘
|
||||||
|
[self.textField resignFirstResponder];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)textFieldDidChange:(UITextField *)textField {
|
- (void)textFieldDidChange:(UITextField *)textField {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
27
keyBoard/Class/AiTalk/V/PopView/KBAIChatDeleteConfirmView.h
Normal 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
|
||||||
172
keyBoard/Class/AiTalk/V/PopView/KBAIChatDeleteConfirmView.m
Normal 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
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
if (gesture.state == UIGestureRecognizerStateBegan) {
|
|
||||||
CGPoint point = [gesture locationInView:self.tableView];
|
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) {
|
||||||
|
// 关键:长按期间禁用 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
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 添加到父视图(确保在最上层)
|
// 添加到父视图(确保在最上层)
|
||||||
|
if (self.deleteButton.superview != self.view) {
|
||||||
[self.view addSubview:self.deleteButton];
|
[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,14 +241,60 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,9 +304,6 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
|
|||||||
NSLog(@"[KBAIMessageChatingVC] 开始删除聊天记录:companionId=%ld, name=%@",
|
NSLog(@"[KBAIMessageChatingVC] 开始删除聊天记录:companionId=%ld, name=%@",
|
||||||
(long)companionId, model.name);
|
(long)companionId, model.name);
|
||||||
|
|
||||||
// 隐藏删除按钮
|
|
||||||
[self hideDeleteButton];
|
|
||||||
|
|
||||||
// 显示加载提示
|
// 显示加载提示
|
||||||
[KBHUD show];
|
[KBHUD show];
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#import "KBAiRecordButton.h"
|
#import "KBAiRecordButton.h"
|
||||||
#import "KBHUD.h"
|
#import "KBHUD.h"
|
||||||
#import "KBChatLimitPopView.h"
|
#import "KBChatLimitPopView.h"
|
||||||
#import "KBVipPay.h"
|
#import "KBPayMainVC.h"
|
||||||
#import "LSTPopView.h"
|
#import "LSTPopView.h"
|
||||||
#import "VoiceChatStreamingManager.h"
|
#import "VoiceChatStreamingManager.h"
|
||||||
#import "KBUserSessionManager.h"
|
#import "KBUserSessionManager.h"
|
||||||
@@ -430,9 +430,10 @@
|
|||||||
[self.limitPopView dismiss];
|
[self.limitPopView dismiss];
|
||||||
}
|
}
|
||||||
|
|
||||||
CGFloat width = KB_SCREEN_WIDTH - 60;
|
CGFloat width = 252.0;
|
||||||
|
CGFloat height = 252.0 + 18.0 + 53.0 + 18.0 + 28.0;
|
||||||
KBChatLimitPopView *content =
|
KBChatLimitPopView *content =
|
||||||
[[KBChatLimitPopView alloc] initWithFrame:CGRectMake(0, 0, width, 180)];
|
[[KBChatLimitPopView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
|
||||||
content.message = message;
|
content.message = message;
|
||||||
content.delegate = self;
|
content.delegate = self;
|
||||||
|
|
||||||
@@ -461,7 +462,8 @@
|
|||||||
[[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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,12 @@ typedef void (^AiVMSpeechTranscribeCompletion)(KBAiSpeechTranscribeResponse *_Nu
|
|||||||
pageSize:(NSInteger)pageSize
|
pageSize:(NSInteger)pageSize
|
||||||
completion:(void(^)(KBChatHistoryPageModel * _Nullable pageModel, NSError * _Nullable error))completion;
|
completion:(void(^)(KBChatHistoryPageModel * _Nullable pageModel, NSError * _Nullable error))completion;
|
||||||
|
|
||||||
|
/// 删除聊天记录(根据聊天记录 ID 逻辑删除聊天消息)
|
||||||
|
/// @param historyId 聊天记录 ID(接口字段为 id)
|
||||||
|
/// @param completion 完成回调
|
||||||
|
- (void)deleteChatHistoryWithId:(NSInteger)historyId
|
||||||
|
completion:(void(^)(BOOL success, NSError * _Nullable error))completion;
|
||||||
|
|
||||||
#pragma mark - 评论相关接口
|
#pragma mark - 评论相关接口
|
||||||
|
|
||||||
/// 发表评论
|
/// 发表评论
|
||||||
|
|||||||