feat(mobile): scrollbar for album page (#25507)

This commit is contained in:
Alex 2026-01-25 12:43:49 -06:00 committed by GitHub
parent a244d94ac8
commit be0eef405d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 21 deletions

View file

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart'; import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
@ -17,16 +18,25 @@ class DriftAlbumsPage extends ConsumerStatefulWidget {
} }
class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> { class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> {
final ScrollController _scrollController = ScrollController();
Future<void> onRefresh() async { Future<void> onRefresh() async {
await ref.read(remoteAlbumProvider.notifier).refresh(); await ref.read(remoteAlbumProvider.notifier).refresh();
} }
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RefreshIndicator( final albumCount = ref.watch(remoteAlbumProvider.select((state) => state.albums.length));
onRefresh: onRefresh, final showScrollbar = albumCount > 10;
edgeOffset: 100,
child: CustomScrollView( final scrollView = CustomScrollView(
controller: _scrollController,
slivers: [ slivers: [
ImmichSliverAppBar( ImmichSliverAppBar(
snap: false, snap: false,
@ -46,7 +56,25 @@ class _DriftAlbumsPageState extends ConsumerState<DriftAlbumsPage> {
}, },
), ),
], ],
), );
return RefreshIndicator(
onRefresh: onRefresh,
edgeOffset: 100,
child: showScrollbar
? RawScrollbar(
controller: _scrollController,
interactive: true,
thickness: 8,
radius: const Radius.circular(4),
thumbVisibility: false,
thumbColor: context.colorScheme.primary,
crossAxisMargin: 4,
mainAxisMargin: 60,
minThumbLength: 40,
child: scrollView,
)
: scrollView,
); );
} }
} }

View file

@ -138,6 +138,10 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
.read(remoteAlbumProvider.notifier) .read(remoteAlbumProvider.notifier)
.sortAlbums(ref.read(remoteAlbumProvider).albums, sort.mode, isReverse: sort.isReverse); .sortAlbums(ref.read(remoteAlbumProvider).albums, sort.mode, isReverse: sort.isReverse);
if (!mounted) {
return;
}
setState(() { setState(() {
sortedAlbums = sorted; sortedAlbums = sorted;
}); });
@ -149,6 +153,10 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
Future<void> filterAlbums() async { Future<void> filterAlbums() async {
if (filter.query == null) { if (filter.query == null) {
if (!mounted) {
return;
}
setState(() { setState(() {
shownAlbums = sortedAlbums; shownAlbums = sortedAlbums;
}); });
@ -160,6 +168,10 @@ class _AlbumSelectorState extends ConsumerState<AlbumSelector> {
.read(remoteAlbumProvider.notifier) .read(remoteAlbumProvider.notifier)
.searchAlbums(sortedAlbums, filter.query!, filter.userId, filter.mode); .searchAlbums(sortedAlbums, filter.query!, filter.userId, filter.mode);
if (!mounted) {
return;
}
setState(() { setState(() {
shownAlbums = filteredAlbums; shownAlbums = filteredAlbums;
}); });