import 'dart:io'; 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'; /// Emojies account settings /// /// @author Pierre Hubert class CustomEmojisAccountSettings extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(tr("Custom emojies settings")), ), body: _CustomEmojiesAccountBody(), ); } } class _CustomEmojiesAccountBody extends StatefulWidget { @override _CustomEmojiesAccountBodyState createState() => _CustomEmojiesAccountBodyState(); } class _CustomEmojiesAccountBodyState extends State<_CustomEmojiesAccountBody> { 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 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(); File _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"); } } }