mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-25 22:39:22 +00:00
Can upload new custom emojies
This commit is contained in:
parent
e6df696077
commit
225df61aa0
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user