11import 'dart:convert' ;
22import 'dart:io' ;
33
4+ import 'package:auto_size_text/auto_size_text.dart' ;
45import 'package:flutter/material.dart' ;
56import 'package:flutter/services.dart' ;
67import 'package:html_unescape/html_unescape.dart' ;
@@ -268,6 +269,20 @@ class _ImagePageState extends State<ImagePage> {
268269 });
269270 }
270271
272+ void _onPreviousPage () {
273+ _pageController.previousPage (
274+ duration: const Duration (milliseconds: 500 ),
275+ curve: Curves .ease,
276+ );
277+ }
278+
279+ void _onNextPage () {
280+ _pageController.nextPage (
281+ duration: const Duration (milliseconds: 500 ),
282+ curve: Curves .ease,
283+ );
284+ }
285+
271286 @override
272287 Widget build (BuildContext context) {
273288 return WillPopScope (
@@ -311,66 +326,82 @@ class _ImagePageState extends State<ImagePage> {
311326 curve: _overlayAnimationCurve,
312327 opacity: _showOverlay ? 1 : 0 ,
313328 child: Container (
314- height: 56.0 ,
315- decoration: BoxDecoration (color: Colors .black.withOpacity (0.5 )),
316- child: Row (
329+ decoration: BoxDecoration (
330+ color: Colors .black.withOpacity (0.5 ),
331+ ),
332+ child: Column (
317333 children: [
318- IconButton (
319- onPressed: () => Navigator .of (context).pop (_imageList),
320- icon: Icon (Icons .arrow_back),
321- ),
322- Expanded (
323- child: Text (
324- '${_currentImage .name }' ,
325- softWrap: true ,
326- maxLines: 2 ,
327- overflow: TextOverflow .ellipsis,
328- style: TextStyle (fontSize: 16 , color: Colors .white),
329- ),
330- ),
331- if (MediaQuery .of (context).orientation == Orientation .landscape)
332- ..._actions,
333- if (widget.isAdmin)
334- PopupMenuButton (
335- position: PopupMenuPosition .under,
336- itemBuilder: (context) => [
337- PopupMenuItem (
338- onTap: () => Future .delayed (
339- const Duration (seconds: 0 ),
340- () => share ([_currentImage]),
341- ),
342- child: PopupListItem (
343- icon: Icons .share,
344- text: appStrings.imageOptions_share,
345- ),
334+ SizedBox (
335+ height: 56.0 ,
336+ child: Row (
337+ children: [
338+ IconButton (
339+ onPressed: () => Navigator .of (context).pop (_imageList),
340+ icon: Icon (Icons .arrow_back),
346341 ),
347- if (Preferences .getUserStatus != 'guest' )
348- PopupMenuItem (
349- onTap: () => Future .delayed (
350- const Duration (seconds: 0 ),
351- _onLike,
352- ),
353- child: PopupListItem (
354- icon: ! _currentImage.favorite
355- ? Icons .favorite_border
356- : Icons .favorite,
357- text: ! _currentImage.favorite
358- ? appStrings.imageOptions_addFavorites
359- : appStrings.imageOptions_removeFavorites,
360- ),
361- ),
362- PopupMenuItem (
363- onTap: () => Future .delayed (
364- const Duration (seconds: 0 ),
365- () => downloadImages ([_currentImage]),
366- ),
367- child: PopupListItem (
368- icon: Icons .download,
369- text: appStrings.downloadImage_title (1 ),
342+ Expanded (
343+ child: AutoSizeText (
344+ '${_currentImage .name }' ,
345+ softWrap: true ,
346+ maxLines: 1 ,
347+ maxFontSize: 16.0 ,
348+ minFontSize: 10.0 ,
349+ overflow: TextOverflow .ellipsis,
350+ style: TextStyle (fontSize: 16.0 , color: Colors .white),
370351 ),
371352 ),
353+ if (MediaQuery .of (context).orientation ==
354+ Orientation .landscape)
355+ ..._actions,
356+ if (widget.isAdmin)
357+ PopupMenuButton (
358+ position: PopupMenuPosition .under,
359+ itemBuilder: (context) => [
360+ PopupMenuItem (
361+ onTap: () => Future .delayed (
362+ const Duration (seconds: 0 ),
363+ () => share ([_currentImage]),
364+ ),
365+ child: PopupListItem (
366+ icon: Icons .share,
367+ text: appStrings.imageOptions_share,
368+ ),
369+ ),
370+ if (Preferences .getUserStatus != 'guest' )
371+ PopupMenuItem (
372+ onTap: () => Future .delayed (
373+ const Duration (seconds: 0 ),
374+ _onLike,
375+ ),
376+ child: PopupListItem (
377+ icon: ! _currentImage.favorite
378+ ? Icons .favorite_border
379+ : Icons .favorite,
380+ text: ! _currentImage.favorite
381+ ? appStrings.imageOptions_addFavorites
382+ : appStrings.imageOptions_removeFavorites,
383+ ),
384+ ),
385+ PopupMenuItem (
386+ onTap: () => Future .delayed (
387+ const Duration (seconds: 0 ),
388+ () => downloadImages ([_currentImage]),
389+ ),
390+ child: PopupListItem (
391+ icon: Icons .download,
392+ text: appStrings.downloadImage_title (1 ),
393+ ),
394+ ),
395+ ],
396+ ),
372397 ],
373398 ),
399+ ),
400+ AnimatedSize (
401+ duration: _overlayAnimationDuration,
402+ curve: _overlayAnimationCurve,
403+ child: _tags,
404+ ),
374405 ],
375406 ),
376407 ),
@@ -382,7 +413,7 @@ class _ImagePageState extends State<ImagePage> {
382413 /// Image tags
383414 Widget get _tags {
384415 List <TagModel > tags = _currentImage.tags;
385- if (tags.isEmpty) return const SizedBox ();
416+ if (tags.isEmpty) return const SizedBox (width : double .infinity );
386417 return SizedBox (
387418 height: 36.0 ,
388419 child: Center (
@@ -544,40 +575,73 @@ class _ImagePageState extends State<ImagePage> {
544575 duration: _overlayAnimationDuration,
545576 curve: _overlayAnimationCurve,
546577 opacity: _showOverlay ? 1 : 0 ,
547- child: OrientationBuilder (builder: (context, orientation) {
548- return Column (
549- children: [
550- _comment,
551- Container (
552- decoration: BoxDecoration (
553- color: Colors .black.withOpacity (0.5 ),
554- ),
555- child: AnimatedSize (
556- duration: _overlayAnimationDuration,
557- curve: _overlayAnimationCurve,
558- child: _tags,
559- ),
578+ child: Column (
579+ children: [
580+ _comment,
581+ Container (
582+ decoration: BoxDecoration (
583+ color: Colors .black.withOpacity (0.5 ),
560584 ),
561- if (MediaQuery .of (context).orientation == Orientation .portrait)
562- Container (
563- height: 56.0 ,
564- decoration: BoxDecoration (
565- color: Colors .black.withOpacity (0.5 ),
566- ),
567- child: Row (
568- children: _actions
569- .map ((action) => Expanded (child: action))
570- .toList (),
571- ),
572- ),
573- ],
574- );
575- }),
585+ child: AnimatedSize (
586+ duration: _overlayAnimationDuration,
587+ curve: _overlayAnimationCurve,
588+ child: OrientationBuilder (builder: (context, orientation) {
589+ return Column (
590+ crossAxisAlignment: CrossAxisAlignment .stretch,
591+ children: [
592+ _pagination,
593+ if (MediaQuery .of (context).orientation ==
594+ Orientation .portrait)
595+ SizedBox (
596+ height: 56.0 ,
597+ child: Row (
598+ children: _actions
599+ .map ((action) => Expanded (child: action))
600+ .toList (),
601+ ),
602+ ),
603+ ],
604+ );
605+ }),
606+ ),
607+ ),
608+ ],
609+ ),
576610 ),
577611 ),
578612 );
579613 }
580614
615+ Widget get _pagination {
616+ return CallbackShortcuts (
617+ bindings: < ShortcutActivator , VoidCallback > {
618+ const SingleActivator (LogicalKeyboardKey .arrowLeft): _onPreviousPage,
619+ const SingleActivator (LogicalKeyboardKey .arrowRight): _onNextPage,
620+ },
621+ child: Row (
622+ children: [
623+ IconButton (
624+ onPressed: _onPreviousPage,
625+ icon: Icon (Icons .chevron_left),
626+ ),
627+ Expanded (
628+ child: Text (
629+ "${_page + 1 }/${_album .nbImages }" ,
630+ textAlign: TextAlign .center,
631+ style: TextStyle (
632+ color: AppColors .white,
633+ ),
634+ ),
635+ ),
636+ IconButton (
637+ onPressed: _onNextPage,
638+ icon: Icon (Icons .chevron_right),
639+ ),
640+ ],
641+ ),
642+ );
643+ }
644+
581645 /// Description of the file
582646 Widget get _comment {
583647 return Padding (
0 commit comments