Cache photos to the left and right

This commit is contained in:
Vishnu Mohandas 2020-06-10 23:47:54 +05:30
parent a659fefa6d
commit 59dcc38ba5
6 changed files with 135 additions and 26 deletions

View file

@ -0,0 +1,7 @@
import 'package:photos/models/photo.dart';
class PhotoOpenedEvent {
final Photo photo;
PhotoOpenedEvent(this.photo);
}

View file

@ -1,8 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:like_button/like_button.dart';
import 'package:photos/core/event_bus.dart';
import 'package:photos/events/photo_opened_event.dart';
import 'package:photos/favorite_photos_repository.dart';
import 'package:photos/models/photo.dart';
import 'package:photos/ui/extents_page_view.dart';
import 'package:photos/ui/zoomable_image.dart';
import 'package:photos/utils/share_util.dart';
import 'package:logging/logging.dart';
@ -52,29 +55,35 @@ class _DetailPageState extends State<DetailPage> {
Widget _buildPageView() {
_pageController = PageController(initialPage: _selectedIndex);
return PageView.builder(
return ExtentsPageView.extents(
itemBuilder: (context, index) {
final photo = _photos[index];
final image = ZoomableImage(
photo,
shouldDisableScroll: (value) {
setState(() {
_shouldDisableScroll = value;
});
},
final image = Hero(
tag: photo.hashCode,
child: ZoomableImage(
photo,
shouldDisableScroll: (value) {
setState(() {
_shouldDisableScroll = value;
});
},
),
);
if (index == _selectedIndex) {
Bus.instance.fire(PhotoOpenedEvent(photo));
}
return image;
},
onPageChanged: (int index) {
setState(() {
_selectedIndex = index;
});
_selectedIndex = index;
Bus.instance.fire(PhotoOpenedEvent(widget.photos[index]));
},
physics: _shouldDisableScroll
? NeverScrollableScrollPhysics()
: PageScrollPhysics(),
controller: _pageController,
itemCount: _photos.length,
extents: 1,
);
}

View file

@ -1,8 +1,11 @@
import 'dart:async';
import 'dart:collection';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:photos/core/event_bus.dart';
import 'package:photos/events/photo_opened_event.dart';
import 'package:photos/models/photo.dart';
import 'package:photos/photo_sync_manager.dart';
import 'package:photos/ui/detail_page.dart';
@ -32,6 +35,24 @@ class _GalleryState extends State<Gallery> {
List<Photo> _photos;
RefreshController _refreshController =
RefreshController(initialRefresh: false);
StreamSubscription<PhotoOpenedEvent> _subscription;
Photo _openedPhoto;
@override
void initState() {
_subscription = Bus.instance.on<PhotoOpenedEvent>().listen((event) {
setState(() {
_openedPhoto = event.photo;
});
});
super.initState();
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
@ -127,10 +148,9 @@ class _GalleryState extends State<Gallery> {
? Border.all(width: 4.0, color: Colors.blue)
: null,
),
child: Hero(
tag: photo.hashCode,
child: ThumbnailWidget(photo),
),
child: photo == _openedPhoto
? Hero(tag: photo.hashCode, child: ThumbnailWidget(photo))
: ThumbnailWidget(photo),
),
);
}

View file

@ -1,3 +1,4 @@
import 'package:extended_image/extended_image.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:photos/core/cache/image_cache.dart';
@ -21,7 +22,8 @@ class ZoomableImage extends StatefulWidget {
_ZoomableImageState createState() => _ZoomableImageState();
}
class _ZoomableImageState extends State<ZoomableImage> {
class _ZoomableImageState extends State<ZoomableImage>
with SingleTickerProviderStateMixin {
ImageProvider _imageProvider;
bool _loadedSmallThumbnail = false;
bool _loadingLargeThumbnail = false;
@ -29,6 +31,10 @@ class _ZoomableImageState extends State<ZoomableImage> {
bool _loadingFinalImage = false;
bool _loadedFinalImage = false;
ValueChanged<PhotoViewScaleState> _scaleStateChangedCallback;
// AnimationController _animationController;
// Animation _animation;
// VoidCallback _animationListener;
final doubleTapScales = [1.0, 2.0];
@override
void initState() {
@ -37,6 +43,10 @@ class _ZoomableImageState extends State<ZoomableImage> {
widget.shouldDisableScroll(value != PhotoViewScaleState.initial);
}
};
// _animationController = AnimationController(
// vsync: this,
// duration: const Duration(milliseconds: 100),
// );
super.initState();
}
@ -49,12 +59,46 @@ class _ZoomableImageState extends State<ZoomableImage> {
}
if (_imageProvider != null) {
// return ExtendedImage(
// image: _imageProvider,
// gaplessPlayback: true,
// mode: ExtendedImageMode.gesture,
// enableSlideOutPage: true,
// initGestureConfigHandler: (state) {
// return GestureConfig(
// inPageView: true,
// initialScale: 1.0,
// minScale: 1.0,
// );
// },
// onDoubleTap: (ExtendedImageGestureState state) {
// var pointerDownPosition = state.pointerDownPosition;
// double begin = state.gestureDetails.totalScale;
// double end;
// _animation?.removeListener(_animationListener);
// _animationController.stop();
// _animationController.reset();
// if (begin == doubleTapScales[0]) {
// end = doubleTapScales[1];
// } else {
// end = doubleTapScales[0];
// }
// _animationListener = () {
// state.handleDoubleTap(
// scale: _animation.value,
// doubleTapPosition: pointerDownPosition);
// };
// _animation =
// _animationController.drive(Tween<double>(begin: begin, end: end));
// _animation.addListener(_animationListener);
// _animationController.forward();
// },
// );
return PhotoView(
imageProvider: _imageProvider,
scaleStateChangedCallback: _scaleStateChangedCallback,
minScale: PhotoViewComputedScale.contained,
gaplessPlayback: true,
heroAttributes: PhotoViewHeroAttributes(tag: widget.photo.hashCode),
);
} else {
return loadWidget;

View file

@ -36,6 +36,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.3"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
collection:
dependency: transitive
description:
@ -120,6 +127,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
extended_image:
dependency: "direct main"
description:
name: extended_image
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
extended_image_library:
dependency: transitive
description:
name: extended_image_library
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.3"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
flutter:
dependency: "direct main"
description: flutter
@ -191,6 +219,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.1"
http_client_helper:
dependency: transitive
description:
name: http_client_helper
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.1"
http_parser:
dependency: transitive
description:
@ -267,7 +302,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.4"
version: "1.7.0"
path_provider:
dependency: "direct main"
description:
@ -345,13 +380,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.8"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
sensors:
dependency: transitive
description:
@ -475,7 +503,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.15"
version: "0.2.16"
toast:
dependency: "direct main"
description:

View file

@ -50,6 +50,7 @@ dependencies:
flutter_typeahead: ^1.8.1
pull_to_refresh: ^1.5.7
fluttertoast: ^4.0.1
extended_image: ^0.9.0
dev_dependencies:
flutter_test: