From fd572c58384845dd034c035c9bb90bf4d64e37cd Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 8 Aug 2020 21:31:19 +0900 Subject: [PATCH] changed dialog style --- lib/utils/constants.dart | 8 -- .../action_delegates/create_album_dialog.dart | 107 ++++++++---------- .../entry_action_delegate.dart | 6 +- .../group_collection_dialog.dart | 31 ++--- .../action_delegates/permission_aware.dart | 9 +- .../action_delegates/rename_entry_dialog.dart | 6 +- .../selection_action_delegate.dart | 5 +- .../sort_collection_dialog.dart | 29 ++--- lib/widgets/common/dialog.dart | 68 +++++++++++ 9 files changed, 145 insertions(+), 124 deletions(-) create mode 100644 lib/widgets/common/dialog.dart diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 58381d2f7..902979c8e 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -22,14 +22,6 @@ class Constants { static const svgBackground = Colors.white; static const svgColorFilter = ColorFilter.mode(svgBackground, BlendMode.dstOver); - static const dialogContentHorizontalPadding = EdgeInsets.symmetric(horizontal: 24); - static const dialogActionsPadding = EdgeInsets.symmetric(horizontal: 8); - static const dialogShape = RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(24), - ), - ); - static const List androidDependencies = [ Dependency( name: 'CWAC-Document', diff --git a/lib/widgets/common/action_delegates/create_album_dialog.dart b/lib/widgets/common/action_delegates/create_album_dialog.dart index 8a2b3d587..a32dfcf53 100644 --- a/lib/widgets/common/action_delegates/create_album_dialog.dart +++ b/lib/widgets/common/action_delegates/create_album_dialog.dart @@ -1,11 +1,12 @@ import 'dart:io'; import 'package:aves/utils/android_file_utils.dart'; -import 'package:aves/utils/constants.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:path/path.dart'; +import '../dialog.dart'; + class CreateAlbumDialog extends StatefulWidget { @override _CreateAlbumDialogState createState() => _CreateAlbumDialogState(); @@ -34,63 +35,53 @@ class _CreateAlbumDialogState extends State { @override Widget build(BuildContext context) { - return AlertDialog( - title: Text('New Album'), - content: Container( - // workaround because the dialog tries - // to size itself to the content intrinsic size, - // but the `ListView` viewport does not have one - width: double.maxFinite, - child: ListView( - shrinkWrap: true, - children: [ - if (_allVolumes.length > 1) ...[ - Padding( - padding: Constants.dialogContentHorizontalPadding, - child: Text('Storage:'), - ), - ..._allVolumes.map((volume) => RadioListTile( - value: volume, - groupValue: _selectedVolume, - onChanged: (volume) { - _selectedVolume = volume; - _checkAlbumExists(); - setState(() {}); - }, - title: Text( - volume.description, - softWrap: false, - overflow: TextOverflow.fade, - maxLines: 1, - ), - subtitle: Text( - volume.path, - softWrap: false, - overflow: TextOverflow.fade, - maxLines: 1, - ), - )), - SizedBox(height: 8), - ], - Padding( - padding: Constants.dialogContentHorizontalPadding, - child: ValueListenableBuilder( - valueListenable: _existsNotifier, - builder: (context, exists, child) { - return TextField( - controller: _nameController, - decoration: InputDecoration( - helperText: exists ? 'Album already exists' : '', - ), - onChanged: (_) => _checkAlbumExists(), - onSubmitted: (_) => _submit(context), - ); - }), - ), - ], + return AvesDialog( + title: 'New Album', + scrollableContent: [ + if (_allVolumes.length > 1) ...[ + Padding( + padding: AvesDialog.contentHorizontalPadding + EdgeInsets.only(top: 20), + child: Text('Storage:'), + ), + ..._allVolumes.map((volume) => RadioListTile( + value: volume, + groupValue: _selectedVolume, + onChanged: (volume) { + _selectedVolume = volume; + _checkAlbumExists(); + setState(() {}); + }, + title: Text( + volume.description, + softWrap: false, + overflow: TextOverflow.fade, + maxLines: 1, + ), + subtitle: Text( + volume.path, + softWrap: false, + overflow: TextOverflow.fade, + maxLines: 1, + ), + )), + SizedBox(height: 8), + ], + Padding( + padding: AvesDialog.contentHorizontalPadding, + child: ValueListenableBuilder( + valueListenable: _existsNotifier, + builder: (context, exists, child) { + return TextField( + controller: _nameController, + decoration: InputDecoration( + helperText: exists ? 'Album already exists' : '', + ), + onChanged: (_) => _checkAlbumExists(), + onSubmitted: (_) => _submit(context), + ); + }), ), - ), - contentPadding: EdgeInsets.only(top: 20), + ], actions: [ FlatButton( onPressed: () => Navigator.pop(context), @@ -101,8 +92,6 @@ class _CreateAlbumDialogState extends State { child: Text('Create'.toUpperCase()), ), ], - actionsPadding: Constants.dialogActionsPadding, - shape: Constants.dialogShape, ); } diff --git a/lib/widgets/common/action_delegates/entry_action_delegate.dart b/lib/widgets/common/action_delegates/entry_action_delegate.dart index 36c36b235..127734449 100644 --- a/lib/widgets/common/action_delegates/entry_action_delegate.dart +++ b/lib/widgets/common/action_delegates/entry_action_delegate.dart @@ -4,10 +4,10 @@ import 'package:aves/model/image_entry.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/android_app_service.dart'; import 'package:aves/services/image_file_service.dart'; -import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/common/action_delegates/feedback.dart'; import 'package:aves/widgets/common/action_delegates/permission_aware.dart'; import 'package:aves/widgets/common/action_delegates/rename_entry_dialog.dart'; +import 'package:aves/widgets/common/dialog.dart'; import 'package:aves/widgets/common/entry_actions.dart'; import 'package:aves/widgets/common/image_providers/uri_image_provider.dart'; import 'package:aves/widgets/fullscreen/debug.dart'; @@ -120,7 +120,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin { final confirmed = await showDialog( context: context, builder: (context) { - return AlertDialog( + return AvesDialog( content: Text('Are you sure?'), actions: [ FlatButton( @@ -132,8 +132,6 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin { child: Text('Delete'.toUpperCase()), ), ], - actionsPadding: Constants.dialogActionsPadding, - shape: Constants.dialogShape, ); }, ); diff --git a/lib/widgets/common/action_delegates/group_collection_dialog.dart b/lib/widgets/common/action_delegates/group_collection_dialog.dart index 2739bc90a..111eb8765 100644 --- a/lib/widgets/common/action_delegates/group_collection_dialog.dart +++ b/lib/widgets/common/action_delegates/group_collection_dialog.dart @@ -1,9 +1,10 @@ import 'package:aves/model/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; -import 'package:aves/utils/constants.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import '../dialog.dart'; + class GroupCollectionDialog extends StatefulWidget { @override _GroupCollectionDialogState createState() => _GroupCollectionDialogState(); @@ -20,24 +21,14 @@ class _GroupCollectionDialogState extends State { @override Widget build(BuildContext context) { - return AlertDialog( - title: Text('Group'), - content: Container( - // workaround because the dialog tries - // to size itself to the content intrinsic size, - // but the `ListView` viewport does not have one - width: double.maxFinite, - child: ListView( - shrinkWrap: true, - children: [ - _buildRadioListTile(GroupFactor.album, 'By album'), - _buildRadioListTile(GroupFactor.month, 'By month'), - _buildRadioListTile(GroupFactor.day, 'By day'), - _buildRadioListTile(GroupFactor.none, 'Do not group'), - ], - ), - ), - contentPadding: EdgeInsets.only(top: 20), + return AvesDialog( + title: 'Group', + scrollableContent: [ + _buildRadioListTile(GroupFactor.album, 'By album'), + _buildRadioListTile(GroupFactor.month, 'By month'), + _buildRadioListTile(GroupFactor.day, 'By day'), + _buildRadioListTile(GroupFactor.none, 'Do not group'), + ], actions: [ FlatButton( onPressed: () => Navigator.pop(context), @@ -48,8 +39,6 @@ class _GroupCollectionDialogState extends State { child: Text('Apply'.toUpperCase()), ), ], - actionsPadding: Constants.dialogActionsPadding, - shape: Constants.dialogShape, ); } diff --git a/lib/widgets/common/action_delegates/permission_aware.dart b/lib/widgets/common/action_delegates/permission_aware.dart index cddbfa92b..d1df692b5 100644 --- a/lib/widgets/common/action_delegates/permission_aware.dart +++ b/lib/widgets/common/action_delegates/permission_aware.dart @@ -1,8 +1,9 @@ import 'package:aves/model/image_entry.dart'; import 'package:aves/services/android_file_service.dart'; -import 'package:aves/utils/constants.dart'; import 'package:flutter/material.dart'; +import '../dialog.dart'; + mixin PermissionAwareMixin { Future checkStoragePermission(BuildContext context, Iterable entries) { return checkStoragePermissionForAlbums(context, entries.where((e) => e.path != null).map((e) => e.directory).toSet()); @@ -23,8 +24,8 @@ mixin PermissionAwareMixin { final confirmed = await showDialog( context: context, builder: (context) { - return AlertDialog( - title: Text('Storage Volume Access'), + return AvesDialog( + title: 'Storage Volume Access', content: Text('Please select the $dirDisplayName directory of “$volumeDescription” in the next screen, so that this app can access it and complete your request.'), actions: [ FlatButton( @@ -36,8 +37,6 @@ mixin PermissionAwareMixin { child: Text('OK'.toUpperCase()), ), ], - actionsPadding: Constants.dialogActionsPadding, - shape: Constants.dialogShape, ); }, ); diff --git a/lib/widgets/common/action_delegates/rename_entry_dialog.dart b/lib/widgets/common/action_delegates/rename_entry_dialog.dart index d7fb28535..33cee0309 100644 --- a/lib/widgets/common/action_delegates/rename_entry_dialog.dart +++ b/lib/widgets/common/action_delegates/rename_entry_dialog.dart @@ -1,5 +1,5 @@ import 'package:aves/model/image_entry.dart'; -import 'package:aves/utils/constants.dart'; +import 'package:aves/widgets/common/dialog.dart'; import 'package:flutter/material.dart'; class RenameEntryDialog extends StatefulWidget { @@ -29,7 +29,7 @@ class _RenameEntryDialogState extends State { @override Widget build(BuildContext context) { - return AlertDialog( + return AvesDialog( content: TextField( controller: _nameController, autofocus: true, @@ -44,8 +44,6 @@ class _RenameEntryDialogState extends State { child: Text('Apply'.toUpperCase()), ), ], - actionsPadding: Constants.dialogActionsPadding, - shape: Constants.dialogShape, ); } } diff --git a/lib/widgets/common/action_delegates/selection_action_delegate.dart b/lib/widgets/common/action_delegates/selection_action_delegate.dart index 67cb50b20..f753cab5f 100644 --- a/lib/widgets/common/action_delegates/selection_action_delegate.dart +++ b/lib/widgets/common/action_delegates/selection_action_delegate.dart @@ -15,6 +15,7 @@ import 'package:aves/widgets/album/empty.dart'; import 'package:aves/widgets/common/action_delegates/create_album_dialog.dart'; import 'package:aves/widgets/common/action_delegates/feedback.dart'; import 'package:aves/widgets/common/action_delegates/permission_aware.dart'; +import 'package:aves/widgets/common/dialog.dart'; import 'package:aves/widgets/common/entry_actions.dart'; import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/filter_grid_page.dart'; @@ -189,7 +190,7 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin { final confirmed = await showDialog( context: context, builder: (context) { - return AlertDialog( + return AvesDialog( content: Text('Are you sure you want to delete ${Intl.plural(count, one: 'this item', other: 'these $count items')}?'), actions: [ FlatButton( @@ -201,8 +202,6 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin { child: Text('Delete'.toUpperCase()), ), ], - actionsPadding: Constants.dialogActionsPadding, - shape: Constants.dialogShape, ); }, ); diff --git a/lib/widgets/common/action_delegates/sort_collection_dialog.dart b/lib/widgets/common/action_delegates/sort_collection_dialog.dart index 452b2d06e..8286fd667 100644 --- a/lib/widgets/common/action_delegates/sort_collection_dialog.dart +++ b/lib/widgets/common/action_delegates/sort_collection_dialog.dart @@ -1,9 +1,10 @@ import 'package:aves/model/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; -import 'package:aves/utils/constants.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import '../dialog.dart'; + class SortCollectionDialog extends StatefulWidget { @override _SortCollectionDialogState createState() => _SortCollectionDialogState(); @@ -20,23 +21,13 @@ class _SortCollectionDialogState extends State { @override Widget build(BuildContext context) { - return AlertDialog( - title: Text('Sort'), - content: Container( - // workaround because the dialog tries - // to size itself to the content intrinsic size, - // but the `ListView` viewport does not have one - width: double.maxFinite, - child: ListView( - shrinkWrap: true, - children: [ - _buildRadioListTile(SortFactor.date, 'By date'), - _buildRadioListTile(SortFactor.size, 'By size'), - _buildRadioListTile(SortFactor.name, 'By album & file name'), - ], - ), - ), - contentPadding: EdgeInsets.only(top: 20), + return AvesDialog( + title: 'Sort', + scrollableContent: [ + _buildRadioListTile(SortFactor.date, 'By date'), + _buildRadioListTile(SortFactor.size, 'By size'), + _buildRadioListTile(SortFactor.name, 'By album & file name'), + ], actions: [ FlatButton( onPressed: () => Navigator.pop(context), @@ -47,8 +38,6 @@ class _SortCollectionDialogState extends State { child: Text('Apply'.toUpperCase()), ), ], - actionsPadding: Constants.dialogActionsPadding, - shape: Constants.dialogShape, ); } diff --git a/lib/widgets/common/dialog.dart b/lib/widgets/common/dialog.dart new file mode 100644 index 000000000..01b919004 --- /dev/null +++ b/lib/widgets/common/dialog.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + +class AvesDialog extends AlertDialog { + static const contentHorizontalPadding = EdgeInsets.symmetric(horizontal: 24); + + AvesDialog({ + String title, + List scrollableContent, + Widget content, + @required List actions, + }) : assert((scrollableContent != null) ^ (content != null)), + super( + title: title != null ? DialogTitle(title: title) : null, + titlePadding: EdgeInsets.zero, + // the `scrollable` flag of `AlertDialog` makes it + // scroll both the title and the content together, + // and overflow feedback ignores the dialog shape, + // so we restrict scrolling to the content instead + content: scrollableContent != null + ? Builder( + builder: (context) => Container( + // workaround because the dialog tries + // to size itself to the content intrinsic size, + // but the `ListView` viewport does not have one + width: 1, + child: ListView( + shrinkWrap: true, + children: scrollableContent, + ), + ), + ) + : content, + contentPadding: scrollableContent != null ? EdgeInsets.zero : EdgeInsets.fromLTRB(24, 20, 24, 24), + actions: actions, + actionsPadding: EdgeInsets.symmetric(horizontal: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(24), + ), + ), + ); +} + +class DialogTitle extends StatelessWidget { + final String title; + + const DialogTitle({@required this.title}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Text( + title, + style: TextStyle( + fontWeight: FontWeight.bold, + fontFamily: 'Concourse Caps', + ), + ), + ), + Divider(height: 1), + ], + ); + } +}