fix: deep link for assets when asset viewer already open (#27971)

This commit is contained in:
Brandon Wees
2026-05-12 11:19:54 -05:00
committed by GitHub
parent ad7aedb843
commit dc6f8e746e
2 changed files with 32 additions and 48 deletions
+21 -8
View File
@@ -179,19 +179,32 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
final isColdStart = currentRouteName == null || currentRouteName == SplashScreenRoute.name; final isColdStart = currentRouteName == null || currentRouteName == SplashScreenRoute.name;
PageRouteInfo? route;
if (deepLink.uri.scheme == "immich") { if (deepLink.uri.scheme == "immich") {
final proposedRoute = await deepLinkHandler.handleScheme(deepLink, ref, isColdStart); route = await deepLinkHandler.handleScheme(deepLink, ref);
} else if (deepLink.uri.host == "my.immich.app") {
return proposedRoute; route = await deepLinkHandler.handleMyImmichApp(deepLink, ref);
} else {
return DeepLink.path(deepLink.path);
} }
if (deepLink.uri.host == "my.immich.app") { if (route == null) {
final proposedRoute = await deepLinkHandler.handleMyImmichApp(deepLink, ref, isColdStart); return isColdStart ? DeepLink.defaultPath : DeepLink.none;
return proposedRoute;
} }
return DeepLink.path(deepLink.path); // We need to replace the route if the destination is the current route
if (!isColdStart) {
unawaited(
ref.read(appRouterProvider).pushAndPopUntil(route, predicate: (r) => r.settings.name != route!.routeName),
);
return DeepLink.none;
}
return DeepLink([
// we need something to segue back to if the app was cold started
if (isColdStart) const TabShellRoute(children: [MainTimelineRoute()]),
route,
]);
} }
@override @override
+11 -40
View File
@@ -45,21 +45,12 @@ class DeepLinkService {
this._currentUser, this._currentUser,
); );
DeepLink _handleColdStart(PageRouteInfo<dynamic> route, bool isColdStart) { Future<PageRouteInfo?> handleScheme(PlatformDeepLink link, WidgetRef ref) async {
return DeepLink([
// we need something to segue back to if the app was cold started
// TODO: use MainTimelineRoute this when beta is default
if (isColdStart) const TabShellRoute(),
route,
]);
}
Future<DeepLink> handleScheme(PlatformDeepLink link, WidgetRef ref, bool isColdStart) async {
// get everything after the scheme, since Uri cannot parse path // get everything after the scheme, since Uri cannot parse path
final intent = link.uri.host; final intent = link.uri.host;
final queryParams = link.uri.queryParameters; final queryParams = link.uri.queryParameters;
PageRouteInfo<dynamic>? deepLinkRoute = switch (intent) { return switch (intent) {
"memory" => await _buildMemoryDeepLink(queryParams['id'] ?? ''), "memory" => await _buildMemoryDeepLink(queryParams['id'] ?? ''),
"asset" => await _buildAssetDeepLink(queryParams['id'] ?? '', ref), "asset" => await _buildAssetDeepLink(queryParams['id'] ?? '', ref),
"album" => await _buildAlbumDeepLink(queryParams['id'] ?? ''), "album" => await _buildAlbumDeepLink(queryParams['id'] ?? ''),
@@ -67,20 +58,9 @@ class DeepLinkService {
"activity" => await _buildActivityDeepLink(queryParams['albumId'] ?? ''), "activity" => await _buildActivityDeepLink(queryParams['albumId'] ?? ''),
_ => null, _ => null,
}; };
// Deep link resolution failed, safely handle it based on the app state
if (deepLinkRoute == null) {
if (isColdStart) {
return DeepLink.defaultPath;
}
return DeepLink.none;
}
return _handleColdStart(deepLinkRoute, isColdStart);
} }
Future<DeepLink> handleMyImmichApp(PlatformDeepLink link, WidgetRef ref, bool isColdStart) async { Future<PageRouteInfo?> handleMyImmichApp(PlatformDeepLink link, WidgetRef ref) async {
final path = link.uri.path; final path = link.uri.path;
const uuidRegex = r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; const uuidRegex = r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
@@ -88,29 +68,20 @@ class DeepLinkService {
final albumRegex = RegExp('/albums/($uuidRegex)'); final albumRegex = RegExp('/albums/($uuidRegex)');
final peopleRegex = RegExp('/people/($uuidRegex)'); final peopleRegex = RegExp('/people/($uuidRegex)');
PageRouteInfo<dynamic>? deepLinkRoute;
if (assetRegex.hasMatch(path)) { if (assetRegex.hasMatch(path)) {
final assetId = assetRegex.firstMatch(path)?.group(1) ?? ''; final assetId = assetRegex.firstMatch(path)?.group(1) ?? '';
deepLinkRoute = await _buildAssetDeepLink(assetId, ref); return _buildAssetDeepLink(assetId, ref);
} else if (albumRegex.hasMatch(path)) { }
if (albumRegex.hasMatch(path)) {
final albumId = albumRegex.firstMatch(path)?.group(1) ?? ''; final albumId = albumRegex.firstMatch(path)?.group(1) ?? '';
deepLinkRoute = await _buildAlbumDeepLink(albumId); return _buildAlbumDeepLink(albumId);
} else if (peopleRegex.hasMatch(path)) { }
if (peopleRegex.hasMatch(path)) {
final peopleId = peopleRegex.firstMatch(path)?.group(1) ?? ''; final peopleId = peopleRegex.firstMatch(path)?.group(1) ?? '';
deepLinkRoute = await _buildPeopleDeepLink(peopleId); return _buildPeopleDeepLink(peopleId);
} else if (path == "/memory") {
deepLinkRoute = await _buildMemoryDeepLink(null);
} }
// Deep link resolution failed, safely handle it based on the app state return null;
if (deepLinkRoute == null) {
if (isColdStart) {
return DeepLink.defaultPath;
}
return DeepLink.none;
}
return _handleColdStart(deepLinkRoute, isColdStart);
} }
Future<PageRouteInfo?> _buildMemoryDeepLink(String? memoryId) async { Future<PageRouteInfo?> _buildMemoryDeepLink(String? memoryId) async {