nc-photos/app/lib/widget/new_album_dialog.dart

290 lines
8.9 KiB
Dart
Raw Normal View History

import 'dart:async';
2021-04-10 06:28:12 +02:00
import 'package:flutter/material.dart';
2022-01-29 12:31:32 +01:00
import 'package:kiwi/kiwi.dart';
2021-04-10 06:28:12 +02:00
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
2021-07-25 07:00:38 +02:00
import 'package:nc_photos/app_localizations.dart';
2022-01-29 12:31:32 +01:00
import 'package:nc_photos/di_container.dart';
2021-04-10 06:28:12 +02:00
import 'package:nc_photos/entity/album.dart';
2021-06-26 13:51:13 +02:00
import 'package:nc_photos/entity/album/cover_provider.dart';
2021-06-24 18:26:56 +02:00
import 'package:nc_photos/entity/album/provider.dart';
2021-07-07 20:40:43 +02:00
import 'package:nc_photos/entity/album/sort_provider.dart';
2021-07-23 22:05:57 +02:00
import 'package:nc_photos/entity/file.dart';
2022-01-29 12:31:32 +01:00
import 'package:nc_photos/entity/tag.dart';
2021-12-10 19:44:56 +01:00
import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/snack_bar_manager.dart';
2021-04-10 06:28:12 +02:00
import 'package:nc_photos/use_case/create_album.dart';
2021-06-29 11:44:35 +02:00
import 'package:nc_photos/widget/album_dir_picker.dart';
import 'package:nc_photos/widget/processing_dialog.dart';
2022-01-29 12:31:32 +01:00
import 'package:nc_photos/widget/tag_picker_dialog.dart';
2021-04-10 06:28:12 +02:00
/// Dialog to create a new album
///
/// The created album will be popped to the previous route, or null if user
/// cancelled
class NewAlbumDialog extends StatefulWidget {
2021-09-15 08:58:06 +02:00
const NewAlbumDialog({
2021-07-23 22:05:57 +02:00
Key? key,
required this.account,
2021-06-29 11:44:35 +02:00
this.isAllowDynamic = true,
2021-04-10 06:28:12 +02:00
}) : super(key: key);
@override
createState() => _NewAlbumDialogState();
final Account account;
2021-06-29 11:44:35 +02:00
final bool isAllowDynamic;
2021-04-10 06:28:12 +02:00
}
class _NewAlbumDialogState extends State<NewAlbumDialog> {
_NewAlbumDialogState() {
final c = KiwiContainer().resolve<DiContainer>();
assert(require(c));
_c = c;
}
static bool require(DiContainer c) => DiContainer.has(c, DiType.albumRepo);
2021-04-10 06:28:12 +02:00
@override
initState() {
super.initState();
}
@override
build(BuildContext context) {
2021-06-29 11:44:35 +02:00
return Visibility(
visible: _isVisible,
child: AlertDialog(
2022-01-27 22:03:15 +01:00
title: Text(L10n.global().createCollectionTooltip),
2021-06-29 11:44:35 +02:00
content: Form(
key: _formKey,
child: Container(
2021-09-15 08:58:06 +02:00
constraints: const BoxConstraints.tightFor(width: 280),
2021-06-29 11:44:35 +02:00
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
decoration: InputDecoration(
hintText: L10n.global().nameInputHint,
2021-06-29 11:44:35 +02:00
),
validator: (value) {
2021-07-23 22:05:57 +02:00
if (value!.isEmpty) {
return L10n.global().albumNameInputInvalidEmpty;
2021-06-29 11:44:35 +02:00
}
return null;
},
onSaved: (value) {
2021-07-23 22:05:57 +02:00
_formValue.name = value!;
2021-06-29 11:44:35 +02:00
},
),
if (widget.isAllowDynamic) ...[
DropdownButtonHideUnderline(
child: DropdownButtonFormField<_Provider>(
value: _provider,
2022-01-27 22:05:02 +01:00
items: _Provider.values
2021-06-29 11:44:35 +02:00
.map((e) => DropdownMenuItem<_Provider>(
value: e,
child: Text(e.toValueString(context)),
))
.toList(),
onChanged: (newValue) {
setState(() {
2021-07-23 22:05:57 +02:00
_provider = newValue!;
2021-06-29 11:44:35 +02:00
});
},
onSaved: (value) {
_formValue.provider = value;
},
),
),
const SizedBox(height: 8),
Text(
_provider.toDescription(context),
style: Theme.of(context).textTheme.bodyText2,
),
],
],
),
2021-04-10 06:28:12 +02:00
),
),
2021-06-29 11:44:35 +02:00
actions: [
TextButton(
onPressed: () => _onOkPressed(context),
child: Text(MaterialLocalizations.of(context).okButtonLabel),
),
],
2021-04-10 06:28:12 +02:00
),
);
}
void _onOkPressed(BuildContext context) {
2021-07-23 22:05:57 +02:00
if (_formKey.currentState?.validate() == true) {
_formKey.currentState!.save();
2022-01-27 22:05:02 +01:00
switch (_formValue.provider) {
case _Provider.static:
case null:
_onConfirmStaticAlbum();
break;
case _Provider.dir:
_onConfirmDirAlbum();
break;
2022-01-29 12:31:32 +01:00
case _Provider.tag:
_onConfirmTagAlbum();
break;
2021-06-29 11:44:35 +02:00
}
}
}
2021-12-10 19:44:56 +01:00
Future<void> _onConfirmStaticAlbum() async {
setState(() {
_isVisible = false;
});
unawaited(showDialog(
barrierDismissible: false,
context: context,
builder: (context) =>
ProcessingDialog(text: L10n.global().genericProcessingDialogContent),
));
2021-12-10 19:44:56 +01:00
try {
final album = Album(
name: _formValue.name,
provider: AlbumStaticProvider(
items: const [],
),
coverProvider: AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(isAscending: false),
);
_log.info("[_onConfirmStaticAlbum] Creating static album: $album");
final newAlbum = await CreateAlbum(_c.albumRepo)(widget.account, album);
Navigator.of(context)..pop()..pop(newAlbum);
2021-12-10 19:44:56 +01:00
} catch (e, stacktrace) {
_log.shout("[_onConfirmStaticAlbum] Failed", e, stacktrace);
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(e)),
duration: k.snackBarDurationNormal,
));
Navigator.of(context)..pop()..pop();
2021-12-10 19:44:56 +01:00
}
2021-06-29 11:44:35 +02:00
}
2021-12-10 19:44:56 +01:00
Future<void> _onConfirmDirAlbum() async {
2021-06-29 11:44:35 +02:00
setState(() {
_isVisible = false;
});
2021-12-10 19:44:56 +01:00
try {
final dirs = await Navigator.of(context).pushNamed<List<File>>(
AlbumDirPicker.routeName,
arguments: AlbumDirPickerArguments(widget.account));
if (dirs == null) {
2021-06-29 11:44:35 +02:00
Navigator.of(context).pop();
return;
}
2021-04-10 06:28:12 +02:00
final album = Album(
name: _formValue.name,
2021-06-29 11:44:35 +02:00
provider: AlbumDirProvider(
2021-12-10 19:44:56 +01:00
dirs: dirs,
2021-06-24 18:26:56 +02:00
),
2021-06-26 13:51:13 +02:00
coverProvider: AlbumAutoCoverProvider(),
2021-09-15 08:58:06 +02:00
sortProvider: const AlbumTimeSortProvider(isAscending: false),
2021-04-10 06:28:12 +02:00
);
2021-12-10 19:44:56 +01:00
_log.info("[_onConfirmDirAlbum] Creating dir album: $album");
final newAlbum = await CreateAlbum(_c.albumRepo)(widget.account, album);
2021-04-10 06:28:12 +02:00
Navigator.of(context).pop(newAlbum);
2021-12-10 19:44:56 +01:00
} catch (e, stacktrace) {
_log.shout("[_onConfirmDirAlbum] Failed", e, stacktrace);
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(e)),
duration: k.snackBarDurationNormal,
));
2021-06-29 11:44:35 +02:00
Navigator.of(context).pop();
2021-12-10 19:44:56 +01:00
}
2021-04-10 06:28:12 +02:00
}
2022-01-29 12:31:32 +01:00
Future<void> _onConfirmTagAlbum() async {
setState(() {
_isVisible = false;
});
try {
final tags = await showDialog<List<Tag>>(
context: context,
builder: (_) => TagPickerDialog(account: widget.account),
);
if (tags == null || tags.isEmpty) {
Navigator.of(context).pop();
return;
}
final album = Album(
name: _formValue.name,
provider: AlbumTagProvider(tags: tags),
coverProvider: AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(isAscending: false),
);
_log.info(
"[_onConfirmTagAlbum] Creating tag album: ${tags.map((t) => t.displayName).join(", ")}");
final c = KiwiContainer().resolve<DiContainer>();
final newAlbum = await CreateAlbum(c.albumRepo)(widget.account, album);
Navigator.of(context).pop(newAlbum);
} catch (e, stackTrace) {
_log.shout("[_onConfirmTagAlbum] Failed", e, stackTrace);
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(e)),
duration: k.snackBarDurationNormal,
));
Navigator.of(context).pop();
}
}
late final DiContainer _c;
2021-04-10 06:28:12 +02:00
final _formKey = GlobalKey<FormState>();
2021-06-29 11:44:35 +02:00
var _provider = _Provider.static;
2021-04-10 06:28:12 +02:00
final _formValue = _FormValue();
2021-06-29 11:44:35 +02:00
var _isVisible = true;
2021-07-01 22:23:30 +02:00
static final _log = Logger("widget.new_album_dialog._NewAlbumDialogState");
2021-04-10 06:28:12 +02:00
}
class _FormValue {
2021-07-23 22:05:57 +02:00
late String name;
_Provider? provider;
2021-06-29 11:44:35 +02:00
}
enum _Provider {
static,
dir,
2022-01-29 12:31:32 +01:00
tag,
2021-06-29 11:44:35 +02:00
}
extension on _Provider {
String toValueString(BuildContext context) {
switch (this) {
case _Provider.static:
2022-01-27 22:03:15 +01:00
return L10n.global().createCollectionDialogAlbumLabel;
2021-06-29 11:44:35 +02:00
case _Provider.dir:
2022-01-27 22:03:15 +01:00
return L10n.global().createCollectionDialogFolderLabel;
2022-01-29 12:31:32 +01:00
case _Provider.tag:
return L10n.global().createCollectionDialogTagLabel;
2021-06-29 11:44:35 +02:00
default:
throw StateError("Unknown value: $this");
}
}
String toDescription(BuildContext context) {
switch (this) {
case _Provider.static:
2022-01-27 22:03:15 +01:00
return L10n.global().createCollectionDialogAlbumDescription;
2021-06-29 11:44:35 +02:00
case _Provider.dir:
2022-01-27 22:03:15 +01:00
return L10n.global().createCollectionDialogFolderDescription;
2022-01-29 12:31:32 +01:00
case _Provider.tag:
return L10n.global().createCollectionDialogTagDescription;
2021-06-29 11:44:35 +02:00
default:
throw StateError("Unknown value: $this");
}
}
2021-04-10 06:28:12 +02:00
}