From e959827cdb5cf20329dfe76831b457c34fc0cf00 Mon Sep 17 00:00:00 2001 From: kilowatt Date: Thu, 22 Oct 2020 21:27:09 +0300 Subject: [PATCH 1/3] Open scalable album art on tap --- lib/api/player.dart | 2 +- lib/ui/player_screen.dart | 44 +++++++++++++++++++++++++++++++++++---- pubspec.lock | 7 +++++++ pubspec.yaml | 1 + 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/lib/api/player.dart b/lib/api/player.dart index 6f4ef4f..6c73d26 100644 --- a/lib/api/player.dart +++ b/lib/api/player.dart @@ -29,7 +29,7 @@ class PlayerHelper { QueueSource queueSource; LoopMode repeatType = LoopMode.off; //Find queue index by id - int get queueIndex => AudioService.queue.indexWhere((mi) => mi.id == AudioService.currentMediaItem?.id??'Random string so it returns -1'); + int get queueIndex => AudioService.queue == null ? 0 : AudioService.queue.indexWhere((mi) => mi.id == AudioService.currentMediaItem?.id??'Random string so it returns -1'); Future start() async { //Subscribe to custom events diff --git a/lib/ui/player_screen.dart b/lib/ui/player_screen.dart index 53e16fb..ce8cb3b 100644 --- a/lib/ui/player_screen.dart +++ b/lib/ui/player_screen.dart @@ -1,3 +1,4 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:audio_service/audio_service.dart'; import 'package:flutter/services.dart'; @@ -14,6 +15,7 @@ import 'package:freezer/ui/tiles.dart'; import 'package:async/async.dart'; import 'package:just_audio/just_audio.dart'; import 'package:marquee/marquee.dart'; +import 'package:photo_view/photo_view.dart'; import 'cached_image.dart'; import '../api/definitions.dart'; @@ -429,6 +431,8 @@ class _BigAlbumArtState extends State { ); StreamSubscription _currentItemSub; bool _animationLock = true; + PhotoViewController controller; + bool photoViewOpened = false; @override void initState() { @@ -438,6 +442,8 @@ class _BigAlbumArtState extends State { _animationLock = false; }); super.initState(); + controller = PhotoViewController() + ..outputStateStream.listen(listener); } @override @@ -447,6 +453,14 @@ class _BigAlbumArtState extends State { super.dispose(); } + // Listener of PhotoView scale changes. Used for closing PhotoView by pinch-in + void listener(PhotoViewControllerValue value){ + if (value.scale < 0.16 && photoViewOpened) { + Navigator.pop(context); + photoViewOpened = false; // to avoid multiple pop() when picture are being scaled out too slowly + } + } + @override Widget build(BuildContext context) { return GestureDetector( @@ -461,10 +475,32 @@ class _BigAlbumArtState extends State { if (_animationLock) return; AudioService.skipToQueueItem(AudioService.queue[index].id); }, - children: List.generate(AudioService.queue.length, (i) => CachedImage( - url: AudioService.queue[i].artUri, - fullThumb: true, - )), + children: List.generate(AudioService.queue.length, (i) { + String artUri = AudioService.queue[i].artUri; + return FlatButton( + child: CachedImage( + url: artUri, + fullThumb: true, + ), + onPressed: () { + Navigator.of(context).push(PageRouteBuilder( + opaque: false, // transparent background + pageBuilder: (context, a, b) { + if (AudioService.queue != null) { + photoViewOpened = true; + return PhotoView( + imageProvider: CachedNetworkImageProvider(artUri), + maxScale: 8.0, + minScale: 0.2, + controller: controller, + backgroundDecoration: BoxDecoration( + color: Color.fromARGB(0x90, 0, 0, 0))); + } else { + return null; + } + })); + }); + }), ), ); } diff --git a/pubspec.lock b/pubspec.lock index 4fd6485..bdfe5b6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -651,6 +651,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + photo_view: + dependency: "direct main" + description: + name: photo_view + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.2" platform: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a3794fc..e6a6ad5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,6 +69,7 @@ dependencies: share: ^0.6.5+2 numberpicker: ^1.2.1 quick_actions: ^0.4.0+10 + photo_view: audio_session: ^0.0.9 audio_service: From bdada4654171b14e7e5bd7ee26f9cad0b5d811ea Mon Sep 17 00:00:00 2001 From: kilowatt Date: Fri, 23 Oct 2020 00:24:30 +0300 Subject: [PATCH 2/3] Extract ZoomableImage to separate class; add it for artist page --- lib/ui/cached_image.dart | 59 +++++++++++++++++++++++++++++++++++++ lib/ui/details_screens.dart | 3 +- lib/ui/player_screen.dart | 41 +------------------------- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/lib/ui/cached_image.dart b/lib/ui/cached_image.dart index 20571a2..b48ba49 100644 --- a/lib/ui/cached_image.dart +++ b/lib/ui/cached_image.dart @@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:palette_generator/palette_generator.dart'; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:photo_view/photo_view.dart'; ImagesDatabase imagesDatabase = ImagesDatabase(); @@ -78,3 +79,61 @@ class _CachedImageState extends State { ); } } + +class ZoomableImage extends StatefulWidget { + final String url; + final bool rounded; + final double width; + + ZoomableImage({@required this.url, this.rounded = false, this.width}); + + @override + _ZoomableImageState createState() => _ZoomableImageState(); +} + +class _ZoomableImageState extends State { + BuildContext ctx; + PhotoViewController controller; + bool photoViewOpened = false; + + @override + void initState() { + super.initState(); + controller = PhotoViewController() + ..outputStateStream.listen(listener); + } + + // Listener of PhotoView scale changes. Used for closing PhotoView by pinch-in + void listener(PhotoViewControllerValue value) { + if (value.scale < 0.16 && photoViewOpened) { + Navigator.pop(ctx); + photoViewOpened = false; // to avoid multiple pop() when picture are being scaled out too slowly + } + } + + @override + Widget build(BuildContext context) { + ctx = context; + return FlatButton( + child: CachedImage( + url: widget.url, + rounded: widget.rounded, + width: widget.width, + fullThumb: true, + ), + onPressed: () { + Navigator.of(context).push(PageRouteBuilder( + opaque: false, // transparent background + pageBuilder: (context, a, b) { + photoViewOpened = true; + return PhotoView( + imageProvider: CachedNetworkImageProvider(widget.url), + maxScale: 8.0, + minScale: 0.2, + controller: controller, + backgroundDecoration: + BoxDecoration(color: Color.fromARGB(0x90, 0, 0, 0))); + })); + }); + } +} \ No newline at end of file diff --git a/lib/ui/details_screens.dart b/lib/ui/details_screens.dart index 3de835d..c7212d9 100644 --- a/lib/ui/details_screens.dart +++ b/lib/ui/details_screens.dart @@ -303,11 +303,10 @@ class ArtistDetails extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - CachedImage( + ZoomableImage( url: artist.picture.full, width: MediaQuery.of(context).size.width / 2 - 8, rounded: true, - fullThumb: true, ), Container( width: MediaQuery.of(context).size.width / 2 - 8, diff --git a/lib/ui/player_screen.dart b/lib/ui/player_screen.dart index ce8cb3b..7050bae 100644 --- a/lib/ui/player_screen.dart +++ b/lib/ui/player_screen.dart @@ -1,4 +1,3 @@ -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:audio_service/audio_service.dart'; import 'package:flutter/services.dart'; @@ -15,7 +14,6 @@ import 'package:freezer/ui/tiles.dart'; import 'package:async/async.dart'; import 'package:just_audio/just_audio.dart'; import 'package:marquee/marquee.dart'; -import 'package:photo_view/photo_view.dart'; import 'cached_image.dart'; import '../api/definitions.dart'; @@ -431,8 +429,6 @@ class _BigAlbumArtState extends State { ); StreamSubscription _currentItemSub; bool _animationLock = true; - PhotoViewController controller; - bool photoViewOpened = false; @override void initState() { @@ -442,8 +438,6 @@ class _BigAlbumArtState extends State { _animationLock = false; }); super.initState(); - controller = PhotoViewController() - ..outputStateStream.listen(listener); } @override @@ -453,14 +447,6 @@ class _BigAlbumArtState extends State { super.dispose(); } - // Listener of PhotoView scale changes. Used for closing PhotoView by pinch-in - void listener(PhotoViewControllerValue value){ - if (value.scale < 0.16 && photoViewOpened) { - Navigator.pop(context); - photoViewOpened = false; // to avoid multiple pop() when picture are being scaled out too slowly - } - } - @override Widget build(BuildContext context) { return GestureDetector( @@ -475,32 +461,7 @@ class _BigAlbumArtState extends State { if (_animationLock) return; AudioService.skipToQueueItem(AudioService.queue[index].id); }, - children: List.generate(AudioService.queue.length, (i) { - String artUri = AudioService.queue[i].artUri; - return FlatButton( - child: CachedImage( - url: artUri, - fullThumb: true, - ), - onPressed: () { - Navigator.of(context).push(PageRouteBuilder( - opaque: false, // transparent background - pageBuilder: (context, a, b) { - if (AudioService.queue != null) { - photoViewOpened = true; - return PhotoView( - imageProvider: CachedNetworkImageProvider(artUri), - maxScale: 8.0, - minScale: 0.2, - controller: controller, - backgroundDecoration: BoxDecoration( - color: Color.fromARGB(0x90, 0, 0, 0))); - } else { - return null; - } - })); - }); - }), + children: List.generate(AudioService.queue.length, (i) => ZoomableImage(url: AudioService.queue[i].artUri)), ), ); } From bf5a145e9a1aa75c189e840c12ccf5454270144b Mon Sep 17 00:00:00 2001 From: kilowatt Date: Fri, 23 Oct 2020 21:57:20 +0300 Subject: [PATCH 3/3] Use ZoomableImage in album page --- lib/ui/details_screens.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ui/details_screens.dart b/lib/ui/details_screens.dart index c7212d9..4748515 100644 --- a/lib/ui/details_screens.dart +++ b/lib/ui/details_screens.dart @@ -60,10 +60,9 @@ class AlbumDetails extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Container(height: 8.0,), - CachedImage( + ZoomableImage( url: album.art.full, width: MediaQuery.of(context).size.width / 2, - fullThumb: true, rounded: true, ), Container(height: 8,),