fix: deep link hidden handling on MacOS (#1262)

This commit is contained in:
Levi authored and GitHub committed 2026-01-28 18:57:09 +08:00
1 parent 640e798d70
commit fe90c1d261
4 files changed
+82 -60

No files matched your search

@@ -62,6 +62,11 @@ final allTrackerSubscribeUrlCdns = {
class AppController extends GetxController with WindowListener, TrayListener {
static StartConfig? _defaultStartConfig;
/// Command line --hidden flag passed from main.dart
final bool hiddenFromArgs;
AppController({this.hiddenFromArgs = false});
final autoStartup = false.obs;
final startConfig = StartConfig().obs;
final runningPort = 0.obs;
@@ -156,24 +161,44 @@ class AppController extends GetxController with WindowListener, TrayListener {
Future<void> _initDeepLinks() async {
if (Util.isWeb()) {
// For web, just show window
return;
}
// Handle deep link
() async {
_appLinks = AppLinks();
_appLinks = AppLinks();
// Handle link when app is in warm state (front or background)
_linkSubscription = _appLinks.uriLinkStream.listen((uri) async {
await _handleDeepLink(uri);
});
// Handle link when app is in warm state (front or background)
_linkSubscription = _appLinks.uriLinkStream.listen((uri) async {
await _handleDeepLink(uri);
});
// Check initial link if app was in cold state (terminated)
final uri = await _appLinks.getInitialLink();
if (uri != null) {
await _handleDeepLink(uri);
}
}();
// Get initial link for cold start - this works after runApp()
Uri? initialLink;
try {
initialLink = await _appLinks.getInitialLink();
} catch (e) {
// ignore errors
}
// Determine if window should be hidden
// Priority 1: gopeed: URL scheme hidden parameter
// Priority 2: Command line --hidden flag
bool shouldHide = hiddenFromArgs;
if (initialLink?.scheme == "gopeed") {
shouldHide = initialLink!.queryParameters["hidden"] == "true";
}
// Show window if not hidden (desktop only)
if (Util.isDesktop() && !shouldHide) {
await windowManager.show();
await windowManager.focus();
}
// Handle initial link for deep link navigation
if (initialLink != null) {
_handleDeepLink(initialLink);
}
// Handle shared media, e.g. shared link from browser
if (Util.isMobile()) {
@@ -638,7 +663,7 @@ class AppController extends GetxController with WindowListener, TrayListener {
launchAtStartup.setup(
appName: packageInfo.appName,
appPath: Platform.resolvedExecutable,
args: ['--${Args.flagHidden}']);
args: ['--${StartupArgs.flagHidden}']);
autoStartup.value = await launchAtStartup.isEnabled();
}
@@ -44,7 +44,11 @@ class AppView extends GetView<AppController> {
// Set the title bar to use the actual brightness of the UI
windowManager.setBrightness(brightness);
}
return child!;
// Fix for GetX Overlay issue with Flutter 3.38.1+
// Reference: https://github.com/jonataslaw/getx/issues/3425
return Overlay(
initialEntries: [OverlayEntry(builder: (_) => child!)],
);
},
),
);
@@ -38,7 +38,7 @@ class ExtensionView extends GetView<ExtensionController> {
_installBtnController.start();
try {
await installExtension(InstallExtension(url: _installUrlController.text));
Get.snackbar('tip'.tr, 'extensionInstallSuccess'.tr);
showMessage('tip'.tr, 'extensionInstallSuccess'.tr);
await controller.load();
} catch (e) {
showErrorMessage(e);
@@ -109,7 +109,7 @@ class ExtensionView extends GetView<ExtensionController> {
try {
await installExtension(
InstallExtension(devMode: true, url: dir));
Get.snackbar(
showMessage(
'tip'.tr, 'extensionInstallSuccess'.tr);
await controller.load();
} catch (e) {
@@ -290,7 +290,7 @@ class ExtensionView extends GetView<ExtensionController> {
return showDialog<void>(
context: Get.context!,
barrierDismissible: false,
builder: (_) => AlertDialog(
builder: (dialogContext) => AlertDialog(
content: Builder(builder: (context) {
final height = MediaQuery.of(context).size.height;
final width = MediaQuery.of(context).size.width;
@@ -351,7 +351,7 @@ class ExtensionView extends GetView<ExtensionController> {
backgroundColor: MaterialStateProperty.all(
Get.theme.colorScheme.background)),
onPressed: () {
Get.back();
Navigator.of(dialogContext).pop();
},
child: Text('cancel'.tr),
),
@@ -372,7 +372,9 @@ class ExtensionView extends GetView<ExtensionController> {
UpdateExtensionSettings(
settings: formKey.currentState!.value));
await controller.load();
Get.back();
if (dialogContext.mounted) {
Navigator.of(dialogContext).pop();
}
}
} catch (e) {
showErrorMessage(e);
@@ -453,12 +455,12 @@ class ExtensionView extends GetView<ExtensionController> {
showDialog(
context: Get.context!,
barrierDismissible: false,
builder: (_) => AlertDialog(
builder: (dialogContext) => AlertDialog(
title: Text('extensionDelete'.tr),
actions: [
TextButton(
child: Text('cancel'.tr),
onPressed: () => Get.back(),
onPressed: () => Navigator.of(dialogContext).pop(),
),
TextButton(
child: Text(
@@ -469,7 +471,9 @@ class ExtensionView extends GetView<ExtensionController> {
try {
await deleteExtension(extension.identity);
await controller.load();
Get.back();
if (dialogContext.mounted) {
Navigator.of(dialogContext).pop();
}
} catch (e) {
showErrorMessage(e);
}
@@ -484,14 +488,14 @@ class ExtensionView extends GetView<ExtensionController> {
showDialog(
context: Get.context!,
builder: (context) => AlertDialog(
builder: (dialogContext) => AlertDialog(
content: Text('newVersionTitle'.trParams({
'version': 'v${controller.updateFlags[extension.identity]!}'
})),
actions: [
TextButton(
onPressed: () {
Get.back();
Navigator.of(dialogContext).pop();
},
child: Text('newVersionLater'.tr),
),
@@ -503,7 +507,9 @@ class ExtensionView extends GetView<ExtensionController> {
await updateExtension(extension.identity);
await controller.load();
controller.updateFlags.remove(extension.identity);
Get.back();
if (dialogContext.mounted) {
Navigator.of(dialogContext).pop();
}
showMessage('tip'.tr, 'extensionUpdateSuccess'.tr);
} catch (e) {
showErrorMessage(e);