import 'package:comunic/helpers/settings_helper.dart'; import 'package:comunic/helpers/users_helper.dart'; import 'package:comunic/lists/custom_emojies_list.dart'; import 'package:comunic/models/custom_emoji.dart'; import 'package:comunic/models/new_emoji.dart'; 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'; import 'package:comunic/utils/files_utils.dart'; import 'package:comunic/utils/input_utils.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; import '../../../models/api_request.dart'; import '../../../utils/ui_utils.dart'; /// Emojies account settings /// /// @author Pierre Hubert class CustomEmojisAccountSettings extends StatefulWidget { @override _CustomEmojisAccountSettingsState createState() => _CustomEmojisAccountSettingsState(); } class _CustomEmojisAccountSettingsState extends State { late User _user; final _key = GlobalKey(); Future _reload() async { _user = await UsersHelper().getSingleWithThrow( userID(), forceDownload: true, ); } @override Widget build(BuildContext context) { return AsyncScreenWidget( key: _key, onReload: _reload, onBuild: _buildSettings, errorMessage: tr("Could not refresh user information!")!, showOldDataWhileUpdating: true, ); } Widget _buildSettings() { return Padding( padding: const EdgeInsets.all(8.0), child: Stack( children: [_buildList(), _buildAddButton()], ), ); } Widget _buildList() { return ListView( children: _user.customEmojies .map((u) => ListTile( leading: NetworkImageWidget(url: u.url!, width: 50), title: Text(u.shortcut!), trailing: IconButton( icon: Icon(Icons.delete), onPressed: () => _deleteEmoji(u)), )) .toList()); } 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( context: context, builder: (c) => _NewCustomEmojiDialog( currentList: _user.customEmojies, ), ); if (newEmoji == null) return; 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(); } /// 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"); showSimpleSnack(context, tr("Could not delete custom emoji!")!); } _key.currentState!.refresh(); } } /// Dialog used to upload new custom emojies class _NewCustomEmojiDialog extends StatefulWidget { final CustomEmojiesList currentList; const _NewCustomEmojiDialog({ Key? key, required this.currentList, }) : assert(currentList != null), super(key: key); @override _NewCustomEmojiDialogState createState() => _NewCustomEmojiDialogState(); } class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> { final _controller = TextEditingController(); BytesFile? _file; bool get _hasImage => _file != null; String get _shortcut => _controller.text; bool get _shortcutValid => _shortcut.isNotEmpty && validateShortcut(_shortcut) && !widget.currentList.hasShortcut(_shortcut); 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: [ 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: [ 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"); snack(context, tr("Failed to pick an image!")!); } } }