This commit is contained in:
2025-11-12 21:23:31 +08:00
parent 0aead49816
commit bc261661ae
7 changed files with 317 additions and 24 deletions

View File

@@ -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; }