collection: prevent hero when navigating from drawer

This commit is contained in:
Thibault Deckers 2021-02-03 13:00:43 +09:00
parent 104373a186
commit accfb2c57b
8 changed files with 37 additions and 21 deletions

View file

@ -21,6 +21,7 @@ class CollectionLens with ChangeNotifier, CollectionActivityMixin, CollectionSel
EntryGroupFactor groupFactor;
EntrySortFactor sortFactor;
final AChangeNotifier filterChangeNotifier = AChangeNotifier();
int id;
bool listenToSource;
List<AvesEntry> _filteredEntries;
@ -33,10 +34,12 @@ class CollectionLens with ChangeNotifier, CollectionActivityMixin, CollectionSel
Iterable<CollectionFilter> filters,
@required EntryGroupFactor groupFactor,
@required EntrySortFactor sortFactor,
this.id,
this.listenToSource = true,
}) : filters = {if (filters != null) ...filters.where((f) => f != null)},
groupFactor = groupFactor ?? EntryGroupFactor.month,
sortFactor = sortFactor ?? EntrySortFactor.date {
id ??= hashCode;
if (listenToSource) {
_subscriptions.add(source.eventBus.on<EntryAddedEvent>().listen((e) => _refresh()));
_subscriptions.add(source.eventBus.on<EntryRemovedEvent>().listen((e) => onEntryRemoved(e.entries)));

View file

@ -54,16 +54,20 @@ class InteractiveThumbnail extends StatelessWidget {
context,
TransparentMaterialPageRoute(
settings: RouteSettings(name: EntryViewerPage.routeName),
pageBuilder: (c, a, sa) => EntryViewerPage(
collection: CollectionLens(
pageBuilder: (c, a, sa) {
final viewerCollection = CollectionLens(
source: collection.source,
filters: collection.filters,
groupFactor: collection.groupFactor,
sortFactor: collection.sortFactor,
id: collection.id,
listenToSource: false,
),
);
return EntryViewerPage(
collection: viewerCollection,
initialEntry: entry,
),
);
},
),
);
}

View file

@ -27,17 +27,21 @@ class DecoratedThumbnail extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 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)
final heroTag = hashValues(collection?.id, entry);
var child = entry.isSvg
? VectorImageThumbnail(
entry: entry,
extent: extent,
canHero: true,
heroTag: heroTag,
)
: RasterImageThumbnail(
entry: entry,
extent: extent,
isScrollingNotifier: isScrollingNotifier,
canHero: true,
heroTag: heroTag,
);
child = Stack(

View file

@ -10,14 +10,14 @@ class RasterImageThumbnail extends StatefulWidget {
final AvesEntry entry;
final double extent;
final ValueNotifier<bool> isScrollingNotifier;
final bool canHero;
final Object heroTag;
const RasterImageThumbnail({
Key key,
@required this.entry,
@required this.extent,
this.isScrollingNotifier,
this.canHero = false,
this.heroTag,
}) : super(key: key);
@override
@ -124,9 +124,9 @@ class _RasterImageThumbnailState extends State<RasterImageThumbnail> {
height: extent,
fit: BoxFit.cover,
);
return widget.canHero
return widget.heroTag != null
? Hero(
tag: entry,
tag: widget.heroTag,
flightShuttleBuilder: (flight, animation, direction, fromHero, toHero) {
return TransitionImage(
image: entry.getBestThumbnail(extent),

View file

@ -10,13 +10,13 @@ import 'package:provider/provider.dart';
class VectorImageThumbnail extends StatelessWidget {
final AvesEntry entry;
final double extent;
final bool canHero;
final Object heroTag;
const VectorImageThumbnail({
Key key,
@required this.entry,
@required this.extent,
this.canHero = false,
this.heroTag,
}) : super(key: key);
@override
@ -63,9 +63,9 @@ class VectorImageThumbnail extends StatelessWidget {
);
},
);
return canHero
return heroTag != null
? Hero(
tag: entry,
tag: heroTag,
transitionOnUserGestures: true,
child: child,
)

View file

@ -77,7 +77,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with SingleTickerPr
super.initState();
final entry = widget.initialEntry;
// opening hero, with viewer as target
_heroInfoNotifier.value = HeroInfo(entry);
_heroInfoNotifier.value = HeroInfo(collection?.id, entry);
_entryNotifier.value = entry;
_currentHorizontalPage = max(0, entries.indexOf(entry));
_currentVerticalPage = ValueNotifier(imagePage);
@ -421,7 +421,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with SingleTickerPr
}
// closing hero, with viewer as source
final heroInfo = HeroInfo(_entryNotifier.value);
final heroInfo = HeroInfo(collection?.id, _entryNotifier.value);
if (_heroInfoNotifier.value != heroInfo) {
_heroInfoNotifier.value = heroInfo;
// we post closing the viewer page so that hero animation source is ready

View file

@ -1,16 +1,21 @@
import 'package:aves/model/entry.dart';
import 'package:flutter/widgets.dart';
class HeroInfo {
// 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)
final int collectionId;
final AvesEntry entry;
const HeroInfo(this.entry);
const HeroInfo(this.collectionId, this.entry);
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) return false;
return other is HeroInfo && other.entry == entry;
return other is HeroInfo && other.collectionId == collectionId && other.entry == entry;
}
@override
int get hashCode => entry.hashCode;
int get hashCode => hashValues(collectionId, entry);
}

View file

@ -145,7 +145,7 @@ class _EntryPageViewState extends State<EntryPageView> {
return Consumer<HeroInfo>(
builder: (context, info, child) => Hero(
tag: info?.entry == mainEntry ? mainEntry : hashCode,
tag: info?.entry == mainEntry ? hashValues(info.collectionId, mainEntry) : hashCode,
transitionOnUserGestures: true,
child: child,
),