multipage: thumbnail request cancellation

This commit is contained in:
Thibault Deckers 2021-02-04 17:45:46 +09:00
parent ff517925f6
commit 8fa3f18aef
7 changed files with 35 additions and 16 deletions

View file

@ -172,6 +172,15 @@ class AvesEntry {
addressChangeNotifier.dispose();
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) return false;
return other is AvesEntry && other.uri == uri && other.pageId == pageId && other._dateModifiedSecs == _dateModifiedSecs;
}
@override
int get hashCode => hashValues(uri, pageId, _dateModifiedSecs);
@override
String toString() => '$runtimeType#${shortHash(this)}{uri=$uri, path=$path, pageId=$pageId}';

View file

@ -1,11 +1,13 @@
import 'package:flutter/foundation.dart';
class MultiPageInfo {
final String uri;
final List<SinglePageInfo> pages;
int get pageCount => pages.length;
MultiPageInfo({
@required this.uri,
this.pages,
}) {
if (pages.isNotEmpty) {
@ -18,8 +20,11 @@ class MultiPageInfo {
}
}
factory MultiPageInfo.fromPageMaps(List<Map> pageMaps) {
return MultiPageInfo(pages: pageMaps.map((page) => SinglePageInfo.fromMap(page)).toList());
factory MultiPageInfo.fromPageMaps(String uri, List<Map> pageMaps) {
return MultiPageInfo(
uri: uri,
pages: pageMaps.map((page) => SinglePageInfo.fromMap(page)).toList(),
);
}
SinglePageInfo get defaultPage => pages.firstWhere((page) => page.isDefault, orElse: () => null);
@ -29,7 +34,7 @@ class MultiPageInfo {
SinglePageInfo getById(int pageId) => pages.firstWhere((page) => page.pageId == pageId, orElse: () => null);
@override
String toString() => '$runtimeType#${shortHash(this)}{pages=$pages}';
String toString() => '$runtimeType#${shortHash(this)}{uri=$uri, pages=$pages}';
}
class SinglePageInfo implements Comparable<SinglePageInfo> {

View file

@ -89,7 +89,7 @@ class MetadataService {
'uri': entry.uri,
});
final pageMaps = (result as List).cast<Map>();
return MultiPageInfo.fromPageMaps(pageMaps);
return MultiPageInfo.fromPageMaps(entry.uri, pageMaps);
} on PlatformException catch (e) {
debugPrint('getMultiPageInfo failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}

View file

@ -43,7 +43,10 @@ class InteractiveThumbnail extends StatelessWidget {
entry: entry,
extent: tileExtent,
collection: collection,
isScrollingNotifier: isScrollingNotifier,
// 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,
),
),
);

View file

@ -9,7 +9,7 @@ class DecoratedThumbnail extends StatelessWidget {
final AvesEntry entry;
final double extent;
final CollectionLens collection;
final ValueNotifier<bool> isScrollingNotifier;
final ValueNotifier<bool> cancellableNotifier;
final bool selectable, highlightable;
static final Color borderColor = Colors.grey.shade700;
@ -20,7 +20,7 @@ class DecoratedThumbnail extends StatelessWidget {
@required this.entry,
@required this.extent,
this.collection,
this.isScrollingNotifier,
this.cancellableNotifier,
this.selectable = true,
this.highlightable = true,
}) : super(key: key);
@ -40,7 +40,7 @@ class DecoratedThumbnail extends StatelessWidget {
: RasterImageThumbnail(
entry: entry,
extent: extent,
isScrollingNotifier: isScrollingNotifier,
cancellableNotifier: cancellableNotifier,
heroTag: heroTag,
);

View file

@ -9,14 +9,14 @@ import 'package:flutter/material.dart';
class RasterImageThumbnail extends StatefulWidget {
final AvesEntry entry;
final double extent;
final ValueNotifier<bool> isScrollingNotifier;
final ValueNotifier<bool> cancellableNotifier;
final Object heroTag;
const RasterImageThumbnail({
Key key,
@required this.entry,
@required this.extent,
this.isScrollingNotifier,
this.cancellableNotifier,
this.heroTag,
}) : super(key: key);
@ -70,11 +70,7 @@ class _RasterImageThumbnailState extends State<RasterImageThumbnail> {
}
void _pauseProvider() {
final isScrolling = widget.isScrollingNotifier?.value ?? false;
// 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
if (isScrolling) {
if (widget.cancellableNotifier?.value ?? false) {
_fastThumbnailProvider?.pause();
_sizedThumbnailProvider?.pause();
}

View file

@ -27,6 +27,7 @@ class MultiPageOverlay extends StatefulWidget {
}
class _MultiPageOverlayState extends State<MultiPageOverlay> {
final _cancellableNotifier = ValueNotifier(true);
ScrollController _scrollController;
bool _syncScroll = true;
@ -90,7 +91,8 @@ class _MultiPageOverlayState extends State<MultiPageOverlay> {
future: controller.info,
builder: (context, snapshot) {
final multiPageInfo = snapshot.data;
if ((multiPageInfo?.pageCount ?? 0) <= 1) return SizedBox.shrink();
if ((multiPageInfo?.pageCount ?? 0) <= 1) return SizedBox();
if (multiPageInfo.uri != mainEntry.uri) return SizedBox();
return Container(
height: extent + separatorWidth * 2,
child: Stack(
@ -125,6 +127,10 @@ class _MultiPageOverlayState extends State<MultiPageOverlay> {
child: DecoratedThumbnail(
entry: pageEntry,
extent: extent,
// the retrieval task queue can pile up for thumbnails of heavy pages
// (e.g. thumbnails of 15MP HEIF images inside 100MB+ HEIC containers)
// so we cancel these requests when possible
cancellableNotifier: _cancellableNotifier,
selectable: false,
highlightable: false,
),