add basic emote picker
This commit is contained in:
parent
b3ecefd354
commit
f8a0233b74
|
@ -107,6 +107,30 @@ class SimpleDialogs {
|
||||||
return confirmed;
|
return confirmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> inform({
|
||||||
|
String titleText,
|
||||||
|
String contentText,
|
||||||
|
String okText,
|
||||||
|
}) async {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (c) => AlertDialog(
|
||||||
|
title: titleText != null ? Text(titleText) : null,
|
||||||
|
content: contentText != null ? Text(contentText) : null,
|
||||||
|
actions: <Widget>[
|
||||||
|
FlatButton(
|
||||||
|
child: Text(
|
||||||
|
okText ?? L10n.of(context).ok.toUpperCase(),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<dynamic> tryRequestWithLoadingDialog(Future<dynamic> request,
|
Future<dynamic> tryRequestWithLoadingDialog(Future<dynamic> request,
|
||||||
{Function(MatrixException) onAdditionalAuth}) async {
|
{Function(MatrixException) onAdditionalAuth}) async {
|
||||||
showLoadingDialog(context);
|
showLoadingDialog(context);
|
||||||
|
|
|
@ -424,6 +424,31 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"Emote Settings": "Emote Einstellungen",
|
||||||
|
"@Emote Settings": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"Emote shortcode": "Emote kürzel",
|
||||||
|
"@Emote shortcode": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"emoteWarnNeedToPick": "Wähle ein Emote-kürzel und ein Bild!",
|
||||||
|
"@emoteWarnNeedToPick": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"emoteExists": "Emote existiert bereits!",
|
||||||
|
"@emoteExists": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"emoteInvalid": "Ungültiges Emote-kürzel!",
|
||||||
|
"@emoteInvalid": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"Empty chat": "Leerer Chat",
|
"Empty chat": "Leerer Chat",
|
||||||
"@Empty chat": {
|
"@Empty chat": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -768,6 +793,11 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"No emotes found. 😕": "Keine Emotes gefunden. 😕",
|
||||||
|
"@No emotes found. 😕": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"No permission": "Keine Berechtigung",
|
"No permission": "Keine Berechtigung",
|
||||||
"@No permission": {
|
"@No permission": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -790,6 +820,11 @@
|
||||||
"number": {}
|
"number": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ok": "ok",
|
||||||
|
"@ok": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"Oops something went wrong...": "Hoppla! Da ist etwas schief gelaufen ...",
|
"Oops something went wrong...": "Hoppla! Da ist etwas schief gelaufen ...",
|
||||||
"@Oops something went wrong...": {
|
"@Oops something went wrong...": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -815,6 +850,11 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"Pick image": "Wähle Bild",
|
||||||
|
"@Pick image": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"play": "Play {fileName}",
|
"play": "Play {fileName}",
|
||||||
"@play": {
|
"@play": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -1327,4 +1367,4 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"@@last_modified": "2020-05-09T15:29:08.901368",
|
"@@last_modified": "2020-05-12T08:42:24.358124",
|
||||||
"About": "About",
|
"About": "About",
|
||||||
"@About": {
|
"@About": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -424,6 +424,31 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"Emote Settings": "Emote Settings",
|
||||||
|
"@Emote Settings": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"Emote shortcode": "Emote shortcode",
|
||||||
|
"@Emote shortcode": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"emoteWarnNeedToPick": "You need to pick an emote shortcode and an image!",
|
||||||
|
"@emoteWarnNeedToPick": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"emoteExists": "Emote already exists!",
|
||||||
|
"@emoteExists": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"emoteInvalid": "Invalid emote shortcode!",
|
||||||
|
"@emoteInvalid": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"Empty chat": "Empty chat",
|
"Empty chat": "Empty chat",
|
||||||
"@Empty chat": {
|
"@Empty chat": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -768,6 +793,11 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"No emotes found. 😕": "No emotes found. 😕",
|
||||||
|
"@No emotes found. 😕": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"No permission": "No permission",
|
"No permission": "No permission",
|
||||||
"@No permission": {
|
"@No permission": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -790,6 +820,11 @@
|
||||||
"number": {}
|
"number": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ok": "ok",
|
||||||
|
"@ok": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"Oops something went wrong...": "Oops something went wrong...",
|
"Oops something went wrong...": "Oops something went wrong...",
|
||||||
"@Oops something went wrong...": {
|
"@Oops something went wrong...": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
@ -820,6 +855,11 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"Pick image": "Pick image",
|
||||||
|
"@Pick image": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"play": "Play {fileName}",
|
"play": "Play {fileName}",
|
||||||
"@play": {
|
"@play": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
|
|
@ -298,6 +298,20 @@ class L10n extends MatrixLocalizations {
|
||||||
|
|
||||||
String get editDisplayname => Intl.message("Edit displayname");
|
String get editDisplayname => Intl.message("Edit displayname");
|
||||||
|
|
||||||
|
String get emoteSettings => Intl.message('Emote Settings');
|
||||||
|
|
||||||
|
String get emoteShortcode => Intl.message('Emote shortcode');
|
||||||
|
|
||||||
|
String get emoteWarnNeedToPick =>
|
||||||
|
Intl.message('You need to pick an emote shortcode and an image!',
|
||||||
|
name: 'emoteWarnNeedToPick');
|
||||||
|
|
||||||
|
String get emoteExists =>
|
||||||
|
Intl.message('Emote already exists!', name: 'emoteExists');
|
||||||
|
|
||||||
|
String get emoteInvalid =>
|
||||||
|
Intl.message('Invalid emote shortcode!', name: 'emoteInvalid');
|
||||||
|
|
||||||
String get emptyChat => Intl.message("Empty chat");
|
String get emptyChat => Intl.message("Empty chat");
|
||||||
|
|
||||||
String get enableEncryptionWarning => Intl.message(
|
String get enableEncryptionWarning => Intl.message(
|
||||||
|
@ -482,6 +496,8 @@ class L10n extends MatrixLocalizations {
|
||||||
|
|
||||||
String get none => Intl.message("None");
|
String get none => Intl.message("None");
|
||||||
|
|
||||||
|
String get noEmotesFound => Intl.message('No emotes found. 😕');
|
||||||
|
|
||||||
String get noPermission => Intl.message("No permission");
|
String get noPermission => Intl.message("No permission");
|
||||||
|
|
||||||
String get noRoomsFound => Intl.message("No rooms found...");
|
String get noRoomsFound => Intl.message("No rooms found...");
|
||||||
|
@ -491,6 +507,8 @@ class L10n extends MatrixLocalizations {
|
||||||
String numberSelected(String number) =>
|
String numberSelected(String number) =>
|
||||||
Intl.message("$number selected", name: "numberSelected", args: [number]);
|
Intl.message("$number selected", name: "numberSelected", args: [number]);
|
||||||
|
|
||||||
|
String get ok => Intl.message('ok');
|
||||||
|
|
||||||
String get oopsSomethingWentWrong =>
|
String get oopsSomethingWentWrong =>
|
||||||
Intl.message("Oops something went wrong...");
|
Intl.message("Oops something went wrong...");
|
||||||
|
|
||||||
|
@ -505,6 +523,8 @@ class L10n extends MatrixLocalizations {
|
||||||
|
|
||||||
String get password => Intl.message("Password");
|
String get password => Intl.message("Password");
|
||||||
|
|
||||||
|
String get pickImage => Intl.message('Pick image');
|
||||||
|
|
||||||
String play(String fileName) => Intl.message(
|
String play(String fileName) => Intl.message(
|
||||||
"Play $fileName",
|
"Play $fileName",
|
||||||
name: "play",
|
name: "play",
|
||||||
|
|
|
@ -193,6 +193,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Download file" : MessageLookupByLibrary.simpleMessage("Datei herunterladen"),
|
"Download file" : MessageLookupByLibrary.simpleMessage("Datei herunterladen"),
|
||||||
"Edit Jitsi instance" : MessageLookupByLibrary.simpleMessage("Jitsi Instanz ändern"),
|
"Edit Jitsi instance" : MessageLookupByLibrary.simpleMessage("Jitsi Instanz ändern"),
|
||||||
"Edit displayname" : MessageLookupByLibrary.simpleMessage("Anzeigename ändern"),
|
"Edit displayname" : MessageLookupByLibrary.simpleMessage("Anzeigename ändern"),
|
||||||
|
"Emote Settings" : MessageLookupByLibrary.simpleMessage("Emote Einstellungen"),
|
||||||
|
"Emote shortcode" : MessageLookupByLibrary.simpleMessage("Emote kürzel"),
|
||||||
"Empty chat" : MessageLookupByLibrary.simpleMessage("Leerer Chat"),
|
"Empty chat" : MessageLookupByLibrary.simpleMessage("Leerer Chat"),
|
||||||
"Encryption algorithm" : MessageLookupByLibrary.simpleMessage("Verschlüsselungsalgorithmus"),
|
"Encryption algorithm" : MessageLookupByLibrary.simpleMessage("Verschlüsselungsalgorithmus"),
|
||||||
"Encryption is not enabled" : MessageLookupByLibrary.simpleMessage("Verschlüsselung ist nicht aktiviert"),
|
"Encryption is not enabled" : MessageLookupByLibrary.simpleMessage("Verschlüsselung ist nicht aktiviert"),
|
||||||
|
@ -241,6 +243,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Mute chat" : MessageLookupByLibrary.simpleMessage("Stummschalten"),
|
"Mute chat" : MessageLookupByLibrary.simpleMessage("Stummschalten"),
|
||||||
"New message in FluffyChat" : MessageLookupByLibrary.simpleMessage("Neue Nachricht in FluffyChat"),
|
"New message in FluffyChat" : MessageLookupByLibrary.simpleMessage("Neue Nachricht in FluffyChat"),
|
||||||
"New private chat" : MessageLookupByLibrary.simpleMessage("Neuer privater Chat"),
|
"New private chat" : MessageLookupByLibrary.simpleMessage("Neuer privater Chat"),
|
||||||
|
"No emotes found. 😕" : MessageLookupByLibrary.simpleMessage("Keine Emotes gefunden. 😕"),
|
||||||
"No permission" : MessageLookupByLibrary.simpleMessage("Keine Berechtigung"),
|
"No permission" : MessageLookupByLibrary.simpleMessage("Keine Berechtigung"),
|
||||||
"No rooms found..." : MessageLookupByLibrary.simpleMessage("Keine Räume gefunden ..."),
|
"No rooms found..." : MessageLookupByLibrary.simpleMessage("Keine Räume gefunden ..."),
|
||||||
"None" : MessageLookupByLibrary.simpleMessage("Keiner"),
|
"None" : MessageLookupByLibrary.simpleMessage("Keiner"),
|
||||||
|
@ -249,6 +252,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Open camera" : MessageLookupByLibrary.simpleMessage("Kamera öffnen"),
|
"Open camera" : MessageLookupByLibrary.simpleMessage("Kamera öffnen"),
|
||||||
"Participating user devices" : MessageLookupByLibrary.simpleMessage("Teilnehmende Geräte"),
|
"Participating user devices" : MessageLookupByLibrary.simpleMessage("Teilnehmende Geräte"),
|
||||||
"Password" : MessageLookupByLibrary.simpleMessage("Passwort"),
|
"Password" : MessageLookupByLibrary.simpleMessage("Passwort"),
|
||||||
|
"Pick image" : MessageLookupByLibrary.simpleMessage("Wähle Bild"),
|
||||||
"Please be aware that you need Pantalaimon to use end-to-end encryption for now." : MessageLookupByLibrary.simpleMessage("Bitte beachte, dass du Pantalaimon brauchst, um Ende-zu-Ende-Verschlüsselung benutzen zu können."),
|
"Please be aware that you need Pantalaimon to use end-to-end encryption for now." : MessageLookupByLibrary.simpleMessage("Bitte beachte, dass du Pantalaimon brauchst, um Ende-zu-Ende-Verschlüsselung benutzen zu können."),
|
||||||
"Please choose a username" : MessageLookupByLibrary.simpleMessage("Bitte wähle einen Benutzernamen"),
|
"Please choose a username" : MessageLookupByLibrary.simpleMessage("Bitte wähle einen Benutzernamen"),
|
||||||
"Please enter a matrix identifier" : MessageLookupByLibrary.simpleMessage("Bitte eine Matrix ID eingeben"),
|
"Please enter a matrix identifier" : MessageLookupByLibrary.simpleMessage("Bitte eine Matrix ID eingeben"),
|
||||||
|
@ -339,6 +343,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"dateAndTimeOfDay" : m21,
|
"dateAndTimeOfDay" : m21,
|
||||||
"dateWithYear" : m22,
|
"dateWithYear" : m22,
|
||||||
"dateWithoutYear" : m23,
|
"dateWithoutYear" : m23,
|
||||||
|
"emoteExists" : MessageLookupByLibrary.simpleMessage("Emote existiert bereits!"),
|
||||||
|
"emoteInvalid" : MessageLookupByLibrary.simpleMessage("Ungültiges Emote-kürzel!"),
|
||||||
|
"emoteWarnNeedToPick" : MessageLookupByLibrary.simpleMessage("Wähle ein Emote-kürzel und ein Bild!"),
|
||||||
"groupWith" : m24,
|
"groupWith" : m24,
|
||||||
"hasWithdrawnTheInvitationFor" : m25,
|
"hasWithdrawnTheInvitationFor" : m25,
|
||||||
"inviteContactToGroup" : m26,
|
"inviteContactToGroup" : m26,
|
||||||
|
@ -352,6 +359,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"loadCountMoreParticipants" : m33,
|
"loadCountMoreParticipants" : m33,
|
||||||
"logInTo" : m34,
|
"logInTo" : m34,
|
||||||
"numberSelected" : m35,
|
"numberSelected" : m35,
|
||||||
|
"ok" : MessageLookupByLibrary.simpleMessage("ok"),
|
||||||
"play" : m36,
|
"play" : m36,
|
||||||
"redactedAnEvent" : m37,
|
"redactedAnEvent" : m37,
|
||||||
"rejectedTheInvitation" : m38,
|
"rejectedTheInvitation" : m38,
|
||||||
|
|
|
@ -193,6 +193,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Download file" : MessageLookupByLibrary.simpleMessage("Download file"),
|
"Download file" : MessageLookupByLibrary.simpleMessage("Download file"),
|
||||||
"Edit Jitsi instance" : MessageLookupByLibrary.simpleMessage("Edit Jitsi instance"),
|
"Edit Jitsi instance" : MessageLookupByLibrary.simpleMessage("Edit Jitsi instance"),
|
||||||
"Edit displayname" : MessageLookupByLibrary.simpleMessage("Edit displayname"),
|
"Edit displayname" : MessageLookupByLibrary.simpleMessage("Edit displayname"),
|
||||||
|
"Emote Settings" : MessageLookupByLibrary.simpleMessage("Emote Settings"),
|
||||||
|
"Emote shortcode" : MessageLookupByLibrary.simpleMessage("Emote shortcode"),
|
||||||
"Empty chat" : MessageLookupByLibrary.simpleMessage("Empty chat"),
|
"Empty chat" : MessageLookupByLibrary.simpleMessage("Empty chat"),
|
||||||
"Encryption algorithm" : MessageLookupByLibrary.simpleMessage("Encryption algorithm"),
|
"Encryption algorithm" : MessageLookupByLibrary.simpleMessage("Encryption algorithm"),
|
||||||
"Encryption is not enabled" : MessageLookupByLibrary.simpleMessage("Encryption is not enabled"),
|
"Encryption is not enabled" : MessageLookupByLibrary.simpleMessage("Encryption is not enabled"),
|
||||||
|
@ -242,6 +244,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Mute chat" : MessageLookupByLibrary.simpleMessage("Mute chat"),
|
"Mute chat" : MessageLookupByLibrary.simpleMessage("Mute chat"),
|
||||||
"New message in FluffyChat" : MessageLookupByLibrary.simpleMessage("New message in FluffyChat"),
|
"New message in FluffyChat" : MessageLookupByLibrary.simpleMessage("New message in FluffyChat"),
|
||||||
"New private chat" : MessageLookupByLibrary.simpleMessage("New private chat"),
|
"New private chat" : MessageLookupByLibrary.simpleMessage("New private chat"),
|
||||||
|
"No emotes found. 😕" : MessageLookupByLibrary.simpleMessage("No emotes found. 😕"),
|
||||||
"No permission" : MessageLookupByLibrary.simpleMessage("No permission"),
|
"No permission" : MessageLookupByLibrary.simpleMessage("No permission"),
|
||||||
"No rooms found..." : MessageLookupByLibrary.simpleMessage("No rooms found..."),
|
"No rooms found..." : MessageLookupByLibrary.simpleMessage("No rooms found..."),
|
||||||
"None" : MessageLookupByLibrary.simpleMessage("None"),
|
"None" : MessageLookupByLibrary.simpleMessage("None"),
|
||||||
|
@ -251,6 +254,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"Open camera" : MessageLookupByLibrary.simpleMessage("Open camera"),
|
"Open camera" : MessageLookupByLibrary.simpleMessage("Open camera"),
|
||||||
"Participating user devices" : MessageLookupByLibrary.simpleMessage("Participating user devices"),
|
"Participating user devices" : MessageLookupByLibrary.simpleMessage("Participating user devices"),
|
||||||
"Password" : MessageLookupByLibrary.simpleMessage("Password"),
|
"Password" : MessageLookupByLibrary.simpleMessage("Password"),
|
||||||
|
"Pick image" : MessageLookupByLibrary.simpleMessage("Pick image"),
|
||||||
"Please be aware that you need Pantalaimon to use end-to-end encryption for now." : MessageLookupByLibrary.simpleMessage("Please be aware that you need Pantalaimon to use end-to-end encryption for now."),
|
"Please be aware that you need Pantalaimon to use end-to-end encryption for now." : MessageLookupByLibrary.simpleMessage("Please be aware that you need Pantalaimon to use end-to-end encryption for now."),
|
||||||
"Please choose a username" : MessageLookupByLibrary.simpleMessage("Please choose a username"),
|
"Please choose a username" : MessageLookupByLibrary.simpleMessage("Please choose a username"),
|
||||||
"Please enter a matrix identifier" : MessageLookupByLibrary.simpleMessage("Please enter a matrix identifier"),
|
"Please enter a matrix identifier" : MessageLookupByLibrary.simpleMessage("Please enter a matrix identifier"),
|
||||||
|
@ -341,6 +345,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"dateAndTimeOfDay" : m21,
|
"dateAndTimeOfDay" : m21,
|
||||||
"dateWithYear" : m22,
|
"dateWithYear" : m22,
|
||||||
"dateWithoutYear" : m23,
|
"dateWithoutYear" : m23,
|
||||||
|
"emoteExists" : MessageLookupByLibrary.simpleMessage("Emote already exists!"),
|
||||||
|
"emoteInvalid" : MessageLookupByLibrary.simpleMessage("Invalid emote shortcode!"),
|
||||||
|
"emoteWarnNeedToPick" : MessageLookupByLibrary.simpleMessage("You need to pick an emote shortcode and an image!"),
|
||||||
"groupWith" : m24,
|
"groupWith" : m24,
|
||||||
"hasWithdrawnTheInvitationFor" : m25,
|
"hasWithdrawnTheInvitationFor" : m25,
|
||||||
"inviteContactToGroup" : m26,
|
"inviteContactToGroup" : m26,
|
||||||
|
@ -354,6 +361,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||||
"loadCountMoreParticipants" : m33,
|
"loadCountMoreParticipants" : m33,
|
||||||
"logInTo" : m34,
|
"logInTo" : m34,
|
||||||
"numberSelected" : m35,
|
"numberSelected" : m35,
|
||||||
|
"ok" : MessageLookupByLibrary.simpleMessage("ok"),
|
||||||
"play" : m36,
|
"play" : m36,
|
||||||
"redactedAnEvent" : m37,
|
"redactedAnEvent" : m37,
|
||||||
"rejectedTheInvitation" : m38,
|
"rejectedTheInvitation" : m38,
|
||||||
|
|
|
@ -16,6 +16,7 @@ import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:link_text/link_text.dart';
|
import 'package:link_text/link_text.dart';
|
||||||
|
import './settings_emotes.dart';
|
||||||
|
|
||||||
class ChatDetails extends StatefulWidget {
|
class ChatDetails extends StatefulWidget {
|
||||||
final Room room;
|
final Room room;
|
||||||
|
@ -274,6 +275,22 @@ class _ChatDetailsState extends State<ChatDetails> {
|
||||||
? widget.room.canonicalAlias
|
? widget.room.canonicalAlias
|
||||||
: L10n.of(context).none),
|
: L10n.of(context).none),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
child: Icon(Icons.insert_emoticon),
|
||||||
|
),
|
||||||
|
title: Text(L10n.of(context).emoteSettings),
|
||||||
|
onTap: () async =>
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
AppRoute.defaultRoute(
|
||||||
|
context,
|
||||||
|
EmotesSettingsView(room: widget.room),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
|
|
|
@ -17,6 +17,7 @@ import '../components/content_banner.dart';
|
||||||
import '../components/matrix.dart';
|
import '../components/matrix.dart';
|
||||||
import '../l10n/l10n.dart';
|
import '../l10n/l10n.dart';
|
||||||
import '../utils/app_route.dart';
|
import '../utils/app_route.dart';
|
||||||
|
import 'settings_emotes.dart';
|
||||||
|
|
||||||
class SettingsView extends StatelessWidget {
|
class SettingsView extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
|
@ -226,11 +227,22 @@ class _SettingsState extends State<Settings> {
|
||||||
activeColor: Theme.of(context).primaryColor,
|
activeColor: Theme.of(context).primaryColor,
|
||||||
onChanged: (bool newValue) async {
|
onChanged: (bool newValue) async {
|
||||||
Matrix.of(context).renderHtml = newValue;
|
Matrix.of(context).renderHtml = newValue;
|
||||||
await client.storeAPI.setItem("chat.fluffy.renderHtml", newValue ? "1" : "0");
|
await client.storeAPI
|
||||||
|
.setItem("chat.fluffy.renderHtml", newValue ? "1" : "0");
|
||||||
setState(() => null);
|
setState(() => null);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10n.of(context).emoteSettings),
|
||||||
|
onTap: () async => await Navigator.of(context).push(
|
||||||
|
AppRoute.defaultRoute(
|
||||||
|
context,
|
||||||
|
EmotesSettingsView(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: Icon(Icons.insert_emoticon),
|
||||||
|
),
|
||||||
Divider(thickness: 1),
|
Divider(thickness: 1),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
|
|
398
lib/views/settings_emotes.dart
Normal file
398
lib/views/settings_emotes.dart
Normal file
|
@ -0,0 +1,398 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_advanced_networkimage/provider.dart';
|
||||||
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
||||||
|
|
||||||
|
import 'chat_list.dart';
|
||||||
|
import '../components/adaptive_page_layout.dart';
|
||||||
|
import '../components/matrix.dart';
|
||||||
|
import '../components/dialogs/simple_dialogs.dart';
|
||||||
|
import '../l10n/l10n.dart';
|
||||||
|
|
||||||
|
class EmotesSettingsView extends StatelessWidget {
|
||||||
|
final Room room;
|
||||||
|
|
||||||
|
EmotesSettingsView({this.room});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AdaptivePageLayout(
|
||||||
|
primaryPage: FocusPage.SECOND,
|
||||||
|
firstScaffold: ChatList(),
|
||||||
|
secondScaffold: EmotesSettings(room: room),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmotesSettings extends StatefulWidget {
|
||||||
|
final Room room;
|
||||||
|
|
||||||
|
EmotesSettings({this.room});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EmotesSettingsState createState() => _EmotesSettingsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmoteEntry {
|
||||||
|
String emote;
|
||||||
|
String mxc;
|
||||||
|
_EmoteEntry({this.emote, this.mxc});
|
||||||
|
|
||||||
|
String get emoteClean => emote.substring(1, emote.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmotesSettingsState extends State<EmotesSettings> {
|
||||||
|
List<_EmoteEntry> emotes;
|
||||||
|
bool showSave = false;
|
||||||
|
TextEditingController newEmoteController = TextEditingController();
|
||||||
|
TextEditingController newMxcController = TextEditingController();
|
||||||
|
|
||||||
|
Future<void> _save(BuildContext context) async {
|
||||||
|
if (readonly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debugPrint("Saving....");
|
||||||
|
final client = Matrix.of(context).client;
|
||||||
|
// be sure to preserve any data not in "short"
|
||||||
|
Map<String, dynamic> content;
|
||||||
|
if (widget.room != null) {
|
||||||
|
content = widget.room.getState('im.ponies.room_emotes')?.content ??
|
||||||
|
<String, dynamic>{};
|
||||||
|
} else {
|
||||||
|
content = client.accountData['im.ponies.user_emotes']?.content ??
|
||||||
|
<String, dynamic>{};
|
||||||
|
}
|
||||||
|
debugPrint(content.toString());
|
||||||
|
content['short'] = <String, String>{};
|
||||||
|
for (final emote in emotes) {
|
||||||
|
content['short'][emote.emote] = emote.mxc;
|
||||||
|
}
|
||||||
|
debugPrint(content.toString());
|
||||||
|
var path = '';
|
||||||
|
if (widget.room != null) {
|
||||||
|
path = '/client/r0/rooms/${widget.room.id}/state/im.ponies.room_emotes/';
|
||||||
|
} else {
|
||||||
|
path =
|
||||||
|
'/client/r0/user/${client.userID}/account_data/im.ponies.user_emotes';
|
||||||
|
}
|
||||||
|
debugPrint(path);
|
||||||
|
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||||
|
client.jsonRequest(
|
||||||
|
type: HTTPType.PUT,
|
||||||
|
action: path,
|
||||||
|
data: content,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get readonly => widget.room == null
|
||||||
|
? false
|
||||||
|
: !(widget.room.canSendEvent('im.ponies.room_emotes'));
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Client client = Matrix.of(context).client;
|
||||||
|
if (emotes == null) {
|
||||||
|
emotes = <_EmoteEntry>[];
|
||||||
|
Map<String, dynamic> emoteSource;
|
||||||
|
if (widget.room != null) {
|
||||||
|
emoteSource = widget.room.getState('im.ponies.room_emotes')?.content;
|
||||||
|
} else {
|
||||||
|
emoteSource = client.accountData['im.ponies.user_emotes']?.content;
|
||||||
|
}
|
||||||
|
if (emoteSource != null && emoteSource['short'] is Map) {
|
||||||
|
emoteSource['short'].forEach((key, value) {
|
||||||
|
if (key is String && value is String && value.startsWith('mxc://')) {
|
||||||
|
emotes.add(_EmoteEntry(emote: key, mxc: value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(L10n.of(context).emoteSettings),
|
||||||
|
),
|
||||||
|
floatingActionButton: showSave
|
||||||
|
? FloatingActionButton(
|
||||||
|
child: Icon(Icons.save, color: Colors.white),
|
||||||
|
onPressed: () async {
|
||||||
|
await _save(context);
|
||||||
|
setState(() {
|
||||||
|
showSave = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
body: StreamBuilder(
|
||||||
|
stream: widget.room?.onUpdate?.stream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
if (!readonly)
|
||||||
|
Container(
|
||||||
|
child: ListTile(
|
||||||
|
leading: Container(
|
||||||
|
width: 180.0,
|
||||||
|
height: 38,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
|
color: Theme.of(context).secondaryHeaderColor,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
controller: newEmoteController,
|
||||||
|
autocorrect: false,
|
||||||
|
minLines: 1,
|
||||||
|
maxLines: 1,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: L10n.of(context).emoteShortcode,
|
||||||
|
prefixText: ': ',
|
||||||
|
suffixText: ':',
|
||||||
|
prefixStyle: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
suffixStyle: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: _EmoteImagePicker(newMxcController),
|
||||||
|
trailing: InkWell(
|
||||||
|
child: Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: Colors.green,
|
||||||
|
size: 32.0,
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
debugPrint("blah");
|
||||||
|
if (newEmoteController.text == null ||
|
||||||
|
newEmoteController.text.isEmpty ||
|
||||||
|
newMxcController.text == null ||
|
||||||
|
newMxcController.text.isEmpty) {
|
||||||
|
await SimpleDialogs(context).inform(
|
||||||
|
contentText:
|
||||||
|
L10n.of(context).emoteWarnNeedToPick);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final emoteCode = ':${newEmoteController.text}:';
|
||||||
|
final mxc = newMxcController.text;
|
||||||
|
if (emotes.indexWhere((e) =>
|
||||||
|
e.emote == emoteCode && e.mxc != mxc) !=
|
||||||
|
-1) {
|
||||||
|
await SimpleDialogs(context).inform(
|
||||||
|
contentText: L10n.of(context).emoteExists);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!RegExp(r'^:[-\w]+:$').hasMatch(emoteCode)) {
|
||||||
|
await SimpleDialogs(context).inform(
|
||||||
|
contentText: L10n.of(context).emoteInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emotes.add(_EmoteEntry(emote: emoteCode, mxc: mxc));
|
||||||
|
await _save(context);
|
||||||
|
setState(() {
|
||||||
|
newEmoteController.text = '';
|
||||||
|
newMxcController.text = '';
|
||||||
|
showSave = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!readonly)
|
||||||
|
Divider(
|
||||||
|
height: 2,
|
||||||
|
thickness: 2,
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: emotes.isEmpty
|
||||||
|
? Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
L10n.of(context).noEmotesFound,
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ListView.separated(
|
||||||
|
separatorBuilder: (BuildContext context, int i) =>
|
||||||
|
Container(),
|
||||||
|
itemCount: emotes.length + 1,
|
||||||
|
itemBuilder: (BuildContext context, int i) {
|
||||||
|
if (i >= emotes.length) {
|
||||||
|
return Container(height: 70);
|
||||||
|
}
|
||||||
|
final emote = emotes[i];
|
||||||
|
final controller = TextEditingController();
|
||||||
|
controller.text = emote.emoteClean;
|
||||||
|
return ListTile(
|
||||||
|
leading: Container(
|
||||||
|
width: 180.0,
|
||||||
|
height: 38,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(10)),
|
||||||
|
color: Theme.of(context).secondaryHeaderColor,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
readOnly: readonly,
|
||||||
|
controller: controller,
|
||||||
|
autocorrect: false,
|
||||||
|
minLines: 1,
|
||||||
|
maxLines: 1,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: L10n.of(context).emoteShortcode,
|
||||||
|
prefixText: ': ',
|
||||||
|
suffixText: ':',
|
||||||
|
prefixStyle: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
suffixStyle: TextStyle(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
onSubmitted: (s) {
|
||||||
|
final emoteCode = ':${s}:';
|
||||||
|
if (emotes.indexWhere((e) =>
|
||||||
|
e.emote == emoteCode &&
|
||||||
|
e.mxc != emote.mxc) !=
|
||||||
|
-1) {
|
||||||
|
controller.text = emote.emoteClean;
|
||||||
|
SimpleDialogs(context).inform(
|
||||||
|
contentText:
|
||||||
|
L10n.of(context).emoteExists);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!RegExp(r'^:[-\w]+:$')
|
||||||
|
.hasMatch(emoteCode)) {
|
||||||
|
controller.text = emote.emoteClean;
|
||||||
|
SimpleDialogs(context).inform(
|
||||||
|
contentText:
|
||||||
|
L10n.of(context).emoteInvalid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
emote.emote = emoteCode;
|
||||||
|
showSave = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: _EmoteImage(emote.mxc),
|
||||||
|
trailing: readonly
|
||||||
|
? null
|
||||||
|
: InkWell(
|
||||||
|
child: Icon(
|
||||||
|
Icons.delete_forever,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 32.0,
|
||||||
|
),
|
||||||
|
onTap: () => setState(() {
|
||||||
|
emotes.removeWhere(
|
||||||
|
(e) => e.emote == emote.emote);
|
||||||
|
showSave = true;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmoteImage extends StatelessWidget {
|
||||||
|
final String mxc;
|
||||||
|
_EmoteImage(this.mxc);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final size = 38.0;
|
||||||
|
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
||||||
|
final url = Uri.parse(mxc)?.getThumbnail(
|
||||||
|
Matrix.of(context).client,
|
||||||
|
width: size * devicePixelRatio,
|
||||||
|
height: size * devicePixelRatio,
|
||||||
|
method: ThumbnailMethod.scale,
|
||||||
|
);
|
||||||
|
return Image(
|
||||||
|
image: AdvancedNetworkImage(
|
||||||
|
url,
|
||||||
|
useDiskCache: !kIsWeb,
|
||||||
|
),
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmoteImagePicker extends StatefulWidget {
|
||||||
|
final TextEditingController controller;
|
||||||
|
|
||||||
|
_EmoteImagePicker(this.controller);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EmoteImagePickerState createState() => _EmoteImagePickerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmoteImagePickerState extends State<_EmoteImagePicker> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (widget.controller.text == null || widget.controller.text.isEmpty) {
|
||||||
|
return RaisedButton(
|
||||||
|
color: Theme.of(context).primaryColor,
|
||||||
|
elevation: 5,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: Text(L10n.of(context).pickImage),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
if (kIsWeb) {
|
||||||
|
showToast(L10n.of(context).notSupportedInWeb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File file = await ImagePicker.pickImage(
|
||||||
|
source: ImageSource.gallery,
|
||||||
|
imageQuality: 50,
|
||||||
|
maxWidth: 128,
|
||||||
|
maxHeight: 128);
|
||||||
|
if (file == null) return;
|
||||||
|
final uploadResp =
|
||||||
|
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||||
|
Matrix.of(context).client.upload(
|
||||||
|
MatrixFile(bytes: await file.readAsBytes(), path: file.path),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
setState(() {
|
||||||
|
widget.controller.text = uploadResp;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return _EmoteImage(widget.controller.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue