mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 12:14:11 +00:00 
			
		
		
		
	Can upload new custom emojies
This commit is contained in:
		@@ -4,6 +4,7 @@ import 'package:comunic/enums/user_page_visibility.dart';
 | 
				
			|||||||
import 'package:comunic/models/account_image_settings.dart';
 | 
					import 'package:comunic/models/account_image_settings.dart';
 | 
				
			||||||
import 'package:comunic/models/api_request.dart';
 | 
					import 'package:comunic/models/api_request.dart';
 | 
				
			||||||
import 'package:comunic/models/general_settings.dart';
 | 
					import 'package:comunic/models/general_settings.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/new_emoji.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Settings helper
 | 
					/// Settings helper
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
@@ -123,4 +124,14 @@ class SettingsHelper {
 | 
				
			|||||||
      (await APIRequest(uri: "settings/delete_account_image", needLogin: true)
 | 
					      (await APIRequest(uri: "settings/delete_account_image", needLogin: true)
 | 
				
			||||||
              .exec())
 | 
					              .exec())
 | 
				
			||||||
          .isOK;
 | 
					          .isOK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Upload a new emoji
 | 
				
			||||||
 | 
					  static Future<void> uploadNewCustomEmoji(NewEmoji newEmoji) async =>
 | 
				
			||||||
 | 
					      (await APIRequest(
 | 
				
			||||||
 | 
					                  uri: "settings/upload_custom_emoji",
 | 
				
			||||||
 | 
					                  needLogin: true,
 | 
				
			||||||
 | 
					                  args: {"shortcut": newEmoji.shortcut})
 | 
				
			||||||
 | 
					              .addFile("image", newEmoji.image)
 | 
				
			||||||
 | 
					              .execWithFiles())
 | 
				
			||||||
 | 
					          .assertOk();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,8 @@ class UsersHelper {
 | 
				
			|||||||
  /// of failure
 | 
					  /// of failure
 | 
				
			||||||
  Future<UsersList> getListWithThrow(Set<int> users,
 | 
					  Future<UsersList> getListWithThrow(Set<int> users,
 | 
				
			||||||
      {bool forceDownload = false}) async {
 | 
					      {bool forceDownload = false}) async {
 | 
				
			||||||
    final list = await getUsersInfo(users.toList());
 | 
					    final list =
 | 
				
			||||||
 | 
					        await getUsersInfo(users.toList(), forceDownload: forceDownload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (list == null)
 | 
					    if (list == null)
 | 
				
			||||||
      throw Exception(
 | 
					      throw Exception(
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								lib/models/new_emoji.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/models/new_emoji.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import 'dart:io';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// New emoji information
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NewEmoji {
 | 
				
			||||||
 | 
					  final String shortcut;
 | 
				
			||||||
 | 
					  final File image;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const NewEmoji({
 | 
				
			||||||
 | 
					    @required this.shortcut,
 | 
				
			||||||
 | 
					    @required this.image,
 | 
				
			||||||
 | 
					  })  : assert(shortcut != null),
 | 
				
			||||||
 | 
					        assert(image != null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,9 +1,16 @@
 | 
				
			|||||||
 | 
					import 'dart:io';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:comunic/helpers/settings_helper.dart';
 | 
				
			||||||
import 'package:comunic/helpers/users_helper.dart';
 | 
					import 'package:comunic/helpers/users_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/new_emoji.dart';
 | 
				
			||||||
import 'package:comunic/models/user.dart';
 | 
					import 'package:comunic/models/user.dart';
 | 
				
			||||||
import 'package:comunic/ui/widgets/async_screen_widget.dart';
 | 
					import 'package:comunic/ui/widgets/async_screen_widget.dart';
 | 
				
			||||||
import 'package:comunic/ui/widgets/network_image_widget.dart';
 | 
					import 'package:comunic/ui/widgets/network_image_widget.dart';
 | 
				
			||||||
import 'package:comunic/utils/account_utils.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/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Emojies account settings
 | 
					/// Emojies account settings
 | 
				
			||||||
@@ -30,6 +37,8 @@ class _EmojiesAccountBody extends StatefulWidget {
 | 
				
			|||||||
class __EmojiesAccountBodyState extends State<_EmojiesAccountBody> {
 | 
					class __EmojiesAccountBodyState extends State<_EmojiesAccountBody> {
 | 
				
			||||||
  User _user;
 | 
					  User _user;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final _key = GlobalKey<AsyncScreenWidgetState>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> _reload() async {
 | 
					  Future<void> _reload() async {
 | 
				
			||||||
    _user = await UsersHelper().getSingleWithThrow(
 | 
					    _user = await UsersHelper().getSingleWithThrow(
 | 
				
			||||||
      userID(),
 | 
					      userID(),
 | 
				
			||||||
@@ -40,13 +49,21 @@ class __EmojiesAccountBodyState extends State<_EmojiesAccountBody> {
 | 
				
			|||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return AsyncScreenWidget(
 | 
					    return AsyncScreenWidget(
 | 
				
			||||||
 | 
					      key: _key,
 | 
				
			||||||
      onReload: _reload,
 | 
					      onReload: _reload,
 | 
				
			||||||
      onBuild: _buildSettings,
 | 
					      onBuild: _buildSettings,
 | 
				
			||||||
      errorMessage: tr("Could not refresh user information!"),
 | 
					      errorMessage: tr("Could not refresh user information!"),
 | 
				
			||||||
 | 
					      showOldDataWhileUpdating: true,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Widget _buildSettings() {
 | 
					  Widget _buildSettings() {
 | 
				
			||||||
 | 
					    return Stack(
 | 
				
			||||||
 | 
					      children: [_buildList(), _buildAddButton()],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget _buildList() {
 | 
				
			||||||
    return ListView(
 | 
					    return ListView(
 | 
				
			||||||
        children: _user.customEmojies
 | 
					        children: _user.customEmojies
 | 
				
			||||||
            .map((u) => ListTile(
 | 
					            .map((u) => ListTile(
 | 
				
			||||||
@@ -55,4 +72,114 @@ class __EmojiesAccountBodyState extends State<_EmojiesAccountBody> {
 | 
				
			|||||||
                ))
 | 
					                ))
 | 
				
			||||||
            .toList());
 | 
					            .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<NewEmoji>(
 | 
				
			||||||
 | 
					        context: context,
 | 
				
			||||||
 | 
					        builder: (c) => _NewEmojiDialog(),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      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();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _NewEmojiDialog extends StatefulWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  __NewEmojiDialogState createState() => __NewEmojiDialogState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class __NewEmojiDialogState extends State<_NewEmojiDialog> {
 | 
				
			||||||
 | 
					  final _controller = TextEditingController();
 | 
				
			||||||
 | 
					  File _file;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get _hasImage => _file != null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  String get _shortcut => _controller.text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get _shortcutValid =>
 | 
				
			||||||
 | 
					      _shortcut.isNotEmpty && validateShortcut(_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: <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");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,3 +31,7 @@ bool validateUrl(String url) {
 | 
				
			|||||||
/// Validate directory reference
 | 
					/// Validate directory reference
 | 
				
			||||||
bool validateDirectoryReference(String ref) =>
 | 
					bool validateDirectoryReference(String ref) =>
 | 
				
			||||||
    RegExp(r'@[a-zA-Z0-9]+').hasMatch(ref);
 | 
					    RegExp(r'@[a-zA-Z0-9]+').hasMatch(ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Validated a shortcut
 | 
				
			||||||
 | 
					bool validateShortcut(String shortcut) =>
 | 
				
			||||||
 | 
					    RegExp(r'^:[a-zA-Z0-9]+:$').hasMatch(shortcut);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user