changed dialog style
This commit is contained in:
parent
a3543a7c69
commit
fd572c5838
9 changed files with 145 additions and 124 deletions
|
@ -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<Dependency> androidDependencies = [
|
||||
Dependency(
|
||||
name: 'CWAC-Document',
|
||||
|
|
|
@ -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<CreateAlbumDialog> {
|
|||
|
||||
@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<StorageVolume>(
|
||||
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<bool>(
|
||||
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<StorageVolume>(
|
||||
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<bool>(
|
||||
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<CreateAlbumDialog> {
|
|||
child: Text('Create'.toUpperCase()),
|
||||
),
|
||||
],
|
||||
actionsPadding: Constants.dialogActionsPadding,
|
||||
shape: Constants.dialogShape,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<bool>(
|
||||
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,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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<GroupCollectionDialog> {
|
|||
|
||||
@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<GroupCollectionDialog> {
|
|||
child: Text('Apply'.toUpperCase()),
|
||||
),
|
||||
],
|
||||
actionsPadding: Constants.dialogActionsPadding,
|
||||
shape: Constants.dialogShape,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<bool> checkStoragePermission(BuildContext context, Iterable<ImageEntry> 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<bool>(
|
||||
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,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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<RenameEntryDialog> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
return AvesDialog(
|
||||
content: TextField(
|
||||
controller: _nameController,
|
||||
autofocus: true,
|
||||
|
@ -44,8 +44,6 @@ class _RenameEntryDialogState extends State<RenameEntryDialog> {
|
|||
child: Text('Apply'.toUpperCase()),
|
||||
),
|
||||
],
|
||||
actionsPadding: Constants.dialogActionsPadding,
|
||||
shape: Constants.dialogShape,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<bool>(
|
||||
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,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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<SortCollectionDialog> {
|
|||
|
||||
@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<SortCollectionDialog> {
|
|||
child: Text('Apply'.toUpperCase()),
|
||||
),
|
||||
],
|
||||
actionsPadding: Constants.dialogActionsPadding,
|
||||
shape: Constants.dialogShape,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
68
lib/widgets/common/dialog.dart
Normal file
68
lib/widgets/common/dialog.dart
Normal file
|
@ -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<Widget> scrollableContent,
|
||||
Widget content,
|
||||
@required List<Widget> 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),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue