import 'package:aves/app_mode.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/selection.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/viewer_service.dart'; import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/scaling.dart'; import 'package:aves/widgets/common/thumbnail/decorated.dart'; import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class InteractiveThumbnail extends StatelessWidget { final CollectionLens collection; final AvesEntry entry; final double tileExtent; final ValueNotifier? isScrollingNotifier; const InteractiveThumbnail({ Key? key, required this.collection, required this.entry, required this.tileExtent, this.isScrollingNotifier, }) : super(key: key); @override Widget build(BuildContext context) { return GestureDetector( key: ValueKey(entry.uri), onTap: () { final appMode = context.read>().value; switch (appMode) { case AppMode.main: final selection = context.read>(); if (selection.isSelecting) { selection.toggleSelection(entry); } else { _goToViewer(context); } break; case AppMode.pickExternal: ViewerService.pick(entry.uri); break; case AppMode.pickInternal: Navigator.pop(context, entry); break; case AppMode.view: break; } }, child: MetaData( metaData: ScalerMetadata(entry), child: DecoratedThumbnail( entry: entry, tileExtent: tileExtent, // when the user is scrolling faster than we can retrieve the thumbnails, // the retrieval task queue can pile up for thumbnails that got disposed // in this case we pause the image retrieval task to get it out of the queue cancellableNotifier: isScrollingNotifier, // hero tag should include a collection identifier, so that it animates // between different views of the entry in the same collection (e.g. thumbnails <-> viewer) // but not between different collection instances, even with the same attributes (e.g. reloading collection page via drawer) heroTagger: () => Object.hashAll([collection.id, entry.uri]), ), ), ); } void _goToViewer(BuildContext context) { Navigator.push( context, TransparentMaterialPageRoute( settings: const RouteSettings(name: EntryViewerPage.routeName), pageBuilder: (context, a, sa) { final viewerCollection = collection.copyWith( listenToSource: false, ); assert(viewerCollection.sortedEntries.map((e) => e.contentId).contains(entry.contentId)); return EntryViewerPage( collection: viewerCollection, initialEntry: entry, ); }, ), ); } }