2
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
#import "KBFullAccessGuideView.h"
|
||||
#import "KBFullAccessManager.h"
|
||||
#import "KBSkinManager.h"
|
||||
#import "KBAuthManager.h" // 登录态判断(共享钥匙串)
|
||||
#import "KBULBridge.h" // Darwin 通知常量(UL 已处理)
|
||||
#import "KBURLOpenBridge.h" // 兜底从扩展侧直接尝试 openURL:
|
||||
#import "KBStreamTextView.h" // 流式文本视图
|
||||
#import "KBStreamOverlayView.h" // 带关闭按钮的流式层
|
||||
@@ -47,6 +49,10 @@
|
||||
// 剪贴板自动检测
|
||||
@property (nonatomic, strong) NSTimer *pasteboardTimer; // 轮询定时器(轻量、主线程)
|
||||
@property (nonatomic, assign) NSInteger lastHandledPBCount; // 上次处理过的 changeCount,避免重复弹窗
|
||||
|
||||
// UL 双路兜底
|
||||
@property (nonatomic, assign) NSUInteger kb_ulSeq; // 当前 UL 发起序号
|
||||
@property (nonatomic, assign) BOOL kb_ulHandledFlag; // 主 App 已确认处理 UL
|
||||
@end
|
||||
|
||||
@implementation KBFunctionView
|
||||
@@ -64,6 +70,14 @@
|
||||
|
||||
// 监听“完全访问”状态变化,动态启停剪贴板监控,避免在未开完全访问时触发 TCC/XPC 错误日志
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_fullAccessChanged) name:KBFullAccessChangedNotification object:nil];
|
||||
|
||||
// 监听主 App 的 Darwin 确认(UL 已处理)
|
||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
|
||||
(__bridge const void *)(self),
|
||||
KBULDarwinCallback,
|
||||
(__bridge CFStringRef)KBDarwinULHandled,
|
||||
NULL,
|
||||
CFNotificationSuspensionBehaviorDeliverImmediately);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -81,6 +95,7 @@
|
||||
[self stopPasteboardMonitor];
|
||||
[self kb_stopNetworkStreaming];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), (__bridge CFStringRef)KBDarwinULHandled, NULL);
|
||||
}
|
||||
|
||||
#pragma mark - UI
|
||||
@@ -278,27 +293,34 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
#pragma mark - KBFunctionTagListViewDelegate
|
||||
|
||||
- (void)tagListView:(KBFunctionTagListView *)view didSelectIndex:(NSInteger)index title:(NSString *)title {
|
||||
// 权限全部打开(键盘已启用 + 完全访问)。在扩展进程中仅需判断“完全访问”。
|
||||
if ([[KBFullAccessManager shared] hasFullAccess]) {
|
||||
// 先在 cell 上显示小菊花,等有数据回来再弹出 overlay
|
||||
[self.tagListView setLoading:YES atIndex:index];
|
||||
self.loadingTagIndex = @(index);
|
||||
self.loadingTagTitle = title ?: @"";
|
||||
[self kb_startNetworkStreamingWithSeed:self.loadingTagTitle];
|
||||
// 1) 先判断权限:未开启“完全访问”则走引导逻辑
|
||||
if (![[KBFullAccessManager shared] hasFullAccess]) {
|
||||
// 未开启完全访问:保持原有引导路径
|
||||
[KBHUD showInfo:@"处理中…"];
|
||||
[[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self];
|
||||
return;
|
||||
}
|
||||
// 未开启完全访问:保持原有引导路径
|
||||
[KBHUD showInfo:@"处理中…"];
|
||||
UIInputViewController *ivc = KBFindInputViewController(self);
|
||||
if (!ivc) return;
|
||||
NSString *encodedTitle = [title stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ?: @"";
|
||||
NSURL *ul = [NSURL URLWithString:[NSString stringWithFormat:@"%@?src=functionView&index=%ld&title=%@", KB_UL_LOGIN, (long)index, encodedTitle]];
|
||||
if (!ul) return;
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[ivc.extensionContext openURL:ul completionHandler:^(BOOL ok) {
|
||||
if (ok) return; // Universal Link 成功
|
||||
NSURL *scheme = [NSURL URLWithString:[NSString stringWithFormat:@"%@@//login?src=functionView&index=%ld&title=%@", KB_APP_SCHEME, (long)index, encodedTitle]];
|
||||
[ivc.extensionContext openURL:scheme completionHandler:^(BOOL ok2) {
|
||||
|
||||
// 2) 权限没问题,再判断是否登录:未登录 -> 直接拉起主 App,由主 App 负责完成登录
|
||||
if (!KBAuthManager.shared.isLoggedIn) {
|
||||
UIInputViewController *ivc = KBFindInputViewController(self);
|
||||
if (!ivc) return;
|
||||
NSString *encodedTitle = [title stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ?: @"";
|
||||
NSURL *ul = [NSURL URLWithString:[NSString stringWithFormat:@"%@?src=functionView&index=%ld&title=%@", KB_UL_LOGIN, (long)index, encodedTitle]];
|
||||
if (!ul) return;
|
||||
// 发起 UL,不依赖 ok 结果
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[ivc.extensionContext openURL:ul completionHandler:^(__unused BOOL ok) {}];
|
||||
});
|
||||
// 双路兜底:500ms 内未收到主 App 确认,则回退到自定义 Scheme
|
||||
self.kb_ulHandledFlag = NO;
|
||||
NSUInteger token = ++self.kb_ulSeq;
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
if (token != self.kb_ulSeq) return; // 已有新请求覆盖
|
||||
if (self.kb_ulHandledFlag) return; // 主 App 已确认处理
|
||||
NSURL *scheme = [NSURL URLWithString:[NSString stringWithFormat:@"%@://login?src=functionView&index=%ld&title=%@", KB_APP_SCHEME, (long)index, encodedTitle]];
|
||||
if (!scheme) return;
|
||||
[ivc.extensionContext openURL:scheme completionHandler:^(__unused BOOL ok2) {
|
||||
if (ok2) return;
|
||||
BOOL bridged = NO;
|
||||
@try {
|
||||
@@ -308,11 +330,26 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
#pragma clang diagnostic pop
|
||||
} @catch (__unused NSException *e) { bridged = NO; }
|
||||
if (!bridged) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{ [[KBFullAccessManager shared] ensureFullAccessOrGuideInView:self]; });
|
||||
[KBHUD showInfo:@"请切换到主App完成登录"];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 3) 已登录:开始业务逻辑(展示加载并拉取流式内容)
|
||||
[self.tagListView setLoading:YES atIndex:index];
|
||||
self.loadingTagIndex = @(index);
|
||||
self.loadingTagTitle = title ?: @"";
|
||||
[self kb_startNetworkStreamingWithSeed:self.loadingTagTitle];
|
||||
return;
|
||||
}
|
||||
|
||||
// Darwin 回调:主 App 已处理 UL
|
||||
static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
|
||||
KBFunctionView *self_ = (__bridge KBFunctionView *)observer;
|
||||
if (!self_) return;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{ self_.kb_ulHandledFlag = YES; });
|
||||
}
|
||||
|
||||
// 用户点击功能标签:优先 UL 拉起主App,失败再 Scheme;两次都失败则提示开启完全访问。
|
||||
@@ -578,6 +615,7 @@ static NSString * const kKBStreamDemoURL = @"http://192.168.1.144:7529/api/demo/
|
||||
return _sendButtonInternal;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Expose
|
||||
|
||||
- (UICollectionView *)collectionView { return self.tagListView.collectionView; }
|
||||
|
||||
Reference in New Issue
Block a user