From 05f792c4d265a9df83b5b223126a880a705a1ee0 Mon Sep 17 00:00:00 2001 From: Aryan Date: Sun, 16 Aug 2026 11:56:57 +0530 Subject: [PATCH] PAINTROID-723 Fix CircularProgressIndicator animation on landing page Cache the projects Future so FutureBuilder does not restart the indicator on every rebuild. Refresh after returning from Pocket Paint and when ProjectDatabase is invalidated. --- lib/ui/pages/landing_page/landing_page.dart | 20 ++++++++++++--- .../landing_page/landing_page_test.dart | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/ui/pages/landing_page/landing_page.dart b/lib/ui/pages/landing_page/landing_page.dart index 1c0ac34a..59860bfd 100644 --- a/lib/ui/pages/landing_page/landing_page.dart +++ b/lib/ui/pages/landing_page/landing_page.dart @@ -39,6 +39,8 @@ class _LandingPageState extends ConsumerState { late ProjectDatabase database; late IFileService fileService; late IImageService imageService; + Future>? _projectsFuture; + ProjectDatabase? _projectsLoadedFrom; @override void initState() { @@ -96,9 +98,15 @@ class _LandingPageState extends ConsumerState { return database.projectDAO.getProjects(); } + void _refreshProjectsFuture() { + _projectsFuture = _getProjects(); + } + Future _navigateToPocketPaint() async { await Navigator.pushNamed(context, '/PocketPaint'); - if (mounted){setState(() {});} + if (mounted) { + setState(_refreshProjectsFuture); + } } Future _loadProject(IOHandler ioHandler, Project project) async { @@ -141,7 +149,13 @@ class _LandingPageState extends ConsumerState { final db = ref.watch(ProjectDatabase.provider); db.when( - data: (value) => database = value, + data: (value) { + database = value; + if (!identical(_projectsLoadedFrom, value)) { + _projectsLoadedFrom = value; + _refreshProjectsFuture(); + } + }, error: (err, stacktrace) => ToastUtils.showShortToast(message: 'Error: $err'), loading: () {}, @@ -158,7 +172,7 @@ class _LandingPageState extends ConsumerState { actions: const [MainOverflowMenu()], ), body: FutureBuilder( - future: _getProjects(), + future: _projectsFuture, builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { diff --git a/test/widget/landing_page/landing_page_test.dart b/test/widget/landing_page/landing_page_test.dart index 68c5f244..07442f32 100644 --- a/test/widget/landing_page/landing_page_test.dart +++ b/test/widget/landing_page/landing_page_test.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; @@ -738,4 +739,28 @@ void main() { expect(find.byType(CircularProgressIndicator), findsOneWidget); }, ); + + testWidgets( + 'Should reuse the projects future across rebuilds while the list is loading', + (tester) async { + final projectsCompleter = Completer>(); + when(database.projectDAO).thenReturn(dao); + when(dao.getProjects()).thenAnswer((_) => projectsCompleter.future); + + await tester.pumpWidget(sut); + await tester.pump(); + + expect(find.byType(CircularProgressIndicator), findsWidgets); + + await tester.pump(); + await tester.pump(const Duration(milliseconds: 16)); + + expect(find.byType(CircularProgressIndicator), findsWidgets); + + projectsCompleter.complete([]); + await tester.pumpAndSettle(); + + verify(dao.getProjects()).called(1); + }, + ); }