feat(mobile): deep links (#19232)

* add deep linking on ios app

* add deeplinking to android

* code review fixes

* lint

* cleanly handle malformed URIs when launching app

* refactor deep link builder/service, still have bug with navigation stack not containing TabControllerRoute

* fix: tab controller insertion conditions

* add my.immich.app app linking

* chore: remove one-liner if statement

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Brandon Wees 2025-06-24 09:20:24 -05:00 committed by GitHub
parent c759233d8c
commit 7d0e8f50f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 251 additions and 5 deletions

View file

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:io';
import 'package:auto_route/auto_route.dart';
import 'package:background_downloader/background_downloader.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:easy_localization/easy_localization.dart';
@ -17,6 +18,7 @@ import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provide
import 'package:immich_mobile/providers/db.provider.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/providers/locale_provider.dart';
import 'package:immich_mobile/providers/routes.provider.dart';
import 'package:immich_mobile/providers/theme.provider.dart';
import 'package:immich_mobile/routing/app_navigation_observer.dart';
import 'package:immich_mobile/routing/router.dart';
@ -26,6 +28,7 @@ import 'package:immich_mobile/theme/dynamic_theme.dart';
import 'package:immich_mobile/theme/theme_data.dart';
import 'package:immich_mobile/utils/bootstrap.dart';
import 'package:immich_mobile/utils/cache/widgets_binding.dart';
import 'package:immich_mobile/services/deep_link.service.dart';
import 'package:immich_mobile/utils/download.dart';
import 'package:immich_mobile/utils/http_ssl_options.dart';
import 'package:immich_mobile/utils/migration.dart';
@ -169,6 +172,31 @@ class ImmichAppState extends ConsumerState<ImmichApp>
);
}
Future<DeepLink> _deepLinkBuilder(PlatformDeepLink deepLink) async {
final deepLinkHandler = ref.read(deepLinkServiceProvider);
final currentRouteName = ref.read(currentRouteNameProvider.notifier).state;
if (deepLink.uri.scheme == "immich") {
final proposedRoute = await deepLinkHandler.handleScheme(
deepLink,
currentRouteName == SplashScreenRoute.name,
);
return proposedRoute;
}
if (deepLink.uri.host == "my.immich.app") {
final proposedRoute = await deepLinkHandler.handleMyImmichApp(
deepLink,
currentRouteName == SplashScreenRoute.name,
);
return proposedRoute;
}
return DeepLink.path(deepLink.path);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
@ -220,8 +248,8 @@ class ImmichAppState extends ConsumerState<ImmichApp>
colorScheme: immichTheme.light,
locale: context.locale,
),
routeInformationParser: router.defaultRouteParser(),
routerDelegate: router.delegate(
routerConfig: router.config(
deepLinkBuilder: _deepLinkBuilder,
navigatorObservers: () => [AppNavigationObserver(ref: ref)],
),
),