624 lines
21 KiB
Objective-C
624 lines
21 KiB
Objective-C
//
|
|
// KeyboardViewController+Panels.m
|
|
// CustomKeyboard
|
|
//
|
|
// Created by Codex on 2026/02/22.
|
|
//
|
|
|
|
#import "KeyboardViewController+Private.h"
|
|
|
|
#import "KBAuthManager.h"
|
|
#import "KBBackspaceUndoManager.h"
|
|
#import "KBChatMessage.h"
|
|
#import "KBChatPanelView.h"
|
|
#import "KBFunctionView.h"
|
|
#import "KBHostAppLauncher.h"
|
|
#import "KBInputBufferManager.h"
|
|
#import "KBKey.h"
|
|
#import "KBKeyBoardMainView.h"
|
|
#import "KBKeyboardSubscriptionView.h"
|
|
#import "KBSettingView.h"
|
|
#import "Masonry.h"
|
|
#import <SDWebImage/SDWebImage.h>
|
|
#import <AVFoundation/AVAudioPlayer.h>
|
|
|
|
@implementation KeyboardViewController (Panels)
|
|
|
|
#pragma mark - Panel Mode
|
|
|
|
- (void)kb_setPanelMode:(KBKeyboardPanelMode)mode animated:(BOOL)animated {
|
|
if (mode == self.kb_panelMode) {
|
|
return;
|
|
}
|
|
|
|
KBKeyboardPanelMode fromMode = self.kb_panelMode;
|
|
self.kb_panelMode = mode;
|
|
|
|
// 主键盘视图是基础承载:确保存在(键盘隐藏后会被释放)
|
|
[self kb_ensureKeyBoardMainViewIfNeeded];
|
|
|
|
// 1) 先收起所有面板(再展开目标面板),避免互相调用导致漏关/层级错乱
|
|
[self kb_setSubscriptionPanelVisible:NO animated:animated];
|
|
[self kb_setSettingViewVisible:NO animated:animated];
|
|
[self kb_setChatPanelVisible:NO animated:animated];
|
|
[self kb_setFunctionPanelVisible:NO];
|
|
|
|
// 2) 再展开目标面板
|
|
switch (mode) {
|
|
case KBKeyboardPanelModeFunction:
|
|
[self kb_setFunctionPanelVisible:YES];
|
|
break;
|
|
case KBKeyboardPanelModeChat:
|
|
[self kb_setChatPanelVisible:YES animated:animated];
|
|
break;
|
|
case KBKeyboardPanelModeSettings:
|
|
[self kb_setSettingViewVisible:YES animated:animated];
|
|
break;
|
|
case KBKeyboardPanelModeSubscription:
|
|
[self kb_setSubscriptionPanelVisible:YES animated:animated];
|
|
break;
|
|
case KBKeyboardPanelModeMain:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// 3) 事件埋点:保持原逻辑(仅功能面板/主面板会互相曝光)
|
|
if (mode == KBKeyboardPanelModeFunction) {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportPageExposureWithEventName:@"enter_keyboard_function_panel"
|
|
pageId:@"keyboard_function_panel"
|
|
extra:nil
|
|
completion:nil];
|
|
} else if (mode == KBKeyboardPanelModeMain &&
|
|
fromMode == KBKeyboardPanelModeFunction) {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportPageExposureWithEventName:@"enter_keyboard_main_panel"
|
|
pageId:@"keyboard_main_panel"
|
|
extra:nil
|
|
completion:nil];
|
|
} else if (mode == KBKeyboardPanelModeSettings) {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportPageExposureWithEventName:@"enter_keyboard_settings"
|
|
pageId:@"keyboard_settings"
|
|
extra:nil
|
|
completion:nil];
|
|
} else if (mode == KBKeyboardPanelModeSubscription) {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportPageExposureWithEventName:@"enter_keyboard_subscription_panel"
|
|
pageId:@"keyboard_subscription_panel"
|
|
extra:nil
|
|
completion:nil];
|
|
}
|
|
|
|
// 4) 层级:保证当前面板在最上层
|
|
if (mode == KBKeyboardPanelModeSubscription) {
|
|
[self.contentView bringSubviewToFront:self.subscriptionView];
|
|
} else if (mode == KBKeyboardPanelModeSettings) {
|
|
[self.contentView bringSubviewToFront:self.settingView];
|
|
} else if (mode == KBKeyboardPanelModeChat) {
|
|
[self.contentView bringSubviewToFront:self.chatPanelView];
|
|
} else if (mode == KBKeyboardPanelModeFunction) {
|
|
[self.contentView bringSubviewToFront:self.functionView];
|
|
} else {
|
|
[self.contentView bringSubviewToFront:self.keyBoardMainView];
|
|
}
|
|
}
|
|
|
|
/// 对外兼容:切换显示功能面板/键盘主视图
|
|
- (void)showFunctionPanel:(BOOL)show {
|
|
if (show) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeFunction animated:NO];
|
|
return;
|
|
}
|
|
if (self.kb_panelMode == KBKeyboardPanelModeFunction) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeMain animated:NO];
|
|
}
|
|
}
|
|
|
|
/// 对外兼容:显示/隐藏设置页(高度与 keyBoardMainView 一致),右侧滑入/滑出
|
|
- (void)showSettingView:(BOOL)show {
|
|
if (show) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeSettings animated:YES];
|
|
return;
|
|
}
|
|
if (self.kb_panelMode == KBKeyboardPanelModeSettings) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeMain animated:YES];
|
|
}
|
|
}
|
|
|
|
/// 对外兼容:显示/隐藏聊天面板(覆盖整个键盘区域)
|
|
- (void)showChatPanel:(BOOL)show {
|
|
if (show) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeChat animated:YES];
|
|
return;
|
|
}
|
|
if (self.kb_panelMode == KBKeyboardPanelModeChat) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeMain animated:YES];
|
|
}
|
|
}
|
|
|
|
- (void)kb_setFunctionPanelVisible:(BOOL)visible {
|
|
if (visible) {
|
|
[self kb_ensureFunctionViewIfNeeded];
|
|
}
|
|
if (_functionView) {
|
|
_functionView.hidden = !visible;
|
|
} else if (visible) {
|
|
// ensure 后按理已存在;这里兜底一次,避免异常情况下状态不一致
|
|
self.functionView.hidden = NO;
|
|
}
|
|
self.keyBoardMainView.hidden = visible;
|
|
}
|
|
|
|
- (void)kb_setChatPanelVisible:(BOOL)visible animated:(BOOL)animated {
|
|
if (visible == self.chatPanelVisible) {
|
|
return;
|
|
}
|
|
self.chatPanelVisible = visible;
|
|
|
|
if (visible) {
|
|
// 记录打开聊天面板时宿主输入框已有的文本,发送时只取新增部分
|
|
[[KBInputBufferManager shared]
|
|
refreshFromProxyIfPossible:self.textDocumentProxy];
|
|
self.chatPanelBaselineText = [KBInputBufferManager shared].liveText ?: @"";
|
|
[self kb_ensureChatPanelViewIfNeeded];
|
|
self.chatPanelView.hidden = NO;
|
|
self.chatPanelView.alpha = 0.0;
|
|
if (animated) {
|
|
[UIView animateWithDuration:0.2
|
|
delay:0
|
|
options:UIViewAnimationOptionCurveEaseOut
|
|
animations:^{
|
|
self.chatPanelView.alpha = 1.0;
|
|
}
|
|
completion:nil];
|
|
} else {
|
|
self.chatPanelView.alpha = 1.0;
|
|
}
|
|
} else {
|
|
// 从未创建过聊天面板时,直接返回,避免 show/hide 触发额外内存分配
|
|
if (!_chatPanelView) {
|
|
[self kb_updateKeyboardLayoutIfNeeded];
|
|
return;
|
|
}
|
|
if (animated) {
|
|
[UIView animateWithDuration:0.18
|
|
delay:0
|
|
options:UIViewAnimationOptionCurveEaseIn
|
|
animations:^{
|
|
self.chatPanelView.alpha = 0.0;
|
|
}
|
|
completion:^(BOOL finished) {
|
|
self.chatPanelView.hidden = YES;
|
|
}];
|
|
} else {
|
|
self.chatPanelView.alpha = 0.0;
|
|
self.chatPanelView.hidden = YES;
|
|
}
|
|
}
|
|
[self kb_updateKeyboardLayoutIfNeeded];
|
|
}
|
|
|
|
- (void)kb_setSettingViewVisible:(BOOL)visible animated:(BOOL)animated {
|
|
if (visible) {
|
|
KBSettingView *settingView = self.settingView;
|
|
if (!settingView.superview) {
|
|
settingView.hidden = YES;
|
|
[self.contentView addSubview:settingView];
|
|
[settingView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.edges.equalTo(self.contentView);
|
|
}];
|
|
[settingView.backButton addTarget:self
|
|
action:@selector(onTapSettingsBack)
|
|
forControlEvents:UIControlEventTouchUpInside];
|
|
}
|
|
[self.contentView bringSubviewToFront:settingView];
|
|
// 以 keyBoardMainView 的实际宽度为准,避免首次添加时 self.view 宽度尚未计算
|
|
[self.contentView layoutIfNeeded];
|
|
CGFloat w = CGRectGetWidth(self.keyBoardMainView.bounds);
|
|
if (w <= 0) {
|
|
w = CGRectGetWidth(self.contentView.bounds);
|
|
}
|
|
if (w <= 0) {
|
|
w = [self kb_portraitWidth];
|
|
}
|
|
settingView.transform = CGAffineTransformMakeTranslation(w, 0);
|
|
settingView.hidden = NO;
|
|
if (animated) {
|
|
[UIView animateWithDuration:0.25
|
|
delay:0
|
|
options:UIViewAnimationOptionCurveEaseOut
|
|
animations:^{
|
|
settingView.transform = CGAffineTransformIdentity;
|
|
}
|
|
completion:nil];
|
|
} else {
|
|
settingView.transform = CGAffineTransformIdentity;
|
|
}
|
|
} else {
|
|
KBSettingView *settingView = _settingView;
|
|
if (!settingView) {
|
|
return;
|
|
}
|
|
if (!settingView.superview || settingView.hidden) {
|
|
return;
|
|
}
|
|
CGFloat w = CGRectGetWidth(self.keyBoardMainView.bounds);
|
|
if (w <= 0) {
|
|
w = CGRectGetWidth(self.contentView.bounds);
|
|
}
|
|
if (w <= 0) {
|
|
w = [self kb_portraitWidth];
|
|
}
|
|
if (animated) {
|
|
[UIView animateWithDuration:0.22
|
|
delay:0
|
|
options:UIViewAnimationOptionCurveEaseIn
|
|
animations:^{
|
|
settingView.transform = CGAffineTransformMakeTranslation(w, 0);
|
|
}
|
|
completion:^(BOOL finished) {
|
|
settingView.hidden = YES;
|
|
}];
|
|
} else {
|
|
settingView.transform = CGAffineTransformMakeTranslation(w, 0);
|
|
settingView.hidden = YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)kb_setSubscriptionPanelVisible:(BOOL)visible animated:(BOOL)animated {
|
|
if (visible) {
|
|
KBKeyboardSubscriptionView *panel = self.subscriptionView;
|
|
if (!panel.superview) {
|
|
panel.hidden = YES;
|
|
[self.contentView addSubview:panel];
|
|
[panel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.edges.equalTo(self.contentView);
|
|
}];
|
|
}
|
|
[self.contentView bringSubviewToFront:panel];
|
|
panel.hidden = NO;
|
|
panel.alpha = 0.0;
|
|
CGFloat height = CGRectGetHeight(self.contentView.bounds);
|
|
if (height <= 0) {
|
|
height = 260;
|
|
}
|
|
panel.transform = CGAffineTransformMakeTranslation(0, height);
|
|
[panel refreshProductsIfNeeded];
|
|
if (animated) {
|
|
[UIView animateWithDuration:0.25
|
|
delay:0
|
|
options:UIViewAnimationOptionCurveEaseOut
|
|
animations:^{
|
|
panel.alpha = 1.0;
|
|
panel.transform = CGAffineTransformIdentity;
|
|
}
|
|
completion:nil];
|
|
} else {
|
|
panel.alpha = 1.0;
|
|
panel.transform = CGAffineTransformIdentity;
|
|
}
|
|
return;
|
|
}
|
|
|
|
KBKeyboardSubscriptionView *panel = _subscriptionView;
|
|
if (!panel) {
|
|
return;
|
|
}
|
|
if (!panel.superview || panel.hidden) {
|
|
return;
|
|
}
|
|
CGFloat height = CGRectGetHeight(panel.bounds);
|
|
if (height <= 0) {
|
|
height = CGRectGetHeight(self.contentView.bounds);
|
|
}
|
|
if (animated) {
|
|
[UIView animateWithDuration:0.22
|
|
delay:0
|
|
options:UIViewAnimationOptionCurveEaseIn
|
|
animations:^{
|
|
panel.alpha = 0.0;
|
|
panel.transform = CGAffineTransformMakeTranslation(0, height);
|
|
}
|
|
completion:^(BOOL finished) {
|
|
panel.hidden = YES;
|
|
panel.alpha = 1.0;
|
|
panel.transform = CGAffineTransformIdentity;
|
|
}];
|
|
} else {
|
|
panel.hidden = YES;
|
|
panel.alpha = 1.0;
|
|
panel.transform = CGAffineTransformIdentity;
|
|
}
|
|
}
|
|
|
|
// 延迟创建:仅在用户真正打开功能面板时才创建/布局,降低默认内存占用。
|
|
- (void)kb_ensureFunctionViewIfNeeded {
|
|
if (_functionView && _functionView.superview) {
|
|
return;
|
|
}
|
|
KBFunctionView *v = self.functionView;
|
|
if (!v.superview) {
|
|
v.hidden = YES;
|
|
[self.contentView addSubview:v];
|
|
[v mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.edges.equalTo(self.contentView);
|
|
}];
|
|
}
|
|
}
|
|
|
|
// 延迟创建:仅在用户打开聊天面板时才创建/布局。
|
|
- (void)kb_ensureChatPanelViewIfNeeded {
|
|
if (_chatPanelView && _chatPanelView.superview) {
|
|
return;
|
|
}
|
|
CGFloat portraitWidth = [self kb_portraitWidth];
|
|
CGFloat chatPanelHeight = [self kb_chatPanelHeightForWidth:portraitWidth];
|
|
KBChatPanelView *v = self.chatPanelView;
|
|
if (!v.superview) {
|
|
[self.contentView addSubview:v];
|
|
[v mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.left.right.equalTo(self.contentView);
|
|
make.bottom.equalTo(self.keyBoardMainView.mas_top);
|
|
self.chatPanelHeightConstraint =
|
|
make.height.mas_equalTo(chatPanelHeight);
|
|
}];
|
|
v.hidden = YES;
|
|
}
|
|
}
|
|
|
|
// 延迟创建:键盘主面板(按键区)在隐藏时会被释放;再次显示时需要重建。
|
|
- (void)kb_ensureKeyBoardMainViewIfNeeded {
|
|
if (_keyBoardMainView && _keyBoardMainView.superview) {
|
|
return;
|
|
}
|
|
CGFloat portraitWidth = [self kb_portraitWidth];
|
|
CGFloat keyboardBaseHeight =
|
|
[self kb_keyboardBaseHeightForWidth:portraitWidth];
|
|
KBKeyBoardMainView *v = self.keyBoardMainView;
|
|
if (!v.superview) {
|
|
[self.contentView addSubview:v];
|
|
[v mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.left.right.equalTo(self.contentView);
|
|
make.bottom.equalTo(self.contentView);
|
|
self.keyBoardMainHeightConstraint =
|
|
make.height.mas_equalTo(keyboardBaseHeight);
|
|
}];
|
|
}
|
|
[self.contentView bringSubviewToFront:v];
|
|
}
|
|
|
|
// 键盘隐藏时释放可重建资源(背景图/缓存/非必需面板),降低扩展内存峰值。
|
|
- (void)kb_releaseMemoryWhenKeyboardHidden {
|
|
[KBHUD setContainerView:nil];
|
|
self.bgImageView.image = nil;
|
|
self.kb_cachedGradientImage = nil;
|
|
[self.kb_defaultGradientLayer removeFromSuperlayer];
|
|
self.kb_defaultGradientLayer = nil;
|
|
[[SDImageCache sharedImageCache] clearMemory];
|
|
|
|
// 聊天相关可能持有音频数据/临时文件,键盘隐藏时直接清空,避免累计占用。
|
|
if (self.chatAudioPlayer) {
|
|
[self.chatAudioPlayer stop];
|
|
self.chatAudioPlayer = nil;
|
|
}
|
|
if (_chatMessages.count > 0) {
|
|
NSString *tmpRoot = NSTemporaryDirectory();
|
|
for (KBChatMessage *msg in _chatMessages.copy) {
|
|
if (tmpRoot.length > 0 && msg.audioFilePath.length > 0 &&
|
|
[msg.audioFilePath hasPrefix:tmpRoot]) {
|
|
[[NSFileManager defaultManager] removeItemAtPath:msg.audioFilePath
|
|
error:nil];
|
|
}
|
|
}
|
|
[_chatMessages removeAllObjects];
|
|
}
|
|
|
|
if (_keyBoardMainView) {
|
|
[_keyBoardMainView removeFromSuperview];
|
|
_keyBoardMainView = nil;
|
|
}
|
|
self.keyBoardMainHeightConstraint = nil;
|
|
|
|
if (_functionView) {
|
|
[_functionView removeFromSuperview];
|
|
_functionView = nil;
|
|
}
|
|
if (_chatPanelView) {
|
|
[_chatPanelView removeFromSuperview];
|
|
_chatPanelView = nil;
|
|
}
|
|
self.chatPanelVisible = NO;
|
|
self.kb_panelMode = KBKeyboardPanelModeMain;
|
|
|
|
if (_subscriptionView) {
|
|
[_subscriptionView removeFromSuperview];
|
|
_subscriptionView = nil;
|
|
}
|
|
if (_settingView) {
|
|
[_settingView removeFromSuperview];
|
|
_settingView = nil;
|
|
}
|
|
}
|
|
|
|
// MARK: - KBKeyBoardMainViewDelegate
|
|
|
|
- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView
|
|
didTapKey:(KBKey *)key {
|
|
switch (key.type) {
|
|
case KBKeyTypeCharacter: {
|
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
|
NSString *text = key.output ?: key.title ?: @"";
|
|
[self.textDocumentProxy insertText:text];
|
|
[self kb_updateCurrentWordWithInsertedText:text];
|
|
[[KBInputBufferManager shared] appendText:text];
|
|
} break;
|
|
case KBKeyTypeBackspace:
|
|
[[KBInputBufferManager shared]
|
|
refreshFromProxyIfPossible:self.textDocumentProxy];
|
|
[[KBInputBufferManager shared]
|
|
prepareSnapshotForDeleteWithContextBefore:
|
|
self.textDocumentProxy.documentContextBeforeInput
|
|
after:
|
|
self.textDocumentProxy
|
|
.documentContextAfterInput];
|
|
[[KBBackspaceUndoManager shared]
|
|
captureAndDeleteBackwardFromProxy:self.textDocumentProxy
|
|
count:1];
|
|
[self kb_scheduleContextRefreshResetSuppression:NO];
|
|
[[KBInputBufferManager shared] applyHoldDeleteCount:1];
|
|
break;
|
|
case KBKeyTypeSpace:
|
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
|
[self.textDocumentProxy insertText:@" "];
|
|
[self kb_clearCurrentWord];
|
|
[[KBInputBufferManager shared] appendText:@" "];
|
|
break;
|
|
case KBKeyTypeReturn:
|
|
if (self.chatPanelVisible) {
|
|
[self kb_handleChatSendAction];
|
|
break;
|
|
}
|
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
|
[self.textDocumentProxy insertText:@"\n"];
|
|
[self kb_clearCurrentWord];
|
|
[[KBInputBufferManager shared] appendText:@"\n"];
|
|
break;
|
|
case KBKeyTypeGlobe:
|
|
[self advanceToNextInputMode];
|
|
break;
|
|
case KBKeyTypeCustom:
|
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
|
// 点击自定义键切换到功能面板
|
|
[self kb_setPanelMode:KBKeyboardPanelModeFunction animated:NO];
|
|
[self kb_clearCurrentWord];
|
|
break;
|
|
case KBKeyTypeModeChange:
|
|
case KBKeyTypeShift:
|
|
// 这些已在 KBKeyBoardMainView/KBKeyboardView 内部处理
|
|
break;
|
|
}
|
|
}
|
|
|
|
- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView
|
|
didTapToolActionAtIndex:(NSInteger)index {
|
|
NSDictionary *extra = @{@"index" : @(index)};
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportClickWithEventName:@"click_keyboard_toolbar_action"
|
|
pageId:@"keyboard_main_panel"
|
|
elementId:@"toolbar_action"
|
|
extra:extra
|
|
completion:nil];
|
|
if (index == 0) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeFunction animated:YES];
|
|
[self kb_clearCurrentWord];
|
|
return;
|
|
}
|
|
if (index == 1) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeChat animated:YES];
|
|
return;
|
|
}
|
|
[self kb_setPanelMode:KBKeyboardPanelModeMain animated:YES];
|
|
}
|
|
|
|
- (void)keyBoardMainViewDidTapSettings:(KBKeyBoardMainView *)keyBoardMainView {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportClickWithEventName:@"click_keyboard_settings_btn"
|
|
pageId:@"keyboard_main_panel"
|
|
elementId:@"settings_btn"
|
|
extra:nil
|
|
completion:nil];
|
|
[self kb_setPanelMode:KBKeyboardPanelModeSettings animated:YES];
|
|
}
|
|
|
|
- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView
|
|
didSelectEmoji:(NSString *)emoji {
|
|
if (emoji.length == 0) {
|
|
return;
|
|
}
|
|
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
|
[self.textDocumentProxy insertText:emoji];
|
|
[self kb_clearCurrentWord];
|
|
[[KBInputBufferManager shared] appendText:emoji];
|
|
}
|
|
|
|
- (void)keyBoardMainViewDidTapUndo:(KBKeyBoardMainView *)keyBoardMainView {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportClickWithEventName:@"click_keyboard_undo_btn"
|
|
pageId:@"keyboard_main_panel"
|
|
elementId:@"undo_btn"
|
|
extra:nil
|
|
completion:nil];
|
|
[[KBBackspaceUndoManager shared] performUndoFromResponder:self.view];
|
|
[self kb_scheduleContextRefreshResetSuppression:YES];
|
|
}
|
|
|
|
- (void)keyBoardMainViewDidTapEmojiSearch:
|
|
(KBKeyBoardMainView *)keyBoardMainView {
|
|
// [[KBMaiPointReporter sharedReporter]
|
|
// reportClickWithEventName:@"click_keyboard_emoji_search_btn"
|
|
// pageId:@"keyboard_main_panel"
|
|
// elementId:@"emoji_search_btn"
|
|
// extra:nil
|
|
// completion:nil];
|
|
[KBHUD showInfo:KBLocalized(@"Search coming soon")];
|
|
}
|
|
|
|
// MARK: - KBFunctionViewDelegate
|
|
|
|
- (void)functionView:(KBFunctionView *)functionView
|
|
didTapToolActionAtIndex:(NSInteger)index {
|
|
// 需求:当 index == 0 时,切回键盘主视图
|
|
if (index == 0) {
|
|
[self kb_setPanelMode:KBKeyboardPanelModeMain animated:NO];
|
|
}
|
|
}
|
|
|
|
- (void)functionView:(KBFunctionView *_Nullable)functionView
|
|
didRightTapToolActionAtIndex:(NSInteger)index {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportClickWithEventName:@"click_keyboard_function_right_action"
|
|
pageId:@"keyboard_function_panel"
|
|
elementId:@"right_action"
|
|
extra:@{@"action" : @"login_or_recharge"}
|
|
completion:nil];
|
|
if (!KBAuthManager.shared.isLoggedIn) {
|
|
NSString *schemeStr =
|
|
[NSString stringWithFormat:@"%@://login?src=keyboard", KB_APP_SCHEME];
|
|
NSURL *scheme = [NSURL URLWithString:schemeStr];
|
|
// 从当前视图作为起点,通过响应链找到 UIApplication 再调起主 App
|
|
BOOL ok = [KBHostAppLauncher openHostAppURL:scheme fromResponder:self.view];
|
|
return;
|
|
}
|
|
NSString *schemeStr =
|
|
[NSString stringWithFormat:@"%@://recharge?src=keyboard", KB_APP_SCHEME];
|
|
NSURL *scheme = [NSURL URLWithString:schemeStr];
|
|
// 从当前视图作为起点,通过响应链找到 UIApplication 再调起主 App
|
|
BOOL ok = [KBHostAppLauncher openHostAppURL:scheme fromResponder:self.view];
|
|
|
|
if (!ok) {
|
|
// 失败兜底:给个文案提示
|
|
// 比如:请回到桌面手动打开 XXX App 进行设置/充值
|
|
[KBHUD showInfo:@"请回到桌面手动打开App进行充值"];
|
|
}
|
|
}
|
|
|
|
- (void)functionViewDidRequestSubscription:(KBFunctionView *)functionView {
|
|
[self showSubscriptionPanel];
|
|
}
|
|
|
|
#pragma mark - Actions
|
|
|
|
- (void)onTapSettingsBack {
|
|
[[KBMaiPointReporter sharedReporter]
|
|
reportClickWithEventName:@"click_keyboard_settings_back_btn"
|
|
pageId:@"keyboard_settings"
|
|
elementId:@"back_btn"
|
|
extra:nil
|
|
completion:nil];
|
|
[self kb_setPanelMode:KBKeyboardPanelModeMain animated:YES];
|
|
}
|
|
|
|
@end
|