import 'package:aves/app_mode.dart'; import 'package:aves/model/entry/entry.dart'; import 'package:aves/model/selection.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/intent_service.dart'; import 'package:aves/widgets/collection/grid/list_details.dart'; import 'package:aves/widgets/collection/grid/list_details_theme.dart'; import 'package:aves/widgets/common/grid/scaling.dart'; import 'package:aves/widgets/common/thumbnail/decorated.dart'; import 'package:aves/widgets/common/thumbnail/notifications.dart'; import 'package:aves/widgets/viewer/hero.dart'; import 'package:aves_model/aves_model.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class InteractiveTile extends StatelessWidget { final CollectionLens collection; final AvesEntry entry; final double thumbnailExtent; final TileLayout tileLayout; final ValueNotifier? isScrollingNotifier; const InteractiveTile({ super.key, required this.collection, required this.entry, required this.thumbnailExtent, required this.tileLayout, this.isScrollingNotifier, }); @override Widget build(BuildContext context) { return InkWell( onTap: () { final appMode = context.read>().value; switch (appMode) { case AppMode.main: final selection = context.read>(); if (selection.isSelecting) { selection.toggleSelection(entry); } else { OpenViewerNotification(entry).dispatch(context); } case AppMode.pickSingleMediaExternal: IntentService.submitPickedItems([entry.uri]); case AppMode.pickMultipleMediaExternal: final selection = context.read>(); selection.toggleSelection(entry); case AppMode.pickFilteredMediaInternal: case AppMode.pickUnfilteredMediaInternal: Navigator.maybeOf(context)?.pop(entry); default: break; } }, child: MetaData( metaData: ScalerMetadata(entry), child: Tile( entry: entry, thumbnailExtent: thumbnailExtent, tileLayout: tileLayout, selectable: true, highlightable: true, isScrollingNotifier: isScrollingNotifier, heroTagger: () => EntryHeroInfo(collection, entry).tag, ), ), ); } } class Tile extends StatelessWidget { final AvesEntry entry; final double thumbnailExtent; final TileLayout tileLayout; final bool selectable, highlightable; final ValueNotifier? isScrollingNotifier; final Object? Function()? heroTagger; const Tile({ super.key, required this.entry, required this.thumbnailExtent, required this.tileLayout, this.selectable = false, this.highlightable = false, this.isScrollingNotifier, this.heroTagger, }); @override Widget build(BuildContext context) { switch (tileLayout) { case TileLayout.mosaic: case TileLayout.grid: return _buildThumbnail(); case TileLayout.list: return Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SizedBox.square( dimension: context.select((v) => v.extent), child: _buildThumbnail(), ), Expanded( child: EntryListDetails( entry: entry, ), ), ], ); } } Widget _buildThumbnail() => DecoratedThumbnail( entry: entry, tileExtent: thumbnailExtent, isMosaic: tileLayout == TileLayout.mosaic, // 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, selectable: selectable, highlightable: highlightable, heroTagger: heroTagger, ); }