Compare commits
30 Commits
fa9af5ff1b
...
dev_st
| Author | SHA1 | Date | |
|---|---|---|---|
| 3cb02d5b76 | |||
| 750b391100 | |||
| faccf6f10f | |||
| 35b1fc0f1e | |||
| b73f225d15 | |||
| dd59094a16 | |||
| bacaf537f3 | |||
| 619d356d31 | |||
| db9f07d199 | |||
| 3ed120106e | |||
| ff4edab820 | |||
| 3e30f619b9 | |||
| 533e23ebfe | |||
| 85fb407717 | |||
| c1b50b407d | |||
| 7c7e2477cb | |||
| faae0297cb | |||
| e50eaecbd9 | |||
| 879dbb860c | |||
| b4e4b7b606 | |||
| 68a610e0a8 | |||
| 305326aa9a | |||
| 61095a379f | |||
| 822a814f85 | |||
| 0bd0392191 | |||
| b9663037f5 | |||
| a0923c8572 | |||
| d482cfcb7d | |||
| 9e6d2906f8 | |||
| 6f7bb4f960 |
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 "KBChatMessage.h"
|
||||
#import "KBChatPanelView.h"
|
||||
#import "KBChatLimitPopView.h"
|
||||
#import "KBSkinInstallBridge.h"
|
||||
#import "KBSkinManager.h"
|
||||
#import "KBSuggestionEngine.h"
|
||||
@@ -66,7 +67,8 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
@interface KeyboardViewController () <KBKeyBoardMainViewDelegate,
|
||||
KBFunctionViewDelegate,
|
||||
KBKeyboardSubscriptionViewDelegate,
|
||||
KBChatPanelViewDelegate>
|
||||
KBChatPanelViewDelegate,
|
||||
KBChatLimitPopViewDelegate>
|
||||
@property(nonatomic, strong)
|
||||
UIButton *nextKeyboardButton; // 系统“下一个键盘”按钮(可选)
|
||||
@property(nonatomic, strong) UIView *contentView;
|
||||
@@ -78,12 +80,14 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
@property(nonatomic, strong) UIImageView *bgImageView; // 背景图(在底层)
|
||||
@property(nonatomic, strong) UIImageView *personaAvatarImageView; // 语音模式下显示的 persona 小头像
|
||||
@property(nonatomic, strong) UIImageView *personaGrayImageView; // 语音模式下显示的 persona 小头像
|
||||
@property(nonatomic, strong) UIVisualEffectView *personaBlurView; // 语音模式下头像高斯模糊层
|
||||
|
||||
@property(nonatomic, strong) KBChatPanelView *chatPanelView;
|
||||
@property(nonatomic, strong) KBKeyboardSubscriptionView *subscriptionView;
|
||||
@property(nonatomic, strong) KBSuggestionEngine *suggestionEngine;
|
||||
@property(nonatomic, copy) NSString *currentWord;
|
||||
@property(nonatomic, assign) BOOL suppressSuggestions;
|
||||
@property(nonatomic, strong) UIControl *chatLimitMaskView;
|
||||
@property(nonatomic, strong) MASConstraint *contentWidthConstraint;
|
||||
@property(nonatomic, strong) MASConstraint *contentHeightConstraint;
|
||||
@property(nonatomic, strong) MASConstraint *keyBoardMainHeightConstraint;
|
||||
@@ -866,14 +870,66 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
[KBHUD showInfo:KBLocalized(@"请开启完全访问后使用")];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 添加 loading 消息
|
||||
[self.chatPanelView kb_addLoadingAssistantMessage];
|
||||
|
||||
|
||||
// 调用新的聊天接口
|
||||
[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 {
|
||||
if (text.length == 0) {
|
||||
return;
|
||||
@@ -1017,16 +1073,22 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) return;
|
||||
|
||||
if (!response.success) {
|
||||
NSLog(@"[KB] ❌ 请求失败: %@", response.errorMessage);
|
||||
if (response.code != 0) {
|
||||
if (response.code == 50030) {
|
||||
NSLog(@"[KB] ⚠️ 次数用尽: %@", response.message);
|
||||
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||
[self kb_showChatLimitPopWithMessage:response.message];
|
||||
return;
|
||||
}
|
||||
NSLog(@"[KB] ❌ 请求失败: %@", response.message);
|
||||
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||
[KBHUD showInfo:response.errorMessage ?: KBLocalized(@"请求失败")];
|
||||
[KBHUD showInfo:response.message ?: KBLocalized(@"请求失败")];
|
||||
return;
|
||||
}
|
||||
|
||||
NSLog(@"[KB] ✅ 收到回复: %@", response.text);
|
||||
NSLog(@"[KB] ✅ 收到回复: %@", response.data.aiResponse);
|
||||
|
||||
if (response.text.length == 0) {
|
||||
if (response.data.aiResponse.length == 0) {
|
||||
[self.chatPanelView kb_removeLoadingAssistantMessage];
|
||||
[KBHUD showInfo:KBLocalized(@"未获取到回复内容")];
|
||||
return;
|
||||
@@ -1034,12 +1096,12 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
|
||||
// 添加 AI 消息(带打字机效果)
|
||||
NSLog(@"[KB] 准备添加 AI 消息");
|
||||
[self.chatPanelView kb_addAssistantMessage:response.text audioId:response.audioId];
|
||||
[self.chatPanelView kb_addAssistantMessage:response.data.aiResponse audioId:response.data.audioId];
|
||||
NSLog(@"[KB] AI 消息添加完成");
|
||||
|
||||
// 如果有 audioId,开始预加载音频
|
||||
if (response.audioId.length > 0) {
|
||||
[self kb_preloadAudioWithAudioId:response.audioId];
|
||||
if (response.data.audioId.length > 0) {
|
||||
[self kb_preloadAudioWithAudioId:response.data.audioId];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -1351,6 +1413,25 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
[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
|
||||
- (KBKeyBoardMainView *)keyBoardMainView {
|
||||
if (!_keyBoardMainView) {
|
||||
@@ -1407,6 +1488,10 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
_personaAvatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_personaAvatarImageView.clipsToBounds = YES;
|
||||
_personaAvatarImageView.hidden = YES;
|
||||
[_personaAvatarImageView addSubview:self.personaBlurView];
|
||||
[self.personaBlurView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(_personaAvatarImageView);
|
||||
}];
|
||||
}
|
||||
return _personaAvatarImageView;
|
||||
}
|
||||
@@ -1419,6 +1504,16 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
return _personaGrayImageView;
|
||||
}
|
||||
|
||||
- (UIVisualEffectView *)personaBlurView {
|
||||
if (!_personaBlurView) {
|
||||
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
|
||||
_personaBlurView = [[UIVisualEffectView alloc] initWithEffect:effect];
|
||||
_personaBlurView.hidden = YES;
|
||||
_personaBlurView.userInteractionEnabled = NO;
|
||||
}
|
||||
return _personaBlurView;
|
||||
}
|
||||
|
||||
#pragma mark - Persona Avatar
|
||||
|
||||
/// 从 AppGroup 读取选中的 persona 信息
|
||||
@@ -1475,6 +1570,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
if (image) {
|
||||
self.personaAvatarImageView.image = image;
|
||||
self.personaAvatarImageView.hidden = NO;
|
||||
self.personaBlurView.hidden = NO;
|
||||
NSLog(@"[Keyboard] persona 封面图加载成功");
|
||||
} else {
|
||||
NSLog(@"[Keyboard] persona 封面图加载失败");
|
||||
@@ -1485,6 +1581,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
||||
- (void)kb_hidePersonaAvatar {
|
||||
self.personaAvatarImageView.hidden = YES;
|
||||
self.personaAvatarImageView.image = nil;
|
||||
self.personaBlurView.hidden = YES;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
@@ -7,15 +7,25 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class KBChatDataModel;
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// 聊天响应模型
|
||||
@interface KBChatResponse : NSObject
|
||||
@property (nonatomic, copy, nullable) NSString *text;
|
||||
@property (nonatomic, copy, nullable) NSString *audioId;
|
||||
@property (nonatomic, copy, nullable) NSString *errorMessage;
|
||||
@property (nonatomic, strong, nullable) KBChatDataModel *data;
|
||||
//@property (nonatomic, copy, nullable) NSString *audioId;
|
||||
@property (nonatomic, copy, nullable) NSString *message;
|
||||
@property (nonatomic, assign) BOOL success;
|
||||
@property (nonatomic, assign) NSInteger code;
|
||||
|
||||
@end
|
||||
|
||||
@interface KBChatDataModel : NSObject
|
||||
@property (nonatomic, copy, nullable) NSString *aiResponse;
|
||||
@property (nonatomic, copy, nullable) NSString *audioId;
|
||||
@property (nonatomic, copy, nullable) NSString *llmDuration;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
/// 音频响应模型
|
||||
|
||||
@@ -7,10 +7,14 @@
|
||||
#import "KBNetworkManager.h"
|
||||
#import "KBConfig.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <MJExtension/MJExtension.h>
|
||||
|
||||
@implementation KBChatResponse
|
||||
@end
|
||||
|
||||
@implementation KBChatDataModel
|
||||
@end
|
||||
|
||||
@implementation KBAudioResponse
|
||||
@end
|
||||
|
||||
@@ -46,7 +50,7 @@
|
||||
if (completion) {
|
||||
KBChatResponse *response = [[KBChatResponse alloc] init];
|
||||
response.success = NO;
|
||||
response.errorMessage = @"内容为空";
|
||||
response.message = @"内容为空";
|
||||
completion(response);
|
||||
}
|
||||
return;
|
||||
@@ -66,24 +70,23 @@
|
||||
headers:nil
|
||||
completion:^(NSDictionary *json, NSURLResponse *response, NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
KBChatResponse *chatResponse = [[KBChatResponse alloc] init];
|
||||
|
||||
if (error) {
|
||||
KBChatResponse *chatResponse = [KBChatResponse mj_objectWithKeyValues:json];
|
||||
if (chatResponse.code != 0) {
|
||||
chatResponse.success = NO;
|
||||
chatResponse.errorMessage = error.localizedDescription ?: @"请求失败";
|
||||
// chatResponse.errorMessage = error.localizedDescription ?: @"请求失败";
|
||||
if (completion) completion(chatResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析文本
|
||||
chatResponse.text = [self p_parseTextFromJSON:json];
|
||||
// 解析 audioId
|
||||
chatResponse.audioId = [self p_parseAudioIdFromJSON:json];
|
||||
// // 解析文本
|
||||
// chatResponse.text = [self p_parseTextFromJSON:json];
|
||||
// // 解析 audioId
|
||||
// chatResponse.audioId = [self p_parseAudioIdFromJSON:json];
|
||||
|
||||
chatResponse.success = (chatResponse.text.length > 0);
|
||||
if (!chatResponse.success) {
|
||||
chatResponse.errorMessage = @"未获取到回复内容";
|
||||
}
|
||||
// chatResponse.success = (chatResponse.text.length > 0);
|
||||
// if (!chatResponse.success) {
|
||||
// chatResponse.errorMessage = @"未获取到回复内容";
|
||||
// }
|
||||
|
||||
if (completion) completion(chatResponse);
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@property (nonatomic, weak, nullable) id<KBToolBarDelegate> delegate;
|
||||
|
||||
/// 左侧按钮的标题(数量由数组决定)。默认值:@[@"AI", @"语音"]。
|
||||
/// 左侧按钮的标题(数量由数组决定)。默认值:@[@"AI"]。
|
||||
@property (nonatomic, copy) NSArray<NSString *> *leftButtonTitles;
|
||||
|
||||
/// 暴露按钮以便外部定制(只读;首次访问时懒加载创建)
|
||||
|
||||
@@ -15,23 +15,25 @@
|
||||
@property (nonatomic, strong) NSArray<UIButton *> *leftButtonsInternal;
|
||||
//@property (nonatomic, strong) UIButton *settingsButtonInternal;
|
||||
@property (nonatomic, strong) UIButton *globeButtonInternal; // 可选:系统“切换输入法”键
|
||||
@property (nonatomic, strong) UIImageView *avatarImageView; // 右侧头像(AppGroup persona_cover.jpg)
|
||||
@property (nonatomic, strong) UIButton *undoButtonInternal; // 右侧撤销删除
|
||||
@property (nonatomic, assign) BOOL kbNeedsInputModeSwitchKey;
|
||||
@property (nonatomic, assign) BOOL kbUndoVisible;
|
||||
@property (nonatomic, assign) BOOL kbAvatarVisible;
|
||||
@end
|
||||
|
||||
@implementation KBToolBar
|
||||
|
||||
static NSString * const kKBAIKeyIdentifier = @"ai";
|
||||
static NSString * const kKBUndoKeyIdentifier = @"key_revoke";
|
||||
static const CGFloat kKBAIButtonWidth = 40;
|
||||
static const CGFloat kKBAIButtonHeight = 40;
|
||||
static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
static NSString * const kKBAIKeyIdentifier = @"ai";
|
||||
static NSString * const kKBUndoKeyIdentifier = @"key_revoke";
|
||||
static const CGFloat kKBAIButtonWidth = 40;
|
||||
static const CGFloat kKBAIButtonHeight = 40;
|
||||
static const CGFloat kKBAvatarSize = 40;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
_leftButtonTitles = @[@"AI", KBLocalized(@"语音")]; // 默认标题
|
||||
_leftButtonTitles = @[@"AI"]; // 默认标题
|
||||
[self setupUI];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(kb_undoStateChanged)
|
||||
@@ -69,7 +71,6 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
}
|
||||
}];
|
||||
[self kb_updateAIButtonAppearance];
|
||||
[self kb_updateVoiceButtonAppearance];
|
||||
}
|
||||
|
||||
#pragma mark - 视图搭建
|
||||
@@ -79,6 +80,7 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
// [self addSubview:self.settingsButtonInternal];
|
||||
[self addSubview:self.globeButtonInternal];
|
||||
[self addSubview:self.undoButtonInternal];
|
||||
[self addSubview:self.avatarImageView];
|
||||
|
||||
// 右侧设置按钮
|
||||
// [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
@@ -94,13 +96,7 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
make.width.height.mas_equalTo(32);
|
||||
}];
|
||||
|
||||
// 右侧撤销按钮
|
||||
[self.undoButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.equalTo(self.mas_right).offset(-12);
|
||||
make.centerY.equalTo(self.mas_centerY);
|
||||
make.height.mas_equalTo(32);
|
||||
make.width.mas_equalTo(84);
|
||||
}];
|
||||
[self kb_updateRightControlsConstraints];
|
||||
|
||||
[self kb_updateLeftContainerConstraints];
|
||||
|
||||
@@ -173,8 +169,8 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
|
||||
- (void)kb_applyTheme {
|
||||
[self kb_updateAIButtonAppearance];
|
||||
[self kb_updateVoiceButtonAppearance];
|
||||
[self kb_updateUndoButtonAppearance];
|
||||
[self kb_updateAvatarAppearance];
|
||||
}
|
||||
|
||||
- (void)kb_updateAIButtonAppearance {
|
||||
@@ -211,16 +207,6 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_updateVoiceButtonAppearance {
|
||||
UIButton *voiceButton = [self kb_voiceButton];
|
||||
if (!voiceButton) { return; }
|
||||
|
||||
voiceButton.backgroundColor = [UIColor colorWithHex:0xE53935];
|
||||
[voiceButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||
voiceButton.layer.cornerRadius = 16;
|
||||
voiceButton.layer.masksToBounds = YES;
|
||||
}
|
||||
|
||||
- (void)kb_updateUndoButtonAppearance {
|
||||
if (!self.undoButtonInternal) { return; }
|
||||
|
||||
@@ -241,6 +227,41 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Avatar
|
||||
|
||||
- (void)kb_updateAvatarAppearance {
|
||||
UIImage *img = [self kb_personaCoverImageFromAppGroup];
|
||||
BOOL shouldShow = (img != nil);
|
||||
self.avatarImageView.image = img;
|
||||
if (self.kbAvatarVisible == shouldShow) {
|
||||
self.avatarImageView.hidden = !shouldShow;
|
||||
return;
|
||||
}
|
||||
self.kbAvatarVisible = shouldShow;
|
||||
self.avatarImageView.hidden = !shouldShow;
|
||||
[self kb_updateRightControlsConstraints];
|
||||
[self kb_updateLeftContainerConstraints];
|
||||
[self setNeedsLayout];
|
||||
[self layoutIfNeeded];
|
||||
}
|
||||
|
||||
- (nullable UIImage *)kb_personaCoverImageFromAppGroup {
|
||||
NSURL *containerURL = [[NSFileManager defaultManager]
|
||||
containerURLForSecurityApplicationGroupIdentifier:AppGroup];
|
||||
if (!containerURL) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *imagePath =
|
||||
[[containerURL path] stringByAppendingPathComponent:@"persona_cover.jpg"];
|
||||
if (imagePath.length == 0 ||
|
||||
![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [UIImage imageWithContentsOfFile:imagePath];
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)onLeftAction:(UIButton *)sender {
|
||||
@@ -261,6 +282,16 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onAvatarTap {
|
||||
if (!self.kbAvatarVisible || self.avatarImageView.hidden) {
|
||||
return;
|
||||
}
|
||||
// 复用原“语音”入口的 index=1 逻辑(外部会按 index 做面板切换)
|
||||
if ([self.delegate respondsToSelector:@selector(toolBar:didTapActionAtIndex:)]) {
|
||||
[self.delegate toolBar:self didTapActionAtIndex:1];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIView *)leftContainer {
|
||||
@@ -271,6 +302,23 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
return _leftContainer;
|
||||
}
|
||||
|
||||
- (UIImageView *)avatarImageView {
|
||||
if (!_avatarImageView) {
|
||||
_avatarImageView = [[UIImageView alloc] init];
|
||||
_avatarImageView.hidden = YES;
|
||||
_avatarImageView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
|
||||
_avatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_avatarImageView.layer.cornerRadius = kKBAvatarSize * 0.5;
|
||||
_avatarImageView.layer.masksToBounds = YES;
|
||||
_avatarImageView.userInteractionEnabled = YES;
|
||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
|
||||
initWithTarget:self
|
||||
action:@selector(onAvatarTap)];
|
||||
[_avatarImageView addGestureRecognizer:tap];
|
||||
}
|
||||
return _avatarImageView;
|
||||
}
|
||||
|
||||
//- (UIButton *)settingsButtonInternal {
|
||||
// if (!_settingsButtonInternal) {
|
||||
// _settingsButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
@@ -319,11 +367,6 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
return self.leftButtonsInternal[0];
|
||||
}
|
||||
|
||||
- (UIButton *)kb_voiceButton {
|
||||
if (self.leftButtonsInternal.count <= kKBVoiceButtonIndex) { return nil; }
|
||||
return self.leftButtonsInternal[kKBVoiceButtonIndex];
|
||||
}
|
||||
|
||||
#pragma mark - Globe (Input Mode Switch)
|
||||
|
||||
// 根据宿主是否已提供系统切换键,决定是否显示地球按钮;并绑定系统事件。
|
||||
@@ -362,6 +405,8 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
}
|
||||
if (self.kbUndoVisible) {
|
||||
make.right.equalTo(self.undoButtonInternal.mas_left).offset(-8);
|
||||
} else if (self.kbAvatarVisible) {
|
||||
make.right.equalTo(self.avatarImageView.mas_left).offset(-8);
|
||||
} else {
|
||||
make.right.equalTo(self).offset(-12);
|
||||
}
|
||||
@@ -371,6 +416,24 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)kb_updateRightControlsConstraints {
|
||||
[self.avatarImageView mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.equalTo(self).offset(-12);
|
||||
make.centerY.equalTo(self).offset(5);
|
||||
make.width.height.mas_equalTo(kKBAvatarSize);
|
||||
}];
|
||||
[self.undoButtonInternal mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
if (self.kbAvatarVisible) {
|
||||
make.right.equalTo(self.avatarImageView.mas_left).offset(-8);
|
||||
} else {
|
||||
make.right.equalTo(self).offset(-12);
|
||||
}
|
||||
make.centerY.equalTo(self.mas_centerY);
|
||||
make.height.mas_equalTo(32);
|
||||
make.width.mas_equalTo(84);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)kb_undoStateChanged {
|
||||
[self kb_updateUndoVisibilityAnimated:YES];
|
||||
}
|
||||
@@ -405,6 +468,7 @@ static const NSInteger kKBVoiceButtonIndex = 1;
|
||||
- (void)didMoveToWindow {
|
||||
[super didMoveToWindow];
|
||||
[self kb_refreshGlobeVisibility];
|
||||
[self kb_updateAvatarAppearance];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -20,6 +20,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
|
||||
secret:(NSString *)secret;
|
||||
|
||||
/// 获取签名原始拼接字符串(HMAC 前的明文)
|
||||
+ (NSString *)signSourceStringWithParams:(NSDictionary<NSString *, NSString *> *)params
|
||||
secret:(NSString *)secret;
|
||||
|
||||
/// 秒级时间戳(字符串)
|
||||
+ (NSString *)currentTimestamp;
|
||||
|
||||
@@ -29,4 +33,3 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
||||
@@ -12,10 +12,16 @@
|
||||
|
||||
+ (NSString *)urlEncode:(NSString *)value {
|
||||
if (!value) return @"";
|
||||
// 和 Swift 里的 .urlQueryAllowed 类似
|
||||
NSCharacterSet *allowed = [NSCharacterSet URLQueryAllowedCharacterSet];
|
||||
// 按 application/x-www-form-urlencoded 规则编码(更贴近后端常见实现)
|
||||
NSMutableCharacterSet *allowed = [NSMutableCharacterSet alphanumericCharacterSet];
|
||||
[allowed addCharactersInString:@"-._*"];
|
||||
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 {
|
||||
@@ -41,6 +47,12 @@
|
||||
|
||||
+ (NSString *)signWithParams:(NSDictionary<NSString *, NSString *> *)params
|
||||
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 自身
|
||||
NSMutableDictionary<NSString *, NSString *> *filtered = [NSMutableDictionary dictionary];
|
||||
@@ -62,15 +74,11 @@
|
||||
[components addObject:part];
|
||||
}
|
||||
|
||||
NSString *encodedSecret = [self urlEncode:secret];
|
||||
NSString *encodedSecret = [self urlEncode:secret ?: @""];
|
||||
NSString *secretPart = [NSString stringWithFormat:@"secret=%@", encodedSecret];
|
||||
[components addObject:secretPart];
|
||||
|
||||
NSString *dataString = [components componentsJoinedByString:@"&"];
|
||||
|
||||
// 4. HMAC-SHA256
|
||||
NSString *sign = [self hmacSHA256:dataString secret:secret];
|
||||
return sign;
|
||||
return [components componentsJoinedByString:@"&"];
|
||||
}
|
||||
|
||||
+ (NSString *)currentTimestamp {
|
||||
@@ -89,4 +97,3 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
0459D1B72EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; };
|
||||
0459D1B82EBA287900F2D189 /* KBSkinManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0459D1B62EBA287900F2D189 /* KBSkinManager.m */; };
|
||||
0460866B2F18D75500757C95 /* ai_test.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 0460866A2F18D75500757C95 /* ai_test.m4a */; };
|
||||
046086732F191B6900757C95 /* KBAiMainVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086722F191B6900757C95 /* KBAiMainVC.m */; };
|
||||
046086752F191CC700757C95 /* AI技术分析.txt in Resources */ = {isa = PBXBuildFile; fileRef = 046086742F191CC700757C95 /* AI技术分析.txt */; };
|
||||
0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086992F19238500757C95 /* KBAiWaveformView.m */; };
|
||||
0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 046086972F19238500757C95 /* KBAiRecordButton.m */; };
|
||||
@@ -141,13 +140,14 @@
|
||||
048FFD112F27432D005D62AE /* KBPersonaPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD0F2F27432D005D62AE /* KBPersonaPageModel.m */; };
|
||||
048FFD142F274342005D62AE /* KBPersonaChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD132F274342005D62AE /* KBPersonaChatCell.m */; };
|
||||
048FFD182F2763A5005D62AE /* KBVoiceInputBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD172F2763A5005D62AE /* KBVoiceInputBar.m */; };
|
||||
048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */; };
|
||||
048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */; };
|
||||
048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
|
||||
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
|
||||
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */; };
|
||||
048FFD302F29F3C3005D62AE /* KBAIMessageZanVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.m */; };
|
||||
048FFD1D2F277486005D62AE /* KBChatHistoryPageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1C2F277486005D62AE /* KBChatHistoryPageModel.m */; };
|
||||
048FFD1E2F277486005D62AE /* KBChatHistoryModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD1A2F277486005D62AE /* KBChatHistoryModel.m */; };
|
||||
048FFD242F28A836005D62AE /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD232F28A836005D62AE /* KBChatLimitPopView.m */; };
|
||||
048FFD272F28C6CF005D62AE /* KBImagePositionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD262F28C6CF005D62AE /* KBImagePositionButton.m */; };
|
||||
048FFD2A2F28E99A005D62AE /* KBCommentModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD292F28E99A005D62AE /* KBCommentModel.m */; };
|
||||
048FFD2D2F29F356005D62AE /* KBAIMessageVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2C2F29F356005D62AE /* KBAIMessageVC.m */; };
|
||||
048FFD302F29F3C3005D62AE /* KBAIMessageZanVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD2F2F29F3C3005D62AE /* KBAIMessageZanVC.m */; };
|
||||
048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD322F29F3D2005D62AE /* KBAIMessageChatingVC.m */; };
|
||||
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; };
|
||||
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.m */; };
|
||||
@@ -238,6 +238,14 @@
|
||||
04E0B2022F300002002CA5A0 /* KBVoiceRecordManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04E0B2012F300002002CA5A0 /* KBVoiceRecordManager.m */; };
|
||||
04E161832F10E6470022C23B /* normal_hei_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161812F10E6470022C23B /* normal_hei_them.zip */; };
|
||||
04E161842F10E6470022C23B /* normal_them.zip in Resources */ = {isa = PBXBuildFile; fileRef = 04E161822F10E6470022C23B /* normal_them.zip */; };
|
||||
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 */; };
|
||||
04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95692EB05497007BD342 /* KBKeyButton.m */; };
|
||||
04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; };
|
||||
@@ -271,6 +279,8 @@
|
||||
04FEDC422F00040000999999 /* KBKeyboardSubscriptionFeatureMarqueeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FEDC412F00040000999999 /* KBKeyboardSubscriptionFeatureMarqueeView.m */; };
|
||||
05A1B2D12F5B1A2B3C4D5E60 /* KBSearchVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 05A1B2C52F5B1A2B3C4D5E60 /* KBSearchVM.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 */; };
|
||||
49B63DBAEE9076C591E13D68 /* KBShopThemeTagModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A844CD2D8584596DBE6316 /* KBShopThemeTagModel.m */; };
|
||||
550CB2630FA4A7B4B9782EFA /* KBMyTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 180D662EC4DB3A7FFF83FF18 /* KBMyTheme.m */; };
|
||||
@@ -394,8 +404,6 @@
|
||||
0459D1B52EBA287900F2D189 /* KBSkinManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinManager.h; sourceTree = "<group>"; };
|
||||
0459D1B62EBA287900F2D189 /* KBSkinManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinManager.m; sourceTree = "<group>"; };
|
||||
0460866A2F18D75500757C95 /* ai_test.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = ai_test.m4a; sourceTree = "<group>"; };
|
||||
046086712F191B6900757C95 /* KBAiMainVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAiMainVC.h; sourceTree = "<group>"; };
|
||||
046086722F191B6900757C95 /* KBAiMainVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAiMainVC.m; sourceTree = "<group>"; };
|
||||
046086742F191CC700757C95 /* AI技术分析.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "AI技术分析.txt"; sourceTree = "<group>"; };
|
||||
046086962F19238500757C95 /* KBAiRecordButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAiRecordButton.h; sourceTree = "<group>"; };
|
||||
046086972F19238500757C95 /* KBAiRecordButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAiRecordButton.m; sourceTree = "<group>"; };
|
||||
@@ -728,6 +736,22 @@
|
||||
04E0B2012F300002002CA5A0 /* KBVoiceRecordManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBVoiceRecordManager.m; sourceTree = "<group>"; };
|
||||
04E161812F10E6470022C23B /* normal_hei_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_hei_them.zip; sourceTree = "<group>"; };
|
||||
04E161822F10E6470022C23B /* normal_them.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = normal_them.zip; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@@ -797,6 +821,10 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@@ -951,6 +979,16 @@
|
||||
04122FAF2EC73C0100EF7AB3 /* KBVipReviewItemCell.m */,
|
||||
04122FB12EC73C0100EF7AB3 /* KBVipReviewListCell.h */,
|
||||
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;
|
||||
sourceTree = "<group>";
|
||||
@@ -962,6 +1000,10 @@
|
||||
04122F802EC5FC6F00EF7AB3 /* KBJfPay.m */,
|
||||
04122F8F2EC73AF700EF7AB3 /* KBVipPay.h */,
|
||||
04122F902EC73AF700EF7AB3 /* KBVipPay.m */,
|
||||
04F4C0A82F32274000E8F08C /* KBPayMainVC.h */,
|
||||
04F4C0A92F32274000E8F08C /* KBPayMainVC.m */,
|
||||
04F4C0AB2F32288600E8F08C /* KBPaySvipVC.h */,
|
||||
04F4C0AC2F32288600E8F08C /* KBPaySvipVC.m */,
|
||||
);
|
||||
path = VC;
|
||||
sourceTree = "<group>";
|
||||
@@ -1114,8 +1156,6 @@
|
||||
0460866E2F191A5100757C95 /* VC */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
046086712F191B6900757C95 /* KBAiMainVC.h */,
|
||||
046086722F191B6900757C95 /* KBAiMainVC.m */,
|
||||
048FFD092F273BFC005D62AE /* KBAIHomeVC.h */,
|
||||
048FFD0A2F273BFC005D62AE /* KBAIHomeVC.m */,
|
||||
048FFD2B2F29F356005D62AE /* KBAIMessageVC.h */,
|
||||
@@ -1431,6 +1471,8 @@
|
||||
04E039452F236E75002CA5A0 /* KBChatTableView.m */,
|
||||
04E039492F236E75002CA5A0 /* KBChatUserMessageCell.h */,
|
||||
04E0394A2F236E75002CA5A0 /* KBChatUserMessageCell.m */,
|
||||
0F2A10012F3C0001002CA5A0 /* KBChatMessageActionPopView.h */,
|
||||
0F2A10022F3C0001002CA5A0 /* KBChatMessageActionPopView.m */,
|
||||
04E039422F236E75002CA5A0 /* KBChatAssistantMessageCell.h */,
|
||||
04E039432F236E75002CA5A0 /* KBChatAssistantMessageCell.m */,
|
||||
04E039472F236E75002CA5A0 /* KBChatTimeCell.h */,
|
||||
@@ -1444,6 +1486,10 @@
|
||||
children = (
|
||||
048FFD222F28A836005D62AE /* KBChatLimitPopView.h */,
|
||||
048FFD232F28A836005D62AE /* KBChatLimitPopView.m */,
|
||||
0F2A10112F3C0002002CA5A0 /* KBAIPersonaSidebarView.h */,
|
||||
0F2A10122F3C0002002CA5A0 /* KBAIPersonaSidebarView.m */,
|
||||
04F4C0BD2F33369900E8F08C /* KBAIChatDeleteConfirmView.h */,
|
||||
04F4C0BE2F33369900E8F08C /* KBAIChatDeleteConfirmView.m */,
|
||||
);
|
||||
path = PopView;
|
||||
sourceTree = "<group>";
|
||||
@@ -2340,14 +2386,15 @@
|
||||
0498BD862EE1BEC9006CC1D5 /* KBSignUtils.m in Sources */,
|
||||
04791FFC2ED71D17004E8522 /* UIColor+Extension.m in Sources */,
|
||||
0450AC4A2EF2C3ED00B6AF06 /* KBKeyboardSubscriptionOptionCell.m in Sources */,
|
||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */,
|
||||
048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */,
|
||||
048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */,
|
||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
|
||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
|
||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */,
|
||||
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */,
|
||||
A1B2C3EB2F20000000000001 /* KBSuggestionBarView.m in Sources */,
|
||||
04A9FE0F2EB481100020DB6D /* KBHUD.m in Sources */,
|
||||
048FFD562F2B9C3D005D62AE /* KBChatAssistantCell.m in Sources */,
|
||||
048FFD572F2B9C3D005D62AE /* KBChatUserCell.m in Sources */,
|
||||
A1B2C9302FCA000100000001 /* KBChatLimitPopView.m in Sources */,
|
||||
04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */,
|
||||
A1B2C9262FC9000100000001 /* KBChatMessage.m in Sources */,
|
||||
A1B2C9272FC9000100000001 /* KBChatMessageCell.m in Sources */,
|
||||
A1B2C9282FC9000100000001 /* KBChatPanelView.m in Sources */,
|
||||
A1B2C3EB2F20000000000001 /* KBSuggestionBarView.m in Sources */,
|
||||
0419C9662F2C7693002E86D3 /* KBVM.m in Sources */,
|
||||
048FFD512F2B68F7005D62AE /* KBPersonaModel.m in Sources */,
|
||||
04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */,
|
||||
@@ -2408,11 +2455,14 @@
|
||||
04122F622EC5F41D00EF7AB3 /* KBUser.m in Sources */,
|
||||
04122F8B2EC6F7C800EF7AB3 /* IAPVerifyTransactionObj.m in Sources */,
|
||||
04B5A1A22EEFA12300AAAAAA /* KBPayProductModel.m in Sources */,
|
||||
04F4C0AD2F32288600E8F08C /* KBPaySvipVC.m in Sources */,
|
||||
046086D62F1A093400757C95 /* KBAICommentInputView.m in Sources */,
|
||||
046086D72F1A093400757C95 /* KBAICommentFooterView.m in Sources */,
|
||||
046086D82F1A093400757C95 /* KBAIReplyCell.m in Sources */,
|
||||
046086D92F1A093400757C95 /* KBAICommentHeaderView.m in Sources */,
|
||||
04E0394B2F236E75002CA5A0 /* KBChatUserMessageCell.m in Sources */,
|
||||
0F2A10032F3C0001002CA5A0 /* KBChatMessageActionPopView.m in Sources */,
|
||||
0F2A10132F3C0002002CA5A0 /* KBAIPersonaSidebarView.m in Sources */,
|
||||
04E0394C2F236E75002CA5A0 /* KBChatTimeCell.m in Sources */,
|
||||
04E0394D2F236E75002CA5A0 /* KBChatAssistantMessageCell.m in Sources */,
|
||||
04E0394E2F236E75002CA5A0 /* KBChatTableView.m in Sources */,
|
||||
@@ -2421,7 +2471,6 @@
|
||||
04122FAD2EC73C0100EF7AB3 /* KBVipSubscribeCell.m in Sources */,
|
||||
049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */,
|
||||
048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */,
|
||||
046086732F191B6900757C95 /* KBAiMainVC.m in Sources */,
|
||||
048909F72EC0AAAA00FABA60 /* KBCategoryTitleView.m in Sources */,
|
||||
048FFD332F29F3D2005D62AE /* KBAIMessageChatingVC.m in Sources */,
|
||||
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */,
|
||||
@@ -2440,6 +2489,7 @@
|
||||
046086CC2F1A092500757C95 /* KBAIReplyModel.m in Sources */,
|
||||
046086CD2F1A092500757C95 /* KBAICommentModel.m in Sources */,
|
||||
04791F8F2ED469C0004E8522 /* KBHostAppLauncher.m in Sources */,
|
||||
04F4C0BF2F33369900E8F08C /* KBAIChatDeleteConfirmView.m in Sources */,
|
||||
047C65582EBCC06D0035E841 /* HomeRankCardCell.m in Sources */,
|
||||
04D1F6B32EDFF10A00B12345 /* KBSkinInstallBridge.m in Sources */,
|
||||
04122F912EC73AF700EF7AB3 /* KBVipPay.m in Sources */,
|
||||
@@ -2475,6 +2525,7 @@
|
||||
048908E92EBF843000FABA60 /* KBSkinDetailHeaderCell.m in Sources */,
|
||||
04A9FE1B2EB892460020DB6D /* KBLocalizationManager.m in Sources */,
|
||||
048908BC2EBE1FCB00FABA60 /* BaseViewController.m in Sources */,
|
||||
04F4C0B02F322EF200E8F08C /* PagingViewTableHeaderView.m in Sources */,
|
||||
0498BD902EE6A3BD006CC1D5 /* KBMyMainModel.m in Sources */,
|
||||
A1F0C1C32FABCDEF12345678 /* KBInviteCodeModel.m in Sources */,
|
||||
A1F0C1D32FACAD0012345678 /* KBMaiPointReporter.m in Sources */,
|
||||
@@ -2511,6 +2562,8 @@
|
||||
047C655C2EBCD0F80035E841 /* UIView+KBShadow.m in Sources */,
|
||||
04E038DD2F20C420002CA5A0 /* VoiceChatStreamingManager.m in Sources */,
|
||||
04E038DE2F20C420002CA5A0 /* VoiceChatWebSocketClient.m in Sources */,
|
||||
04F4C0B52F33053800E8F08C /* KBSvipBenefitCell.m in Sources */,
|
||||
04F4C0B62F33053800E8F08C /* KBSvipSubscribeCell.m in Sources */,
|
||||
049FB2262EC3136D00FAB05D /* KBPersonInfoItemCell.m in Sources */,
|
||||
048908C32EBE32B800FABA60 /* KBSearchVC.m in Sources */,
|
||||
049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */,
|
||||
@@ -2518,6 +2571,7 @@
|
||||
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */,
|
||||
04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */,
|
||||
048908E02EBF73DC00FABA60 /* MySkinVC.m in Sources */,
|
||||
04F4C0AA2F32274000E8F08C /* KBPayMainVC.m in Sources */,
|
||||
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */,
|
||||
048908F22EC047FD00FABA60 /* KBShopHeadView.m in Sources */,
|
||||
0498BD742EE02E3D006CC1D5 /* KBRegistVerEmailVC.m in Sources */,
|
||||
@@ -2579,6 +2633,8 @@
|
||||
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */,
|
||||
0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */,
|
||||
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */,
|
||||
04F4C0BB2F3306CF00E8F08C /* KBSvipFlowLayout.m in Sources */,
|
||||
04F4C0BC2F3306CF00E8F08C /* KBSvipBenefitBgView.m in Sources */,
|
||||
04E039522F2387D2002CA5A0 /* KBAiChatMessage.m in Sources */,
|
||||
0460869A2F19238500757C95 /* KBAiWaveformView.m in Sources */,
|
||||
0460869C2F19238500757C95 /* KBAiRecordButton.m in Sources */,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#import "KBLoginPopView.h"
|
||||
#import "KBSexSelVC.h"
|
||||
#import "KBKeyboardPermissionManager.h"
|
||||
#import "KBVipPay.h"
|
||||
#import "KBPayMainVC.h"
|
||||
#import "KBUserSessionManager.h"
|
||||
#import "KBLoginVC.h"
|
||||
#import "KBConfig.h"
|
||||
@@ -192,6 +192,9 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
||||
return YES;
|
||||
} else if ([host isEqualToString:@"recharge"]) { // kbkeyboard://recharge
|
||||
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"];
|
||||
BOOL autoPay = NO;
|
||||
NSString *autoFlag = params[@"autoPay"];
|
||||
@@ -203,34 +206,37 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
||||
autoPay = YES;
|
||||
}
|
||||
|
||||
BOOL wantsPrefill = NO;
|
||||
NSString *prefillFlag = params[@"prefill"];
|
||||
if ([prefillFlag respondsToSelector:@selector(boolValue)] && prefillFlag.boolValue) {
|
||||
wantsPrefill = YES;
|
||||
}
|
||||
NSString *src = params[@"src"];
|
||||
if ([src isKindOfClass:NSString.class] && [src.lowercaseString isEqualToString:@"keyboard"]) {
|
||||
wantsPrefill = YES;
|
||||
}
|
||||
NSDictionary *prefillPayload = wantsPrefill ? [self kb_consumeSubscriptionPrefillPayloadIfValid] : nil;
|
||||
if ([prefillPayload isKindOfClass:NSDictionary.class]) {
|
||||
NSString *payloadProductId = prefillPayload[@"productId"];
|
||||
if (productId.length == 0 && [payloadProductId isKindOfClass:NSString.class]) {
|
||||
productId = payloadProductId;
|
||||
KBPayMainVC *vc = [[KBPayMainVC alloc] init];
|
||||
vc.initialSelectedIndex = preferSvip ? 1 : 0;
|
||||
if (!preferSvip) {
|
||||
BOOL wantsPrefill = NO;
|
||||
NSString *prefillFlag = params[@"prefill"];
|
||||
if ([prefillFlag respondsToSelector:@selector(boolValue)] && prefillFlag.boolValue) {
|
||||
wantsPrefill = YES;
|
||||
}
|
||||
NSString *src = params[@"src"];
|
||||
if ([src isKindOfClass:NSString.class] && [src.lowercaseString isEqualToString:@"keyboard"]) {
|
||||
wantsPrefill = YES;
|
||||
}
|
||||
NSDictionary *prefillPayload = wantsPrefill ? [self kb_consumeSubscriptionPrefillPayloadIfValid] : nil;
|
||||
if ([prefillPayload isKindOfClass:NSDictionary.class]) {
|
||||
NSString *payloadProductId = prefillPayload[@"productId"];
|
||||
if (productId.length == 0 && [payloadProductId isKindOfClass:NSString.class]) {
|
||||
productId = payloadProductId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KBVipPay *vc = [[KBVipPay alloc] init];
|
||||
if ([prefillPayload isKindOfClass:NSDictionary.class]) {
|
||||
NSArray *productsJSON = prefillPayload[@"products"];
|
||||
NSNumber *selectedIndexNumber = prefillPayload[@"selectedIndex"];
|
||||
NSInteger selectedIndex = [selectedIndexNumber respondsToSelector:@selector(integerValue)] ? selectedIndexNumber.integerValue : NSNotFound;
|
||||
[vc configureWithProductId:productId
|
||||
autoPurchase:autoPay
|
||||
prefillProductsJSON:productsJSON
|
||||
selectedIndex:selectedIndex];
|
||||
} else {
|
||||
[vc configureWithProductId:productId autoPurchase:autoPay];
|
||||
if ([prefillPayload isKindOfClass:NSDictionary.class]) {
|
||||
NSArray *productsJSON = prefillPayload[@"products"];
|
||||
NSNumber *selectedIndexNumber = prefillPayload[@"selectedIndex"];
|
||||
NSInteger selectedIndex = [selectedIndexNumber respondsToSelector:@selector(integerValue)] ? selectedIndexNumber.integerValue : NSNotFound;
|
||||
[vc configureWithProductId:productId
|
||||
autoPurchase:autoPay
|
||||
prefillProductsJSON:productsJSON
|
||||
selectedIndex:selectedIndex];
|
||||
} else {
|
||||
[vc configureWithProductId:productId autoPurchase:autoPay];
|
||||
}
|
||||
}
|
||||
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
||||
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/ai_more_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_more_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_more_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_more_icon.imageset/ai_more_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_more_icon.imageset/ai_more_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
22
keyBoard/Assets.xcassets/AI/ai_role_sel.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_role_sel@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_role_sel@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_role_sel.imageset/ai_role_sel@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
keyBoard/Assets.xcassets/AI/ai_role_sel.imageset/ai_role_sel@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
22
keyBoard/Assets.xcassets/AI/ai_search_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_search_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "ai_search_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/ai_search_icon.imageset/ai_search_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 923 B |
BIN
keyBoard/Assets.xcassets/AI/ai_search_icon.imageset/ai_search_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 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/AI/right_arrow_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "right_arrow_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "right_arrow_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
keyBoard/Assets.xcassets/AI/right_arrow_icon.imageset/right_arrow_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 474 B |
BIN
keyBoard/Assets.xcassets/AI/right_arrow_icon.imageset/right_arrow_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 858 B |
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) NSString *replyToUserId;
|
||||
@property(nonatomic, assign) NSString *replyToUserName;
|
||||
|
||||
/// 创建时间(时间戳)
|
||||
@property(nonatomic, assign) NSTimeInterval createTime;
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@
|
||||
if (!_content) {
|
||||
_content = @"";
|
||||
}
|
||||
if (!_replyToUserName) {
|
||||
_replyToUserName = @"";
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
|
||||
@@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property(nonatomic, copy) NSString *content;
|
||||
|
||||
/// 被回复的用户名(@xxx)
|
||||
@property(nonatomic, copy, nullable) NSString *replyToUserName;
|
||||
@property(nonatomic, copy) NSString *replyToUserName;
|
||||
|
||||
/// 点赞数
|
||||
@property(nonatomic, assign) NSInteger likeCount;
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
if (!_content) {
|
||||
_content = @"";
|
||||
}
|
||||
// if ([_content isEqualToString:@"78910"]) {
|
||||
// NSLog(@"===");
|
||||
// }
|
||||
if (!_replyToUserName) {
|
||||
_replyToUserName = @"";
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ typedef NS_ENUM(NSInteger, KBAiChatMessageType) {
|
||||
/// 消息类型
|
||||
@property (nonatomic, assign) KBAiChatMessageType type;
|
||||
|
||||
/// 聊天记录 ID(服务端返回的 id,用于删除等操作;0 表示本地临时消息)
|
||||
@property (nonatomic, assign) NSInteger historyId;
|
||||
|
||||
/// 文本内容
|
||||
@property (nonatomic, copy) NSString *text;
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, strong, nullable) NSArray<KBCommentItem *> *replies;
|
||||
/// 回复数量
|
||||
@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;
|
||||
/// 用户 ID
|
||||
|
||||
40
keyBoard/Class/AiTalk/V/Chat/KBChatMessageActionPopView.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// KBChatMessageActionPopView.h
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Codex on 2026/2/3.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSInteger, KBChatMessageActionType) {
|
||||
KBChatMessageActionTypeCopy = 0,
|
||||
KBChatMessageActionTypeDelete = 1,
|
||||
KBChatMessageActionTypeReport = 2,
|
||||
};
|
||||
|
||||
@class KBChatMessageActionPopView;
|
||||
|
||||
@protocol KBChatMessageActionPopViewDelegate <NSObject>
|
||||
@optional
|
||||
- (void)chatMessageActionPopView:(KBChatMessageActionPopView *)view
|
||||
didSelectAction:(KBChatMessageActionType)action;
|
||||
@end
|
||||
|
||||
/// 聊天消息长按操作弹窗(Copy / Delete / Report)
|
||||
@interface KBChatMessageActionPopView : UIView
|
||||
|
||||
@property (nonatomic, weak) id<KBChatMessageActionPopViewDelegate> delegate;
|
||||
|
||||
/// 是否显示 “Report” 操作(默认 YES)。
|
||||
/// - 当长按的是右侧用户消息(KBChatUserMessageCell)时,可设置为 NO。
|
||||
@property (nonatomic, assign) BOOL showsReportAction;
|
||||
|
||||
/// 根据是否显示 Report 计算推荐高度
|
||||
+ (CGFloat)preferredHeightWithShowsReportAction:(BOOL)showsReportAction;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||