mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
feat: add support for multiple scenes and handle URL contexts in iOS 13+ (#1889)
This commit is contained in:
82
client/platforms/ios/AmneziaSceneDelegateHooks.mm
Normal file
82
client/platforms/ios/AmneziaSceneDelegateHooks.mm
Normal file
@@ -0,0 +1,82 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <objc/runtime.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
|
||||
#include "ios_controller.h"
|
||||
|
||||
using SceneOpenURLContexts = void (*)(id, SEL, UIScene *, NSSet<UIOpenURLContext *> *);
|
||||
|
||||
static SceneOpenURLContexts g_originalSceneOpenURLContexts = nullptr;
|
||||
|
||||
static void amnezia_handleURL(NSURL *url)
|
||||
{
|
||||
if (!url || !url.isFileURL) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString filePath(url.path.UTF8String);
|
||||
if (filePath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
if (filePath.contains("backup")) {
|
||||
IosController::Instance()->importBackupFromOutside(filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray data = file.readAll();
|
||||
IosController::Instance()->importConfigFromOutside(QString::fromUtf8(data));
|
||||
});
|
||||
}
|
||||
|
||||
static void amnezia_scene_openURLContexts(id self, SEL _cmd, UIScene *scene, NSSet<UIOpenURLContext *> *contexts)
|
||||
{
|
||||
if (g_originalSceneOpenURLContexts) {
|
||||
g_originalSceneOpenURLContexts(self, _cmd, scene, contexts);
|
||||
}
|
||||
|
||||
if (!contexts || contexts.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (@available(iOS 13.0, *)) {
|
||||
for (UIOpenURLContext *context in contexts) {
|
||||
amnezia_handleURL(context.URL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@interface AmneziaSceneDelegateHooks : NSObject
|
||||
@end
|
||||
|
||||
@implementation AmneziaSceneDelegateHooks
|
||||
|
||||
+ (void)load
|
||||
{
|
||||
Class cls = objc_getClass("QIOSWindowSceneDelegate");
|
||||
if (!cls) {
|
||||
return;
|
||||
}
|
||||
|
||||
SEL selector = @selector(scene:openURLContexts:);
|
||||
Method method = class_getInstanceMethod(cls, selector);
|
||||
if (method) {
|
||||
g_originalSceneOpenURLContexts = reinterpret_cast<SceneOpenURLContexts>(method_getImplementation(method));
|
||||
method_setImplementation(method, reinterpret_cast<IMP>(amnezia_scene_openURLContexts));
|
||||
} else {
|
||||
const char *types = "v@:@@";
|
||||
class_addMethod(cls, selector, reinterpret_cast<IMP>(amnezia_scene_openURLContexts), types);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -29,12 +29,46 @@ const char* MessageKey::SplitTunnelSites = "SplitTunnelSites";
|
||||
|
||||
#if !MACOS_NE
|
||||
static UIViewController* getViewController() {
|
||||
NSArray *windows = [[UIApplication sharedApplication]windows];
|
||||
for (UIWindow *window in windows) {
|
||||
if (window.isKeyWindow) {
|
||||
UIApplication *application = [UIApplication sharedApplication];
|
||||
|
||||
if (@available(iOS 13.0, *)) {
|
||||
for (UIScene *scene in application.connectedScenes) {
|
||||
if (scene.activationState != UISceneActivationStateForegroundActive) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (![scene isKindOfClass:[UIWindowScene class]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UIWindowScene *windowScene = (UIWindowScene *)scene;
|
||||
|
||||
for (UIWindow *window in windowScene.windows) {
|
||||
if (window.isKeyWindow && window.rootViewController) {
|
||||
return window.rootViewController;
|
||||
}
|
||||
}
|
||||
|
||||
for (UIWindow *window in windowScene.windows) {
|
||||
if (!window.isHidden && window.rootViewController) {
|
||||
return window.rootViewController;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (UIWindow *window in application.windows) {
|
||||
if (window.isKeyWindow && window.rootViewController) {
|
||||
return window.rootViewController;
|
||||
}
|
||||
}
|
||||
|
||||
for (UIWindow *window in application.windows) {
|
||||
if (window.rootViewController) {
|
||||
return window.rootViewController;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user