1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-26 23:09:21 +00:00
comunicmobile/lib/ui/routes/settings/custom_emojies_account_settings.dart

218 lines
5.8 KiB
Dart
Raw Normal View History

2020-04-29 11:42:01 +00:00
import 'package:comunic/helpers/settings_helper.dart';
2020-04-28 17:03:23 +00:00
import 'package:comunic/helpers/users_helper.dart';
2020-04-29 11:49:16 +00:00
import 'package:comunic/lists/custom_emojies_list.dart';
2020-04-29 15:22:34 +00:00
import 'package:comunic/models/custom_emoji.dart';
2020-04-29 11:42:01 +00:00
import 'package:comunic/models/new_emoji.dart';
2020-04-28 17:03:23 +00:00
import 'package:comunic/models/user.dart';
import 'package:comunic/ui/widgets/async_screen_widget.dart';
import 'package:comunic/ui/widgets/network_image_widget.dart';
import 'package:comunic/utils/account_utils.dart';
2020-04-29 11:42:01 +00:00
import 'package:comunic/utils/files_utils.dart';
import 'package:comunic/utils/input_utils.dart';
2020-04-28 17:03:23 +00:00
import 'package:comunic/utils/intl_utils.dart';
2020-04-29 11:42:01 +00:00
import 'package:comunic/utils/ui_utils.dart';
2020-04-28 17:03:23 +00:00
import 'package:flutter/material.dart';
2021-03-13 17:03:20 +00:00
import '../../../models/api_request.dart';
import '../../../utils/ui_utils.dart';
2020-04-28 17:03:23 +00:00
/// Emojies account settings
///
/// @author Pierre Hubert
2020-05-13 16:12:45 +00:00
class CustomEmojisAccountSettings extends StatefulWidget {
2020-04-28 17:03:23 +00:00
@override
2020-05-13 16:12:45 +00:00
_CustomEmojisAccountSettingsState createState() =>
_CustomEmojisAccountSettingsState();
2020-04-28 17:03:23 +00:00
}
2020-05-13 16:12:45 +00:00
class _CustomEmojisAccountSettingsState
extends State<CustomEmojisAccountSettings> {
2020-04-28 17:03:23 +00:00
User _user;
2020-04-29 11:42:01 +00:00
final _key = GlobalKey<AsyncScreenWidgetState>();
2020-04-28 17:03:23 +00:00
Future<void> _reload() async {
_user = await UsersHelper().getSingleWithThrow(
userID(),
forceDownload: true,
);
}
@override
Widget build(BuildContext context) {
return AsyncScreenWidget(
2020-04-29 11:42:01 +00:00
key: _key,
2020-04-28 17:03:23 +00:00
onReload: _reload,
onBuild: _buildSettings,
errorMessage: tr("Could not refresh user information!"),
2020-04-29 11:42:01 +00:00
showOldDataWhileUpdating: true,
2020-04-28 17:03:23 +00:00
);
}
Widget _buildSettings() {
2020-05-13 16:13:28 +00:00
return Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(
children: [_buildList(), _buildAddButton()],
),
2020-04-29 11:42:01 +00:00
);
}
Widget _buildList() {
2020-04-28 17:03:23 +00:00
return ListView(
children: _user.customEmojies
.map((u) => ListTile(
leading: NetworkImageWidget(url: u.url, width: 50),
title: Text(u.shortcut),
2020-04-29 15:22:34 +00:00
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => _deleteEmoji(u)),
2020-04-28 17:03:23 +00:00
))
.toList());
}
2020-04-29 11:42:01 +00:00
Widget _buildAddButton() {
return Positioned(
child: FloatingActionButton(
onPressed: _addEmoji,
child: Icon(Icons.add),
),
right: 20,
bottom: 20,
);
}
/// Add a custom emoji
void _addEmoji() async {
try {
final newEmoji = await showDialog<NewEmoji>(
context: context,
2020-04-29 11:49:16 +00:00
builder: (c) => _NewCustomEmojiDialog(
currentList: _user.customEmojies,
),
2020-04-29 11:42:01 +00:00
);
2020-04-29 11:44:09 +00:00
if (newEmoji == null) return;
2020-04-29 11:42:01 +00:00
await SettingsHelper.uploadNewCustomEmoji(newEmoji);
} catch (e, stack) {
print("Could not add a new emoji: $e\n$stack");
showSimpleSnack(context, tr("Could not upload emoji!"));
}
_key.currentState.refresh();
}
2020-04-29 15:22:34 +00:00
/// Ask for confirmation before deleting permanently an emoji
void _deleteEmoji(CustomEmoji u) async {
try {
if (!await showConfirmDialog(
context: context,
message: tr("Do you really want to delete this custom emoji ?")))
return;
await SettingsHelper.deleteCustomEmoji(u.id);
} catch (e, stack) {
print("Could not delete custom emoji! $e\n$stack");
2020-04-29 15:24:33 +00:00
showSimpleSnack(context, tr("Could not delete custom emoji!"));
2020-04-29 15:22:34 +00:00
}
2020-04-29 15:24:33 +00:00
_key.currentState.refresh();
2020-04-29 15:22:34 +00:00
}
2020-04-29 11:42:01 +00:00
}
2020-04-29 11:44:09 +00:00
/// Dialog used to upload new custom emojies
class _NewCustomEmojiDialog extends StatefulWidget {
2020-04-29 11:49:16 +00:00
final CustomEmojiesList currentList;
const _NewCustomEmojiDialog({
Key key,
@required this.currentList,
}) : assert(currentList != null),
super(key: key);
2020-04-29 11:42:01 +00:00
@override
2020-04-29 11:44:09 +00:00
_NewCustomEmojiDialogState createState() => _NewCustomEmojiDialogState();
2020-04-29 11:42:01 +00:00
}
2020-04-29 11:44:09 +00:00
class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> {
2020-04-29 11:42:01 +00:00
final _controller = TextEditingController();
2021-03-13 17:03:20 +00:00
BytesFile _file;
2020-04-29 11:42:01 +00:00
bool get _hasImage => _file != null;
String get _shortcut => _controller.text;
bool get _shortcutValid =>
2020-04-29 11:49:16 +00:00
_shortcut.isNotEmpty &&
validateShortcut(_shortcut) &&
!widget.currentList.hasShortcut(_shortcut);
2020-04-29 11:42:01 +00:00
bool get _valid => _hasImage && _shortcutValid;
NewEmoji get _emoji => NewEmoji(shortcut: _shortcut, image: _file);
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(tr("Add new emoji")),
content: ConstrainedBox(
constraints:
BoxConstraints(maxHeight: MediaQuery.of(context).size.height - 50),
child: SingleChildScrollView(
child: _buildBody(),
),
),
actions: <Widget>[
MaterialButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(tr("Cancel").toUpperCase()),
),
MaterialButton(
onPressed: _valid ? () => Navigator.of(context).pop(_emoji) : null,
child: Text(tr("Add").toUpperCase()),
),
],
);
}
Widget _buildBody() {
return Column(
children: <Widget>[
TextField(
controller: _controller,
onChanged: (s) => setState(() {}),
decoration: InputDecoration(
alignLabelWithHint: true,
labelText: tr("Shortcut"),
hintText: tr(":yourShortcut:"),
errorText: _shortcut.isNotEmpty && !_shortcutValid
? tr("Invalid shortcut!")
: null,
),
),
MaterialButton(
onPressed: _pickImage,
child: Text(_hasImage ? tr("Replace image") : tr("Add image")),
)
],
);
}
void _pickImage() async {
try {
final image = await pickImage(context);
if (image == null) return;
setState(() {
_file = image;
});
} catch (e, stack) {
print("Could not pick an image! $e\n$stack");
2021-03-13 17:03:20 +00:00
snack(context, tr("Failed to pick an image!"));
2020-04-29 11:42:01 +00:00
}
}
2020-04-28 17:03:23 +00:00
}