feat(mobile): map asset number (#28911)

* feat(mobile): map asset number

* chore: use totalAssets from service

* refactor: separate widget

* fix: async dispose

* chore: i18n

* chore: add back old i18n key

* bring back reactivity

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
Yaros
2026-08-26 05:59:27 +00:00
committed by GitHub
co-authored by shenlong-tanwen
parent dc688edb6f
commit 0f821a7338
2 changed files with 43 additions and 1 deletions
+1
View File
@@ -1393,6 +1393,7 @@
"manage_your_devices": "Manage your logged-in devices",
"manage_your_oauth_connection": "Manage your OAuth connection",
"map": "Map",
"map_assets_in_bounds": "{count, plural, =0 {No photos in this area} one {# photo} other {# photos}}",
"map_cannot_get_user_location": "Cannot get user's location",
"map_location_picker_page_use_location": "Use this location",
"map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?",
@@ -1,6 +1,11 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/events.model.dart';
import 'package:immich_mobile/domain/utils/event_stream.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
@@ -55,7 +60,43 @@ class _ScopedMapTimeline extends StatelessWidget {
return timelineService;
}),
],
child: const Timeline(appBar: null, bottomSheet: GeneralBottomSheet(minChildSize: 0.23), withScrubber: false),
child: const Column(
children: [
_MapAssetCount(),
Expanded(
child: Timeline(appBar: null, bottomSheet: GeneralBottomSheet(minChildSize: 0.23), withScrubber: false),
),
],
),
);
}
}
class _MapAssetCount extends ConsumerStatefulWidget {
const _MapAssetCount();
@override
ConsumerState<_MapAssetCount> createState() => _MapAssetCountState();
}
class _MapAssetCountState extends ConsumerState<_MapAssetCount> {
StreamSubscription? _reloadSubscription;
@override
void initState() {
super.initState();
_reloadSubscription = EventStream.shared.listen<TimelineReloadEvent>((_) => setState(() {}));
}
@override
void dispose() {
unawaited(_reloadSubscription?.cancel());
super.dispose();
}
@override
Widget build(BuildContext context) {
final count = ref.watch(timelineServiceProvider.select((s) => s.totalAssets));
return Text(context.t.map_assets_in_bounds(count: count), style: context.themeData.textTheme.headlineSmall);
}
}