diff --git a/CustomKeyboard/KeyboardViewControllerHelp/KeyboardViewController+Panels.m b/CustomKeyboard/KeyboardViewControllerHelp/KeyboardViewController+Panels.m
index 7a8dcef..d4417f9 100644
--- a/CustomKeyboard/KeyboardViewControllerHelp/KeyboardViewController+Panels.m
+++ b/CustomKeyboard/KeyboardViewControllerHelp/KeyboardViewController+Panels.m
@@ -12,6 +12,7 @@
#import "KBChatMessage.h"
#import "KBChatPanelView.h"
#import "KBFunctionView.h"
+#import "KBFullAccessManager.h"
#import "KBHostAppLauncher.h"
#import "KBInputBufferManager.h"
#import "KBKey.h"
@@ -32,6 +33,38 @@
}
KBKeyboardPanelMode fromMode = self.kb_panelMode;
+
+ // AI 入口先判完全访问:未开启时仅展示引导,不再继续登录态判断。
+ if (mode == KBKeyboardPanelModeFunction &&
+ ![[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self.view]) {
+ return;
+ }
+
+ // 未登录时,不要提前写入面板状态,避免 mode 被错误卡在 Function 导致后续点击无响应。
+ BOOL islogin = YES;
+ if (mode == KBKeyboardPanelModeFunction) {
+ [[KBAuthManager shared] reloadFromKeychain];
+ islogin = KBAuthManager.shared.isLoggedIn;
+ }
+#if DEBUG
+ if (mode == KBKeyboardPanelModeFunction) {
+ NSString *token = [KBAuthManager shared].current.accessToken ?: @"";
+ NSLog(@"[AuthTrace][Ext] tapAI mode=%ld isLoggedIn=%d tokenLen=%lu",
+ (long)mode, islogin, (unsigned long)token.length);
+ }
+#endif
+ if (mode == KBKeyboardPanelModeFunction && !islogin) {
+ [KBHUD showInfo:KBLocalized(@"请先登录后使用AI功能")];
+ NSString *schemeStr =
+ [NSString stringWithFormat:@"%@://login?src=keyboard", KB_APP_SCHEME];
+ NSURL *scheme = [NSURL URLWithString:schemeStr];
+ BOOL ok = [KBHostAppLauncher openHostAppURL:scheme fromResponder:self.view];
+ if (!ok) {
+ [KBHUD showInfo:KBLocalized(@"请回到桌面手动打开App登录")];
+ }
+ return;
+ }
+
self.kb_panelMode = mode;
// 主键盘视图是基础承载:确保存在(键盘隐藏后会被释放)
@@ -44,31 +77,23 @@
[self kb_setFunctionPanelVisible:NO];
// 2) 再展开目标面板
- switch (mode) {
- case KBKeyboardPanelModeFunction:
- 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;
- }
- [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;
- }
+ 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) {
diff --git a/Shared/KBUserSessionManager.m b/Shared/KBUserSessionManager.m
index 2780d4a..fbaa905 100644
--- a/Shared/KBUserSessionManager.m
+++ b/Shared/KBUserSessionManager.m
@@ -99,10 +99,22 @@ static NSString * const kKBSessionInstallFlagKey = @"KBSession.installInitialize
// 先写 Keychain(统一走 KBAuthManager)
NSString *token = user.token;
if (token.length > 0) {
- [[KBAuthManager shared] saveAccessToken:token
- refreshToken:nil
- expiryDate:nil
- userIdentifier:nil];
+ BOOL saveOK = [[KBAuthManager shared] saveAccessToken:token
+ refreshToken:nil
+ expiryDate:nil
+ userIdentifier:nil];
+#if DEBUG
+ NSLog(@"[AuthTrace][App] saveAccessToken tokenLen=%lu saveOK=%d",
+ (unsigned long)token.length, saveOK);
+#endif
+ // 主动 reload 一次,便于立即验证当前进程读到的登录态
+ [[KBAuthManager shared] reloadFromKeychain];
+#if DEBUG
+ NSString *savedToken = [KBAuthManager shared].current.accessToken ?: @"";
+ NSLog(@"[AuthTrace][App] reloadAfterSave isLoggedIn=%d tokenLen=%lu",
+ [KBAuthManager shared].isLoggedIn,
+ (unsigned long)savedToken.length);
+#endif
}
// 再缓存用户信息,供 App/键盘使用
diff --git a/keyBoard/Assets.xcassets/Ohter/ai_placehode_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/Ohter/ai_placehode_icon.imageset/Contents.json
new file mode 100644
index 0000000..c8b8c42
--- /dev/null
+++ b/keyBoard/Assets.xcassets/Ohter/ai_placehode_icon.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "微信图片_20260226192149_128_935 (1).png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/keyBoard/Assets.xcassets/Ohter/ai_placehode_icon.imageset/微信图片_20260226192149_128_935 (1).png b/keyBoard/Assets.xcassets/Ohter/ai_placehode_icon.imageset/微信图片_20260226192149_128_935 (1).png
new file mode 100644
index 0000000..4a0f402
Binary files /dev/null and b/keyBoard/Assets.xcassets/Ohter/ai_placehode_icon.imageset/微信图片_20260226192149_128_935 (1).png differ
diff --git a/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m b/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m
index a6cbce1..b5ccf75 100644
--- a/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m
+++ b/keyBoard/Class/AiTalk/V/Chat/KBPersonaChatCell.m
@@ -213,7 +213,7 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
// 设置 UI
[self.backgroundImageView sd_setImageWithURL:[NSURL URLWithString:persona.coverImageUrl]
- placeholderImage:[UIImage imageNamed:@"placeholder_bg"]];
+ placeholderImage:[UIImage imageNamed:@"ai_placehode_icon"]];
[self.avatarImageView sd_setImageWithURL:[NSURL URLWithString:persona.avatarUrl]
placeholderImage:[UIImage imageNamed:@"placeholder_avatar"]];
self.nameLabel.text = persona.name;
diff --git a/keyBoard/Info.plist b/keyBoard/Info.plist
index f4ed86f..ab9455d 100644
--- a/keyBoard/Info.plist
+++ b/keyBoard/Info.plist
@@ -28,5 +28,7 @@
audio
+ UIDesignRequiresCompatibility
+