From cee585d03ce3f9e79f1ff691013998d9a6353879 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 21 Dec 2019 00:29:14 +0900 Subject: [PATCH] fixed logo, applied pedantic, added startup timing TODOs --- analysis_options.yaml | 5 ++ assets/aves_logo.svg | 88 +------------------ lib/main.dart | 57 ++++++++---- lib/model/image_collection.dart | 30 +++---- lib/model/image_entry.dart | 10 +-- lib/model/image_file_service.dart | 6 +- lib/model/metadata_db.dart | 16 ++-- lib/model/metadata_service.dart | 2 +- lib/model/settings.dart | 12 +-- lib/utils/android_app_service.dart | 12 +-- lib/utils/android_file_utils.dart | 2 +- lib/utils/geo_utils.dart | 4 +- lib/widgets/common/app_icon.dart | 2 +- lib/widgets/common/icons.dart | 4 +- lib/widgets/common/image_preview.dart | 2 +- .../fullscreen_action_delegate.dart | 17 ++-- lib/widgets/fullscreen/overlay/video.dart | 22 ++--- pubspec.lock | 9 +- pubspec.yaml | 2 + 19 files changed, 125 insertions(+), 177 deletions(-) create mode 100644 analysis_options.yaml diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 000000000..f779f939d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:pedantic/analysis_options.yaml + +analyzer: + exclude: + - lib/generated_plugin_registrant.dart diff --git a/assets/aves_logo.svg b/assets/aves_logo.svg index 685a245e0..dc161703a 100644 --- a/assets/aves_logo.svg +++ b/assets/aves_logo.svg @@ -1,87 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index f3b849bcc..971c9fc62 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,14 +11,20 @@ import 'package:aves/widgets/common/icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_native_timezone/flutter_native_timezone.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:screen/screen.dart'; +final stopwatch = Stopwatch()..start(); + void main() { + debugPrint('main start, elapsed=${stopwatch.elapsed}'); // initialize binding/plugins to configure Skia before `runApp` - WidgetsFlutterBinding.ensureInitialized(); + WidgetsFlutterBinding.ensureInitialized(); // 220ms +// debugPrint('main WidgetsFlutterBinding.ensureInitialized done, elapsed=${stopwatch.elapsed}'); // configure Skia cache to prevent zoomed images becoming black, cf https://github.com/flutter/flutter/issues/36191 - SystemChannels.skia.invokeMethod('Skia.setResourceCacheMaxBytes', 512 * (1 << 20)); + SystemChannels.skia.invokeMethod('Skia.setResourceCacheMaxBytes', 512 * (1 << 20)); // <20ms +// debugPrint('main Skia.setResourceCacheMaxBytes done, elapsed=${stopwatch.elapsed}'); runApp(AvesApp()); } @@ -64,42 +70,55 @@ class _HomePageState extends State { Screen.keepOn(true); } - setup() async { - final permissions = await PermissionHandler().requestPermissions([PermissionGroup.storage]); + Future setup() async { + debugPrint('$runtimeType setup start, elapsed=${stopwatch.elapsed}'); + // TODO reduce permission check time + final permissions = await PermissionHandler().requestPermissions([PermissionGroup.storage]); // 350ms if (permissions[PermissionGroup.storage] != PermissionStatus.granted) { - SystemNavigator.pop(); + unawaited(SystemNavigator.pop()); return; } +// debugPrint('$runtimeType setup permission check done, elapsed=${stopwatch.elapsed}'); - await androidFileUtils.init(); - await IconUtils.init(); - await settings.init(); + androidFileUtils.init(); +// debugPrint('$runtimeType setup androidFileUtils.init done, elapsed=${stopwatch.elapsed}'); + // TODO notify when icons are ready for drawer and section header refresh + unawaited(IconUtils.init()); // 170ms +// debugPrint('$runtimeType setup IconUtils.init done, elapsed=${stopwatch.elapsed}'); + await settings.init(); // <20ms localMediaCollection.groupFactor = settings.collectionGroupFactor; localMediaCollection.sortFactor = settings.collectionSortFactor; + debugPrint('$runtimeType setup settings.init done, elapsed=${stopwatch.elapsed}'); - await metadataDb.init(); - final currentTimeZone = await FlutterNativeTimezone.getLocalTimezone(); + await metadataDb.init(); // <20ms + final currentTimeZone = await FlutterNativeTimezone.getLocalTimezone(); // <20ms final catalogTimeZone = settings.catalogTimeZone; if (currentTimeZone != catalogTimeZone) { // clear catalog metadata to get correct date/times when moving to a different time zone + debugPrint('$runtimeType clear catalog metadata to get correct date/times'); await metadataDb.clearMetadataEntries(); settings.catalogTimeZone = currentTimeZone; } +// debugPrint('$runtimeType setup metadataDb.init done, elapsed=${stopwatch.elapsed}'); eventChannel.receiveBroadcastStream().cast().listen( (entryMap) => localMediaCollection.add(ImageEntry.fromMap(entryMap)), onDone: () async { - debugPrint('mediastore stream done'); - localMediaCollection.updateSections(); - localMediaCollection.updateAlbums(); - await localMediaCollection.loadCatalogMetadata(); - await localMediaCollection.catalogEntries(); - await localMediaCollection.loadAddresses(); - await localMediaCollection.locateEntries(); + debugPrint('$runtimeType mediastore stream done, elapsed=${stopwatch.elapsed}'); + localMediaCollection.updateSections(); // <50ms + // TODO reduce setup time until here + localMediaCollection.updateAlbums(); // <50ms + await localMediaCollection.loadCatalogMetadata(); // 650ms + await localMediaCollection.catalogEntries(); // <50ms + await localMediaCollection.loadAddresses(); // 350ms + await localMediaCollection.locateEntries(); // <50ms + debugPrint('$runtimeType setup end, elapsed=${stopwatch.elapsed}'); }, - onError: (error) => debugPrint('mediastore stream error=$error'), + onError: (error) => debugPrint('$runtimeType mediastore stream error=$error'), ); - await ImageFileService.getImageEntries(); +// debugPrint('$runtimeType setup fetch images, elapsed=${stopwatch.elapsed}'); + // TODO split image fetch AND/OR cache fetch across sessions + await ImageFileService.getImageEntries(); // 460ms } @override diff --git a/lib/model/image_collection.dart b/lib/model/image_collection.dart index b393ec801..94fc46728 100644 --- a/lib/model/image_collection.dart +++ b/lib/model/image_collection.dart @@ -32,17 +32,17 @@ class ImageCollection with ChangeNotifier { List get sortedEntries => List.unmodifiable(sections.entries.expand((e) => e.value)); - sort(SortFactor sortFactor) { + void sort(SortFactor sortFactor) { this.sortFactor = sortFactor; updateSections(); } - group(GroupFactor groupFactor) { + void group(GroupFactor groupFactor) { this.groupFactor = groupFactor; updateSections(); } - updateSections() { + void updateSections() { _applySort(); switch (sortFactor) { case SortFactor.date: @@ -65,7 +65,7 @@ class ImageCollection with ChangeNotifier { notifyListeners(); } - _applySort() { + void _applySort() { switch (sortFactor) { case SortFactor.date: _rawEntries.sort((a, b) => b.bestDate.compareTo(a.bestDate)); @@ -76,7 +76,7 @@ class ImageCollection with ChangeNotifier { } } - add(ImageEntry entry) => _rawEntries.add(entry); + void add(ImageEntry entry) => _rawEntries.add(entry); Future delete(ImageEntry entry) async { final success = await ImageFileService.delete(entry); @@ -87,7 +87,7 @@ class ImageCollection with ChangeNotifier { return success; } - updateAlbums() { + void updateAlbums() { Set albums = _rawEntries.map((entry) => entry.directory).toSet(); List sorted = albums.toList() ..sort((a, b) { @@ -98,19 +98,19 @@ class ImageCollection with ChangeNotifier { sortedAlbums = List.unmodifiable(sorted); } - updateTags() { + void updateTags() { Set tags = _rawEntries.expand((entry) => entry.xmpSubjects).toSet(); List sorted = tags.toList()..sort(compareAsciiUpperCase); sortedTags = List.unmodifiable(sorted); } - onMetadataChanged() { + void onMetadataChanged() { // metadata dates impact sorting and grouping updateSections(); updateTags(); } - loadCatalogMetadata() async { + Future loadCatalogMetadata() async { final start = DateTime.now(); final saved = await metadataDb.loadMetadataEntries(); _rawEntries.forEach((entry) { @@ -123,7 +123,7 @@ class ImageCollection with ChangeNotifier { debugPrint('$runtimeType loadCatalogMetadata complete in ${DateTime.now().difference(start).inSeconds}s with ${saved.length} saved entries'); } - loadAddresses() async { + Future loadAddresses() async { final start = DateTime.now(); final saved = await metadataDb.loadAddresses(); _rawEntries.forEach((entry) { @@ -135,7 +135,7 @@ class ImageCollection with ChangeNotifier { debugPrint('$runtimeType loadAddresses complete in ${DateTime.now().difference(start).inSeconds}s with ${saved.length} saved entries'); } - catalogEntries() async { + Future catalogEntries() async { final start = DateTime.now(); final uncataloguedEntries = _rawEntries.where((entry) => !entry.isCatalogued).toList(); final newMetadata = List(); @@ -143,12 +143,12 @@ class ImageCollection with ChangeNotifier { await entry.catalog(); newMetadata.add(entry.catalogMetadata); }); - metadataDb.saveMetadata(List.unmodifiable(newMetadata)); + await metadataDb.saveMetadata(List.unmodifiable(newMetadata)); onMetadataChanged(); debugPrint('$runtimeType catalogEntries complete in ${DateTime.now().difference(start).inSeconds}s with ${newMetadata.length} new entries'); } - locateEntries() async { + Future locateEntries() async { final start = DateTime.now(); final unlocatedEntries = _rawEntries.where((entry) => entry.hasGps && !entry.isLocated).toList(); final newAddresses = List(); @@ -156,11 +156,11 @@ class ImageCollection with ChangeNotifier { await entry.locate(); newAddresses.add(entry.addressDetails); if (newAddresses.length >= 50) { - metadataDb.saveAddresses(List.unmodifiable(newAddresses)); + await metadataDb.saveAddresses(List.unmodifiable(newAddresses)); newAddresses.clear(); } }); - metadataDb.saveAddresses(List.unmodifiable(newAddresses)); + await metadataDb.saveAddresses(List.unmodifiable(newAddresses)); debugPrint('$runtimeType locateEntries complete in ${DateTime.now().difference(start).inSeconds}s'); } diff --git a/lib/model/image_entry.dart b/lib/model/image_entry.dart index 42b19408e..cab1688fd 100644 --- a/lib/model/image_entry.dart +++ b/lib/model/image_entry.dart @@ -30,7 +30,7 @@ class ImageEntry { CatalogMetadata catalogMetadata; AddressDetails addressDetails; - AChangeNotifier imageChangeNotifier = new AChangeNotifier(), metadataChangeNotifier = new AChangeNotifier(), addressChangeNotifier = new AChangeNotifier(); + final AChangeNotifier imageChangeNotifier = AChangeNotifier(), metadataChangeNotifier = AChangeNotifier(), addressChangeNotifier = AChangeNotifier(); ImageEntry({ this.uri, @@ -84,7 +84,7 @@ class ImageEntry { }; } - dispose() { + void dispose() { imageChangeNotifier.dispose(); metadataChangeNotifier.dispose(); addressChangeNotifier.dispose(); @@ -142,13 +142,13 @@ class ImageEntry { List get xmpSubjects => catalogMetadata?.xmpSubjects?.split(';')?.where((tag) => tag.isNotEmpty)?.toList() ?? []; - catalog() async { + Future catalog() async { if (isCatalogued) return; catalogMetadata = await MetadataService.getCatalogMetadata(this); metadataChangeNotifier.notifyListeners(); } - locate() async { + Future locate() async { if (isLocated) return; await catalog(); @@ -159,7 +159,7 @@ class ImageEntry { final coordinates = Coordinates(latitude, longitude); try { final addresses = await Geocoder.local.findAddressesFromCoordinates(coordinates); - if (addresses != null && addresses.length > 0) { + if (addresses != null && addresses.isNotEmpty) { final address = addresses.first; addressDetails = AddressDetails( contentId: contentId, diff --git a/lib/model/image_file_service.dart b/lib/model/image_file_service.dart index 7ced381ed..1da519c21 100644 --- a/lib/model/image_file_service.dart +++ b/lib/model/image_file_service.dart @@ -5,9 +5,9 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; class ImageFileService { - static const platform = const MethodChannel('deckers.thibault/aves/image'); + static const platform = MethodChannel('deckers.thibault/aves/image'); - static getImageEntries() async { + static Future getImageEntries() async { try { await platform.invokeMethod('getImageEntries'); } on PlatformException catch (e) { @@ -32,7 +32,7 @@ class ImageFileService { return Uint8List(0); } - static cancelGetImageBytes(String uri) async { + static Future cancelGetImageBytes(String uri) async { try { await platform.invokeMethod('cancelGetImageBytes', { 'uri': uri, diff --git a/lib/model/metadata_db.dart b/lib/model/metadata_db.dart index 6be79403f..0ad5a037a 100644 --- a/lib/model/metadata_db.dart +++ b/lib/model/metadata_db.dart @@ -15,7 +15,7 @@ class MetadataDb { MetadataDb._private(); - init() async { + Future init() async { debugPrint('$runtimeType init'); _database = openDatabase( await path, @@ -27,14 +27,14 @@ class MetadataDb { ); } - reset() async { + Future reset() async { debugPrint('$runtimeType reset'); - (await _database).close(); - deleteDatabase(await path); + await (await _database).close(); + await deleteDatabase(await path); await init(); } - clearMetadataEntries() async { + Future clearMetadataEntries() async { final db = await _database; final count = await db.delete(metadataTable, where: '1'); debugPrint('$runtimeType clearMetadataEntries deleted $count entries'); @@ -49,7 +49,7 @@ class MetadataDb { return metadataEntries; } - saveMetadata(Iterable metadataEntries) async { + Future saveMetadata(Iterable metadataEntries) async { if (metadataEntries == null || metadataEntries.isEmpty) return; final start = DateTime.now(); final db = await _database; @@ -63,7 +63,7 @@ class MetadataDb { debugPrint('$runtimeType saveMetadata complete in ${DateTime.now().difference(start).inMilliseconds}ms with ${metadataEntries.length} entries'); } - clearAddresses() async { + Future clearAddresses() async { final db = await _database; final count = await db.delete(addressTable, where: '1'); debugPrint('$runtimeType clearAddresses deleted $count entries'); @@ -78,7 +78,7 @@ class MetadataDb { return addresses; } - saveAddresses(Iterable addresses) async { + Future saveAddresses(Iterable addresses) async { if (addresses == null || addresses.isEmpty) return; final start = DateTime.now(); final db = await _database; diff --git a/lib/model/metadata_service.dart b/lib/model/metadata_service.dart index a08e179b3..883002049 100644 --- a/lib/model/metadata_service.dart +++ b/lib/model/metadata_service.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; class MetadataService { - static const platform = const MethodChannel('deckers.thibault/aves/metadata'); + static const platform = MethodChannel('deckers.thibault/aves/metadata'); // return Map> (map of directories, each directory being a map of metadata label and value description) static Future getAllMetadata(ImageEntry entry) async { diff --git a/lib/model/settings.dart b/lib/model/settings.dart index ab8b43a5d..785dec2b8 100644 --- a/lib/model/settings.dart +++ b/lib/model/settings.dart @@ -25,7 +25,7 @@ class Settings { // state static const windowMetricsKey = 'window_metrics'; - init() async { + Future init() async { prefs = await SharedPreferences.getInstance(); // TODO TLAD try this as an alternative to MediaQuery, in order to rebuild only on specific property change // window.onMetricsChanged = onMetricsChanged; @@ -33,7 +33,7 @@ class Settings { WindowMetrics _metrics; - onMetricsChanged() { + void onMetricsChanged() { final newValue = WindowMetrics( devicePixelRatio: window.devicePixelRatio, physicalSize: window.physicalSize, @@ -46,11 +46,11 @@ class Settings { _metrics = newValue; } - addListener(SettingsCallback listener) => _listeners.add(listener); + void addListener(SettingsCallback listener) => _listeners.add(listener); - removeListener(SettingsCallback listener) => _listeners.remove(listener); + void removeListener(SettingsCallback listener) => _listeners.remove(listener); - notifyListeners(String key, dynamic oldValue, dynamic newValue) { + void notifyListeners(String key, dynamic oldValue, dynamic newValue) { debugPrint('$runtimeType notifyListeners key=$key, old=$oldValue, new=$newValue'); if (_listeners != null) { final List localListeners = _listeners.toList(); @@ -96,7 +96,7 @@ class Settings { return defaultValue; } - setAndNotify(String key, dynamic newValue) { + void setAndNotify(String key, dynamic newValue) { var oldValue = prefs.get(key); if (newValue == null) { prefs.remove(key); diff --git a/lib/utils/android_app_service.dart b/lib/utils/android_app_service.dart index f8b313cd4..208a067b8 100644 --- a/lib/utils/android_app_service.dart +++ b/lib/utils/android_app_service.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; class AndroidAppService { - static const platform = const MethodChannel('deckers.thibault/aves/app'); + static const platform = MethodChannel('deckers.thibault/aves/app'); static Future getAppNames() async { try { @@ -29,7 +29,7 @@ class AndroidAppService { return Uint8List(0); } - static edit(String uri, String mimeType) async { + static Future edit(String uri, String mimeType) async { try { await platform.invokeMethod('edit', { 'title': 'Edit with:', @@ -41,7 +41,7 @@ class AndroidAppService { } } - static open(String uri, String mimeType) async { + static Future open(String uri, String mimeType) async { try { await platform.invokeMethod('open', { 'title': 'Open with:', @@ -53,7 +53,7 @@ class AndroidAppService { } } - static openMap(String geoUri) async { + static Future openMap(String geoUri) async { if (geoUri == null) return; try { await platform.invokeMethod('openMap', { @@ -64,7 +64,7 @@ class AndroidAppService { } } - static setAs(String uri, String mimeType) async { + static Future setAs(String uri, String mimeType) async { try { await platform.invokeMethod('setAs', { 'title': 'Set as:', @@ -76,7 +76,7 @@ class AndroidAppService { } } - static share(String uri, String mimeType) async { + static Future share(String uri, String mimeType) async { try { await platform.invokeMethod('share', { 'title': 'Share via:', diff --git a/lib/utils/android_file_utils.dart b/lib/utils/android_file_utils.dart index a24b94156..42ae6b896 100644 --- a/lib/utils/android_file_utils.dart +++ b/lib/utils/android_file_utils.dart @@ -7,7 +7,7 @@ class AndroidFileUtils { AndroidFileUtils._private(); - init() async { + void init() { // path_provider getExternalStorageDirectory() gives '/storage/emulated/0/Android/data/deckers.thibault.aves/files' externalStorage = '/storage/emulated/0'; dcimPath = join(externalStorage, 'DCIM'); diff --git a/lib/utils/geo_utils.dart b/lib/utils/geo_utils.dart index bc56793fe..0a98c2510 100644 --- a/lib/utils/geo_utils.dart +++ b/lib/utils/geo_utils.dart @@ -5,12 +5,12 @@ import 'package:tuple/tuple.dart'; // adapted from Mike Mitterer's dart-latlong library String _decimal2sexagesimal(final double dec) { - double _round(final double value, {final int decimals: 6}) => (value * math.pow(10, decimals)).round() / math.pow(10, decimals); + double _round(final double value, {final int decimals = 6}) => (value * math.pow(10, decimals)).round() / math.pow(10, decimals); List _split(final double value) { // NumberFormat is necessary to create digit after comma if the value // has no decimal point (only necessary for browser) - final List tmp = new NumberFormat('0.0#####').format(_round(value, decimals: 10)).split('.'); + final List tmp = NumberFormat('0.0#####').format(_round(value, decimals: 10)).split('.'); return [int.parse(tmp[0]).abs(), int.parse(tmp[1])]; } diff --git a/lib/widgets/common/app_icon.dart b/lib/widgets/common/app_icon.dart index 027139089..014a14be1 100644 --- a/lib/widgets/common/app_icon.dart +++ b/lib/widgets/common/app_icon.dart @@ -36,7 +36,7 @@ class AppIconState extends State { future: _byteLoader, builder: (futureContext, AsyncSnapshot snapshot) { final bytes = (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) ? snapshot.data : kTransparentImage; - return bytes.length > 0 + return bytes.isNotEmpty ? Image.memory( bytes, width: widget.size, diff --git a/lib/widgets/common/icons.dart b/lib/widgets/common/icons.dart index a1679cb44..80a960e1e 100644 --- a/lib/widgets/common/icons.dart +++ b/lib/widgets/common/icons.dart @@ -88,9 +88,9 @@ class OverlayIcon extends StatelessWidget { } class IconUtils { - static Map appNameMap; + static Map appNameMap = {}; - static init() async { + static Future init() async { appNameMap = await AndroidAppService.getAppNames(); } diff --git a/lib/widgets/common/image_preview.dart b/lib/widgets/common/image_preview.dart index 2a30fa5d6..6ce2374a2 100644 --- a/lib/widgets/common/image_preview.dart +++ b/lib/widgets/common/image_preview.dart @@ -66,7 +66,7 @@ class ImagePreviewState extends State { future: _byteLoader, builder: (futureContext, AsyncSnapshot snapshot) { final bytes = (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) ? snapshot.data : kTransparentImage; - return bytes.length > 0 ? widget.builder(bytes) : Icon(Icons.error); + return bytes.isNotEmpty ? widget.builder(bytes) : Icon(Icons.error); }); } } diff --git a/lib/widgets/fullscreen/fullscreen_action_delegate.dart b/lib/widgets/fullscreen/fullscreen_action_delegate.dart index 3400066c1..e0d9735b1 100644 --- a/lib/widgets/fullscreen/fullscreen_action_delegate.dart +++ b/lib/widgets/fullscreen/fullscreen_action_delegate.dart @@ -6,6 +6,7 @@ import 'package:aves/utils/android_app_service.dart'; import 'package:flushbar/flushbar.dart'; import 'package:flutter/material.dart'; import 'package:pdf/widgets.dart' as pdf; +import 'package:pedantic/pedantic.dart'; import 'package:printing/printing.dart'; enum FullscreenAction { delete, edit, info, open, openMap, print, rename, rotateCCW, rotateCW, setAs, share } @@ -19,7 +20,7 @@ class FullscreenActionDelegate { @required this.showInfo, }); - onActionSelected(BuildContext context, ImageEntry entry, FullscreenAction action) { + void onActionSelected(BuildContext context, ImageEntry entry, FullscreenAction action) { switch (action) { case FullscreenAction.delete: _showDeleteDialog(context, entry); @@ -57,7 +58,7 @@ class FullscreenActionDelegate { } } - _showFeedback(BuildContext context, String message) { + void _showFeedback(BuildContext context, String message) { Flushbar( message: message, margin: EdgeInsets.all(8), @@ -70,25 +71,25 @@ class FullscreenActionDelegate { )..show(context); } - _print(ImageEntry entry) async { + Future _print(ImageEntry entry) async { final doc = pdf.Document(title: entry.title); final image = await pdfImageFromImageProvider( pdf: doc.document, image: FileImage(File(entry.path)), ); doc.addPage(pdf.Page(build: (context) => pdf.Center(child: pdf.Image(image)))); // Page - Printing.layoutPdf( + unawaited(Printing.layoutPdf( onLayout: (format) => doc.save(), name: entry.title, - ); + )); } - _rotate(BuildContext context, ImageEntry entry, {@required bool clockwise}) async { + Future _rotate(BuildContext context, ImageEntry entry, {@required bool clockwise}) async { final success = await entry.rotate(clockwise: clockwise); _showFeedback(context, success ? 'Done!' : 'Failed'); } - _showDeleteDialog(BuildContext context, ImageEntry entry) async { + Future _showDeleteDialog(BuildContext context, ImageEntry entry) async { final confirmed = await showDialog( context: context, builder: (BuildContext context) { @@ -115,7 +116,7 @@ class FullscreenActionDelegate { } } - _showRenameDialog(BuildContext context, ImageEntry entry) async { + Future _showRenameDialog(BuildContext context, ImageEntry entry) async { final currentName = entry.title; final controller = TextEditingController(text: currentName); final newName = await showDialog( diff --git a/lib/widgets/fullscreen/overlay/video.dart b/lib/widgets/fullscreen/overlay/video.dart index 4a1f70a04..8d27c42cc 100644 --- a/lib/widgets/fullscreen/overlay/video.dart +++ b/lib/widgets/fullscreen/overlay/video.dart @@ -65,11 +65,11 @@ class VideoControlOverlayState extends State with SingleTic super.dispose(); } - registerWidget(VideoControlOverlay widget) { + void registerWidget(VideoControlOverlay widget) { widget.controller.addListener(_onValueChange); } - unregisterWidget(VideoControlOverlay widget) { + void unregisterWidget(VideoControlOverlay widget) { widget.controller.removeListener(_onValueChange); } @@ -108,8 +108,8 @@ class VideoControlOverlayState extends State with SingleTic icon: AnimatedIcons.play_pause, progress: _playPauseAnimation, ), - onPressed: () => _playPause(), - tooltip: 'Play', + onPressed: _playPause, + tooltip: value.isPlaying ? 'Pause' : 'Play', ), ), ], @@ -118,7 +118,7 @@ class VideoControlOverlayState extends State with SingleTic ); } - SizeTransition _buildProgressBar() { + Widget _buildProgressBar() { final progressBarBorderRadius = 123.0; return SizeTransition( sizeFactor: scale, @@ -166,22 +166,22 @@ class VideoControlOverlayState extends State with SingleTic ); } - _onValueChange() { + void _onValueChange() { setState(() {}); updatePlayPauseIcon(); } - _playPause() async { + Future _playPause() async { if (value.isPlaying) { - controller.pause(); + await controller.pause(); } else { if (!value.initialized) await controller.initialize(); - controller.play(); + await controller.play(); } setState(() {}); } - updatePlayPauseIcon() { + void updatePlayPauseIcon() { final isPlaying = value.isPlaying; final status = _playPauseAnimation.status; if (isPlaying && status != AnimationStatus.forward && status != AnimationStatus.completed) { @@ -191,7 +191,7 @@ class VideoControlOverlayState extends State with SingleTic } } - _seek(Offset globalPosition) { + void _seek(Offset globalPosition) { final keyContext = _progressBarKey.currentContext; final RenderBox box = keyContext.findRenderObject(); final localPosition = box.globalToLocal(globalPosition); diff --git a/pubspec.lock b/pubspec.lock index 104788c29..ac388c708 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -139,6 +139,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.16.0" + logger: + dependency: "direct main" + description: + name: logger + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.0" matcher: dependency: transitive description: @@ -182,7 +189,7 @@ packages: source: hosted version: "1.3.25" pedantic: - dependency: transitive + dependency: "direct main" description: name: pedantic url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index b36b69f59..bda0e43ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,8 +29,10 @@ dependencies: geocoder: google_maps_flutter: intl: + logger: path: pdf: + pedantic: permission_handler: photo_view: printing: