From 1be8853e632063966afca89a7fd0490265a9d4dc Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 5 Jun 2020 15:51:08 +0900 Subject: [PATCH] app bar: show cataloguing/locating progress --- lib/main.dart | 2 +- lib/model/collection_source.dart | 2 +- lib/widgets/album/app_bar.dart | 106 ++++++++++++------ .../media_store_collection_provider.dart | 2 +- 4 files changed, 76 insertions(+), 36 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 0ff76ab3d..186c91360 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -116,7 +116,7 @@ class _HomePageState extends State { Future _initViewerEntry({@required String uri, @required String mimeType}) async { _viewerEntry = await ImageFileService.getImageEntry(uri, mimeType); - // cataloging is essential for geolocation and video rotation + // cataloguing is essential for geolocation and video rotation await _viewerEntry.catalog(); unawaited(_viewerEntry.locate()); } diff --git a/lib/model/collection_source.dart b/lib/model/collection_source.dart index 52b45ec30..2f275dd83 100644 --- a/lib/model/collection_source.dart +++ b/lib/model/collection_source.dart @@ -250,7 +250,7 @@ class CollectionSource { } } -enum SourceState { loading, cataloging, locating, ready } +enum SourceState { loading, cataloguing, locating, ready } class AddressMetadataChangedEvent {} diff --git a/lib/widgets/album/app_bar.dart b/lib/widgets/album/app_bar.dart index 4cd36a29e..62d868de3 100644 --- a/lib/widgets/album/app_bar.dart +++ b/lib/widgets/album/app_bar.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:aves/main.dart'; import 'package:aves/model/collection_lens.dart'; import 'package:aves/model/collection_source.dart'; +import 'package:aves/model/image_entry.dart'; import 'package:aves/model/settings.dart'; import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/album/filter_bar.dart'; @@ -135,23 +136,6 @@ class _CollectionAppBarState extends State with SingleTickerPr ValueListenableBuilder( valueListenable: collection.source.stateNotifier, builder: (context, sourceState, child) { - String subtitle; - switch (sourceState) { - case SourceState.loading: - subtitle = 'Loading'; - break; - case SourceState.cataloging: - subtitle = 'Cataloging'; - break; - case SourceState.locating: - subtitle = 'Locating'; - break; - case SourceState.ready: - default: - break; - } - final subtitleStyle = Theme.of(context).textTheme.caption; - final progressIndicatorSize = subtitleStyle.fontSize; return AnimatedSwitcher( duration: Duration(milliseconds: (300 * timeDilation).toInt()), transitionBuilder: (child, animation) => FadeTransition( @@ -161,23 +145,10 @@ class _CollectionAppBarState extends State with SingleTickerPr sizeFactor: animation, ), ), - child: subtitle == null + child: sourceState == SourceState.ready ? const SizedBox.shrink() - : Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.all(1), - width: progressIndicatorSize, - height: progressIndicatorSize, - margin: const EdgeInsetsDirectional.only(end: 8), - child: const CircularProgressIndicator(strokeWidth: 1), - ), - Text( - '$subtitle', - style: subtitleStyle, - ), - ], + : SourceStateSubtitle( + source: collection.source, ), ); }, @@ -387,3 +358,72 @@ class _CollectionAppBarState extends State with SingleTickerPr } enum CollectionAction { copy, move, select, selectAll, selectNone, stats, groupByAlbum, groupByMonth, groupByDay, sortByDate, sortBySize, sortByName } + +class SourceStateSubtitle extends StatefulWidget { + final CollectionSource source; + + const SourceStateSubtitle({@required this.source}); + + @override + _SourceStateSubtitleState createState() => _SourceStateSubtitleState(); +} + +class _SourceStateSubtitleState extends State { + Timer _progressTimer; + + CollectionSource get source => widget.source; + + SourceState get sourceState => source.stateNotifier.value; + + List get entries => source.entries; + + @override + void initState() { + super.initState(); + _progressTimer = Timer.periodic(const Duration(milliseconds: 1000), (timer) => setState(() {})); + } + + @override + void dispose() { + _progressTimer.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + String subtitle; + double progress; + switch (sourceState) { + case SourceState.loading: + subtitle = 'Loading'; + break; + case SourceState.cataloguing: + subtitle = 'Cataloguing'; + progress = entries.where((entry) => entry.isCatalogued).length.toDouble() / entries.length; + break; + case SourceState.locating: + subtitle = 'Locating'; + progress = entries.where((entry) => entry.isLocated).length.toDouble() / entries.length; + break; + case SourceState.ready: + default: + break; + } + final subtitleStyle = Theme.of(context).textTheme.caption; + return subtitle == null + ? const SizedBox.shrink() + : Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(subtitle, style: subtitleStyle), + if (progress != null && progress > 0) ...[ + const SizedBox(width: 8), + Text( + NumberFormat.percentPattern().format(progress), + style: subtitleStyle.copyWith(color: Colors.white30), + ), + ] + ], + ); + } +} diff --git a/lib/widgets/common/data_providers/media_store_collection_provider.dart b/lib/widgets/common/data_providers/media_store_collection_provider.dart index c90e1c119..6ab7007e3 100644 --- a/lib/widgets/common/data_providers/media_store_collection_provider.dart +++ b/lib/widgets/common/data_providers/media_store_collection_provider.dart @@ -49,7 +49,7 @@ class MediaStoreSource { source.addAll(allEntries); // TODO reduce setup time until here source.updateAlbums(); // <50ms - source.stateNotifier.value = SourceState.cataloging; + source.stateNotifier.value = SourceState.cataloguing; await source.loadCatalogMetadata(); // 400ms for 5400 entries await source.catalogEntries(); // <50ms source.stateNotifier.value = SourceState.locating;