From c9539a4aa8814b2d05ab267386d90cc1842b1c9c Mon Sep 17 00:00:00 2001 From: Yaros Date: Tue, 21 Jul 2026 23:26:23 +0200 Subject: [PATCH] fix(mobile): map unresponsive after viewing asset (#27036) * fix(mobile): map unresponsive after viewing asset * chore: better fix --- mobile/lib/presentation/widgets/map/map.widget.dart | 9 ++++++--- mobile/lib/providers/routes.provider.dart | 1 + mobile/lib/routing/app_navigation_observer.dart | 11 +++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mobile/lib/presentation/widgets/map/map.widget.dart b/mobile/lib/presentation/widgets/map/map.widget.dart index f6c4f7d468..a68a475ad4 100644 --- a/mobile/lib/presentation/widgets/map/map.widget.dart +++ b/mobile/lib/presentation/widgets/map/map.widget.dart @@ -16,7 +16,6 @@ import 'package:immich_mobile/presentation/widgets/bottom_sheet/map_bottom_sheet import 'package:immich_mobile/presentation/widgets/map/map.state.dart'; import 'package:immich_mobile/presentation/widgets/map/map_utils.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; -import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/utils/async_mutex.dart'; import 'package:immich_mobile/utils/debounce.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; @@ -133,8 +132,7 @@ class _DriftMapState extends ConsumerState { // When the AssetViewer is open, the DriftMap route stays alive in the background. // If we continue to update bounds, the map-scoped timeline service gets recreated and the previous one disposed, // which can invalidate the TimelineService instance that was passed into AssetViewerRoute (causing "loading forever"). - final currentRoute = ref.read(currentRouteNameProvider); - if (currentRoute == AssetViewerRoute.name) { + if (ref.read(isAssetViewerOpenProvider)) { return; } @@ -183,6 +181,11 @@ class _DriftMapState extends ConsumerState { @override Widget build(BuildContext context) { + ref.listen(isAssetViewerOpenProvider, (previous, current) { + if (previous == true && !current) { + _debouncer.run(() => setBounds(forceReload: true)); + } + }); return Stack( children: [ _Map(initialLocation: widget.initialLocation, onMapCreated: onMapCreated, onMapReady: onMapReady), diff --git a/mobile/lib/providers/routes.provider.dart b/mobile/lib/providers/routes.provider.dart index c51f67bc0e..a752a51a7d 100644 --- a/mobile/lib/providers/routes.provider.dart +++ b/mobile/lib/providers/routes.provider.dart @@ -2,6 +2,7 @@ import 'package:flutter/widgets.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; final inLockedViewProvider = StateProvider((ref) => false); +final isAssetViewerOpenProvider = StateProvider((ref) => false); final currentRouteNameProvider = StateProvider((ref) => null); final previousRouteNameProvider = StateProvider((ref) => null); final previousRouteDataProvider = StateProvider((ref) => null); diff --git a/mobile/lib/routing/app_navigation_observer.dart b/mobile/lib/routing/app_navigation_observer.dart index b6b08d7831..09d17da182 100644 --- a/mobile/lib/routing/app_navigation_observer.dart +++ b/mobile/lib/routing/app_navigation_observer.dart @@ -24,9 +24,20 @@ class AppNavigationObserver extends AutoRouterObserver { ref.read(currentRouteNameProvider.notifier).state = route.settings.name; ref.read(previousRouteNameProvider.notifier).state = previousRoute?.settings.name; ref.read(previousRouteDataProvider.notifier).state = previousRoute?.settings; + if (route.settings.name == AssetViewerRoute.name) { + ref.read(isAssetViewerOpenProvider.notifier).state = true; + } }); } + @override + void didPop(Route route, Route? previousRoute) { + _handleDriftLockedFolderState(previousRoute ?? route, null); + if (route.settings.name == AssetViewerRoute.name) { + Future(() => ref.read(isAssetViewerOpenProvider.notifier).state = false); + } + } + _handleDriftLockedFolderState(Route route, Route? previousRoute) { final isInLockedView = ref.read(inLockedViewProvider); final isFromLockedViewToDetailView =