feat(ui): Translate the entire UI
This commit is contained in:
parent
a30b8f888d
commit
192086546a
@ -1,7 +1,14 @@
|
|||||||
{
|
{
|
||||||
|
"global": {
|
||||||
|
"title": "Moxxy",
|
||||||
|
"moxxySubtitle": "An experiment into building a modern, easy and beautiful XMPP client.",
|
||||||
|
"dialogAccept": "Okay",
|
||||||
|
"dialogCancel": "Cancel",
|
||||||
|
"yes": "Yes",
|
||||||
|
"no": "No"
|
||||||
|
},
|
||||||
"pages": {
|
"pages": {
|
||||||
"intro": {
|
"intro": {
|
||||||
"subtitle": "An experiment into building a modern, easy and beautiful XMPP client.",
|
|
||||||
"noAccount": "Have no XMPP account? No worries, creating one is really easy.",
|
"noAccount": "Have no XMPP account? No worries, creating one is really easy.",
|
||||||
"loginButton": "Login",
|
"loginButton": "Login",
|
||||||
"registerButton": "Register"
|
"registerButton": "Register"
|
||||||
@ -20,6 +27,15 @@
|
|||||||
"noOpenChats": "You have no open chats",
|
"noOpenChats": "You have no open chats",
|
||||||
"startChat": "Start a chat"
|
"startChat": "Start a chat"
|
||||||
},
|
},
|
||||||
|
"conversation": {
|
||||||
|
"unencrypted": "Unencrypted",
|
||||||
|
"encrypted": "Encrypted",
|
||||||
|
"closeChat": "Close chat",
|
||||||
|
"closeChatConfirmTitle": "Close chat",
|
||||||
|
"closeChatConfirmSubtext": "Are you sure you want to close this chat?",
|
||||||
|
"blockUser": "Block user",
|
||||||
|
"online": "Online"
|
||||||
|
},
|
||||||
"addcontact": {
|
"addcontact": {
|
||||||
"title": "Add new contact",
|
"title": "Add new contact",
|
||||||
"xmppAddress": "XMPP-Address",
|
"xmppAddress": "XMPP-Address",
|
||||||
@ -49,6 +65,111 @@
|
|||||||
"muteChat": "Mute",
|
"muteChat": "Mute",
|
||||||
"unmuteChat": "Unmute",
|
"unmuteChat": "Unmute",
|
||||||
"devices": "Devices"
|
"devices": "Devices"
|
||||||
|
},
|
||||||
|
"owndevices": {
|
||||||
|
"title": "Own Devices",
|
||||||
|
"thisDevice": "This device",
|
||||||
|
"otherDevices": "Other devices",
|
||||||
|
"deleteDeviceConfirmTitle": "Delete device",
|
||||||
|
"deleteDeviceConfirmBody": "This means that contacts will not be able to encrypt for that device. Continue?",
|
||||||
|
"recreateOwnSessions": "Rebuild sessions",
|
||||||
|
"recreateOwnSessionsConfirmTitle": "Recreate own sessions?",
|
||||||
|
"recreateOwnSessionsConfirmBody": "This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors.",
|
||||||
|
"recreateOwnDevice": "Recreate device",
|
||||||
|
"recreateOwnDeviceConfirmTitle": "Recreate own device?",
|
||||||
|
"recreateOwnDeviceConfirmBody": "This will recreate this device's cryptographic identity. It will take some time. If contacts verified your device, they will have to do it again. Continue?"
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"title": "Devices",
|
||||||
|
"recreateSessions": "Rebuild sessions",
|
||||||
|
"recreateSessionsConfirmTitle": "Rebuild sessions?",
|
||||||
|
"recreateSessionsConfirmBody": "This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"blocklist": {
|
||||||
|
"title": "Blocklist",
|
||||||
|
"noUsersBlocked": "You have no users blocked",
|
||||||
|
"unblockAll": "Unblock all",
|
||||||
|
"unblockAllConfirmTitle": "Are you sure?",
|
||||||
|
"unblockAllConfirmBody": "Are you sure you want to unblock all users?",
|
||||||
|
"unblockJidConfirmTitle": "Unblock ${jid}?",
|
||||||
|
"unblockJidConfirmBody": "Are you sure you want to unblock ${jid}? You will receive messages from this user again."
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"settings": {
|
||||||
|
"title": "Settings",
|
||||||
|
"conversationsSection": "Conversations",
|
||||||
|
"accountSection": "Account",
|
||||||
|
"signOut": "Sign out",
|
||||||
|
"signOutConfirmTitle": "Sign Out",
|
||||||
|
"signOutConfirmBody": "You are about to sign out. Proceed?",
|
||||||
|
"miscellaneousSection": "Miscellaneous",
|
||||||
|
"debuggingSection": "Debugging"
|
||||||
|
},
|
||||||
|
"about": {
|
||||||
|
"title": "About",
|
||||||
|
"licensed": "Licensed under GPL3",
|
||||||
|
"viewSourceCode": "View source code"
|
||||||
|
},
|
||||||
|
"licenses": {
|
||||||
|
"title": "Open-Source Licenses",
|
||||||
|
"licensedUnder": "Licensed under $license"
|
||||||
|
},
|
||||||
|
"conversation": {
|
||||||
|
"title": "Chat",
|
||||||
|
"appearance": "Appearance",
|
||||||
|
"selectBackgroundImage": "Select background image",
|
||||||
|
"selectBackgroundImageDescription": "This image will be the background of all your chats",
|
||||||
|
"removeBackgroundImage": "Remove background image",
|
||||||
|
"removeBackgroundImageConfirmTitle": "Remove background image",
|
||||||
|
"removeBackgroundImageConfirmBody": "Are you sure you want to remove your conversation background image?",
|
||||||
|
"newChatsSection": "New Conversations",
|
||||||
|
"newChatsMuteByDefault": "Mute new chats by default",
|
||||||
|
"newChatsE2EE": "Enable end-to-end encryption by default. WARNING: Experimental"
|
||||||
|
},
|
||||||
|
"debugging": {
|
||||||
|
"title": "Debugging options",
|
||||||
|
"generalSection": "General",
|
||||||
|
"generalEnableDebugging": "Enable debugging",
|
||||||
|
"generalEncryptionPassword": "Encryption password",
|
||||||
|
"generalEncryptionPasswordSubtext": "The logs may contain sensitive information so pick a strong passphrase",
|
||||||
|
"generalLoggingIp": "Logging IP",
|
||||||
|
"generalLoggingIpSubtext": "The IP the logs should be sent to",
|
||||||
|
"generalLoggingPort": "Logging Port",
|
||||||
|
"generalLoggingPortSubtext": "The IP the logs should be sent to"
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"title": "Network",
|
||||||
|
"automaticDownloadsSection": "Automatic Downloads",
|
||||||
|
"automaticDownloadsText": "Moxxy will automatically download files on...",
|
||||||
|
"automaticDownloadsMaximumSize": "Maximum Download Size",
|
||||||
|
"automaticDownloadsMaximumSizeSubtext": "The maximum file size for a file to be automatically downloaded",
|
||||||
|
"wifi": "Wifi",
|
||||||
|
"mobileData": "Mobile data"
|
||||||
|
},
|
||||||
|
"privacy": {
|
||||||
|
"title": "Pricacy",
|
||||||
|
"generalSection": "General",
|
||||||
|
"showContactRequests": "Show contact requests",
|
||||||
|
"showContactRequestsSubtext": "This will show people who added you to their contact list but sent no message yet",
|
||||||
|
"profilePictureVisibility": "Make profile picture public",
|
||||||
|
"profilePictureVisibilitSubtext": "If enabled, everyone can see your profile picture. If disabled, only users on your contact list can see your profile picture.",
|
||||||
|
"autoAcceptSubscriptionRequests": "Auto-accept subscription requests",
|
||||||
|
"autoAcceptSubscriptionRequestsSubtext": "If enabled, subscription requests will be automatically accepted if the user is in the contact list.",
|
||||||
|
"conversationsSection": "Conversation",
|
||||||
|
"sendChatMarkers": "Send chat markers",
|
||||||
|
"sendChatMarkersSubtext": "This will tell your conversation partner if you received or read a message",
|
||||||
|
"sendChatStates": "Send chat states",
|
||||||
|
"sendChatStatesSubtext": "This will show your conversation partner if you are typing or looking at the chat",
|
||||||
|
"redirectsSection": "Redirects",
|
||||||
|
"redirectText": "This will redirect $serviceName links that you tap to a proxy service, e.g. $exampleProxy",
|
||||||
|
"currentlySelected": "Currently selected: $proxy",
|
||||||
|
"redirectsTitle": "$serviceName Redirect",
|
||||||
|
"cannotEnableRedirect": "Cannot enable $serviceName redirects",
|
||||||
|
"cannotEnableRedirectSubtext": "You must first set a proxy service to redirect to. To do so, tap the field next to the switch.",
|
||||||
|
"urlEmpty": "URL cannot be empty",
|
||||||
|
"urlInvalid": "Invalid URL",
|
||||||
|
"redirectDialogTitle": "$serviceName Redirect"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
{
|
{
|
||||||
|
"global": {
|
||||||
|
"title": "Moxxy",
|
||||||
|
"moxxySubtitle": "Ein Experiment im Entwickeln eines modernen, einfachen und schönen XMPP-Clients.",
|
||||||
|
"dialogAccept": "Okay",
|
||||||
|
"dialogCancel": "Abbrechen",
|
||||||
|
"yes": "Ja",
|
||||||
|
"no": "Nein"
|
||||||
|
},
|
||||||
"pages": {
|
"pages": {
|
||||||
"intro": {
|
"intro": {
|
||||||
"subtitle": "Ein Experiment im Entwickeln eines modernen, einfachen und schönen XMPP-Clients.",
|
|
||||||
"noAccount": "Kein XMPP-Account vorhanden? Einen zu erstellen ist sehr einfach.",
|
"noAccount": "Kein XMPP-Account vorhanden? Einen zu erstellen ist sehr einfach.",
|
||||||
"loginButton": "Einloggen",
|
"loginButton": "Einloggen",
|
||||||
"registerButton": "Registrieren"
|
"registerButton": "Registrieren"
|
||||||
@ -20,6 +27,15 @@
|
|||||||
"noOpenChats": "Du hast keine offenen chats",
|
"noOpenChats": "Du hast keine offenen chats",
|
||||||
"startChat": "Einen chat anfangen"
|
"startChat": "Einen chat anfangen"
|
||||||
},
|
},
|
||||||
|
"conversation": {
|
||||||
|
"unencrypted": "Unverschlüsselt",
|
||||||
|
"encrypted": "Verschlüsselt",
|
||||||
|
"closeChat": "Chat schließen",
|
||||||
|
"closeChatConfirmTitle": "Chat schließen",
|
||||||
|
"closeChatConfirmSubtext": "Bist Du dir sicher, dass du den Chat schließen möchtest?",
|
||||||
|
"blockUser": "Nutzer blockieren",
|
||||||
|
"online": "Online"
|
||||||
|
},
|
||||||
"addcontact": {
|
"addcontact": {
|
||||||
"title": "Neuen Kontakt hinzufügen",
|
"title": "Neuen Kontakt hinzufügen",
|
||||||
"xmppAddress": "XMPP-Adresse",
|
"xmppAddress": "XMPP-Adresse",
|
||||||
@ -37,7 +53,7 @@
|
|||||||
"shareselection": {
|
"shareselection": {
|
||||||
"shareWith": "Teilen mit...",
|
"shareWith": "Teilen mit...",
|
||||||
"confirmTitle": "Dateien senden?",
|
"confirmTitle": "Dateien senden?",
|
||||||
"confirmTitle": "Einer oder mehr Chats sind unverschlüsselt. Das bedeutet, dass die Dateien dem Server unverschlüsselt vorliegen. Dateien trotzdem senden?"
|
"confirmBody": "Einer oder mehr Chats sind unverschlüsselt. Das bedeutet, dass die Dateien dem Server unverschlüsselt vorliegen. Dateien trotzdem senden?"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"self": {
|
"self": {
|
||||||
@ -49,6 +65,111 @@
|
|||||||
"muteChat": "Stummschalten",
|
"muteChat": "Stummschalten",
|
||||||
"unmuteChat": "Lautstellen",
|
"unmuteChat": "Lautstellen",
|
||||||
"devices": "Geräte"
|
"devices": "Geräte"
|
||||||
|
},
|
||||||
|
"owndevices": {
|
||||||
|
"title": "Eigene Geräte",
|
||||||
|
"thisDevice": "Dieses Gerät",
|
||||||
|
"otherDevices": "Andere Geräte",
|
||||||
|
"deleteDeviceConfirmTitle": "Gerät löschen",
|
||||||
|
"deleteDeviceConfirmBody": "Das bedeutet, dass Kontakte für dieses Gerät nichtmehr verschlüsseln können. Fortfahren?",
|
||||||
|
"recreateOwnSessions": "Sessions neuerstellen",
|
||||||
|
"recreateOwnSessionsConfirmTitle": "Eigene Sessions neuerstellen?",
|
||||||
|
"recreateOwnSessionsConfirmBody": "Das wird alle kryptographischen Sessions mit den eigenen Geräten neuerstellen. Verwende dies nur, wenn deine eigenen Geräte Entschlüsselungsfehler erzeugen.",
|
||||||
|
"recreateOwnDevice": "Gerät neuerstellen",
|
||||||
|
"recreateOwnDeviceConfirmTitle": "Gerät neuerstellen?",
|
||||||
|
"recreateOwnDeviceConfirmBody": "Das wird die kryptographische Identität dieses Geräts neu erstellen. Wenn Kontakte die kryptographische Indentität verifiziert haben, dann müssen diese es erneut tun. Fortfahren?"
|
||||||
|
},
|
||||||
|
"devices": {
|
||||||
|
"title": "Devices",
|
||||||
|
"recreateSessions": "Rebuild sessions",
|
||||||
|
"recreateSessionsConfirmTitle": "Rebuild sessions?",
|
||||||
|
"recreateSessionsConfirmBody": "This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"blocklist": {
|
||||||
|
"title": "Blockliste",
|
||||||
|
"noUsersBlocked": "Du hast niemanden blockiert",
|
||||||
|
"unblockAll": "Alle entblocken",
|
||||||
|
"unblockAllConfirmTitle": "Alle entblocken",
|
||||||
|
"unblockAllConfirmBody": "Bist Du dir sicher, dass du alle geblockten Personen entblocken möchtest?",
|
||||||
|
"unblockJidConfirmTitle": "${jid} entblocken?",
|
||||||
|
"unblockJidConfirmBody": "Bist du dir sicher, dass du ${jid} entblocken möchtest? Du wirst wieder Nachrichten von dieser Person erhalten können."
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"settings": {
|
||||||
|
"title": "Einstellungen",
|
||||||
|
"conversationsSection": "Unterhaltungen",
|
||||||
|
"accountSection": "Account",
|
||||||
|
"signOut": "Abmelden",
|
||||||
|
"signOutConfirmTitle": "Abmelden",
|
||||||
|
"signOutConfirmBody": "Du bist dabei dich abzumelden. Fortfahren?",
|
||||||
|
"miscellaneousSection": "Unterschiedlich",
|
||||||
|
"debuggingSection": "Debugging"
|
||||||
|
},
|
||||||
|
"about": {
|
||||||
|
"title": "Über",
|
||||||
|
"licensed": "Lizensiert unter GPL3",
|
||||||
|
"viewSourceCode": "Quellcode anschauen"
|
||||||
|
},
|
||||||
|
"licenses": {
|
||||||
|
"title": "Open-Source Lizenzen",
|
||||||
|
"licensedUnder": "Lizensiert unter $license"
|
||||||
|
},
|
||||||
|
"conversation": {
|
||||||
|
"title": "Chat",
|
||||||
|
"appearance": "Aussehen",
|
||||||
|
"selectBackgroundImage": "Hintergrundbild auswählen",
|
||||||
|
"selectBackgroundImageDescription": "Dieses Bild wird als Hintergrundbild in allen Chats verwendet",
|
||||||
|
"removeBackgroundImage": "Hintergrundbild entfernen",
|
||||||
|
"removeBackgroundImageConfirmTitle": "Hintergrundbild entfernen",
|
||||||
|
"removeBackgroundImageConfirmBody": "Bist Du dir sicher, dass Du das Hintergrundbild entfernen möchtest?",
|
||||||
|
"newChatsSection": "Neue Chats",
|
||||||
|
"newChatsMuteByDefault": "Neue Chats standardmäßig stummschalten",
|
||||||
|
"newChatsE2EE": "Ende-zu-Ende-Verschlüsselung standardmäßig aktivieren. WARNUNG: Experimentell"
|
||||||
|
},
|
||||||
|
"debugging": {
|
||||||
|
"title": "Debuggingoptionen",
|
||||||
|
"generalSection": "Generell",
|
||||||
|
"generalEnableDebugging": "Debugging einschalten",
|
||||||
|
"generalEncryptionPassword": "Verschlüsselungspasswort",
|
||||||
|
"generalEncryptionPasswordSubtext": "Die Logs enthalten eventuell sensible Daten. Wähle also daher eine starke Passphrase",
|
||||||
|
"generalLoggingIp": "Logging-IP",
|
||||||
|
"generalLoggingIpSubtext": "Die IP-Adresse an die die Logs gesendet werden",
|
||||||
|
"generalLoggingPort": "Logging-Port",
|
||||||
|
"generalLoggingPortSubtext": "Der Port an den die Logs gesendet werden"
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"title": "Netzwerk",
|
||||||
|
"automaticDownloadsSection": "Automatische Downloads",
|
||||||
|
"automaticDownloadsText": "Moxxy läd Dateien automatisch herunter, wenn verbunden mit...",
|
||||||
|
"automaticDownloadsMaximumSize": "Maximale Downloadgröße",
|
||||||
|
"automaticDownloadsMaximumSizeSubtext": "Die maximale Dateigröße, die automatisch heruntergeladen werden soll",
|
||||||
|
"wifi": "Wifi",
|
||||||
|
"mobileData": "Mobile Daten"
|
||||||
|
},
|
||||||
|
"privacy": {
|
||||||
|
"title": "Privatsphäre",
|
||||||
|
"generalSection": "Generell",
|
||||||
|
"showContactRequests": "Kontaktanfragen zeigen",
|
||||||
|
"showContactRequestsSubtext": "Dies zeigt Personen in der Chatübersicht an, die Dich zu ihrer Kontaktliste hinzugefügt haben, aber noch keine Nachricht gesendet haben",
|
||||||
|
"profilePictureVisibility": "Öffentliches Profilbild",
|
||||||
|
"profilePictureVisibilitSubtext": "Wenn aktiviert, dann kann jeder Dein Profilbild sehen. Wenn deaktiviert, dann können nur Personen aus deiner Kontaktliste kein Profilbild sehen",
|
||||||
|
"autoAcceptSubscriptionRequests": "Subscriptionanfragen automatisch annehmen",
|
||||||
|
"autoAcceptSubscriptionRequestsSubtext": "Wenn aktiviert, dann werden Subscriptionanfragen automatisch angenommen, wenn die Person in deiner Kontaktliste ist",
|
||||||
|
"conversationsSection": "Unterhaltungen",
|
||||||
|
"sendChatMarkers": "Chatmarker senden",
|
||||||
|
"sendChatMarkersSubtext": "Dies teilt Deinem Gesprächspartner mit, ob du Nachrichten empfangen oder gelesen hast",
|
||||||
|
"sendChatStates": "Chatstates senden",
|
||||||
|
"sendChatStatesSubtext": "Dies teilt Deinem Gesprächspartner mit, ob du gerade im Chat aktiv bist oder schreibst",
|
||||||
|
"redirectsSection": "Weiterleitungen",
|
||||||
|
"redirectText": "Dies leitet Links von $serviceName, die du öffnest, an einen Proxydienst weiter, wie zum Beispiel $exampleProxy",
|
||||||
|
"currentlySelected": "Aktuell ausgewählt: $proxy",
|
||||||
|
"redirectsTitle": "${serviceName}weiterleitung",
|
||||||
|
"cannotEnableRedirect": "Kann ${serviceName}weiterleitung nicht aktivieren",
|
||||||
|
"cannotEnableRedirectSubtext": "Du must zuerst einen Proxydienst auswählen. Dazu berühre das Feld neben dem Schalter.",
|
||||||
|
"urlEmpty": "URL kann nicht leer sein",
|
||||||
|
"urlInvalid": "Ungültige URL",
|
||||||
|
"redirectDialogTitle": "${serviceName}weiterleitung"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:hex/hex.dart';
|
import 'package:hex/hex.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/shared/avatar.dart';
|
import 'package:moxxyv2/shared/avatar.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/crop_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/crop_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
@ -28,11 +29,11 @@ Future<void> showConfirmationDialog(String title, String body, BuildContext cont
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
child: const Text('Yes'),
|
child: Text(t.global.yes),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: Navigator.of(context).pop,
|
onPressed: Navigator.of(context).pop,
|
||||||
child: const Text('No'),
|
child: Text(t.global.no),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -59,7 +60,7 @@ Future<void> showNotImplementedDialog(String feature, BuildContext context) asyn
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Okay'),
|
child: Text(t.global.dialogAccept),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -82,7 +83,7 @@ Future<void> showInfoDialog(String title, String body, BuildContext context) asy
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: Navigator.of(context).pop,
|
onPressed: Navigator.of(context).pop,
|
||||||
child: const Text('Okay'),
|
child: Text(t.global.dialogAccept),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/blocklist_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/blocklist_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/helpers.dart';
|
import 'package:moxxyv2/ui/helpers.dart';
|
||||||
@ -30,9 +31,9 @@ class BlocklistPage extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.only(top: 8),
|
padding: const EdgeInsets.only(top: 8),
|
||||||
child: Image.asset('assets/images/happy_news.png'),
|
child: Image.asset('assets/images/happy_news.png'),
|
||||||
),
|
),
|
||||||
const Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 8),
|
padding: const EdgeInsets.only(top: 8),
|
||||||
child: Text('You have no users blocked'),
|
child: Text(t.pages.blocklist.noUsersBlocked),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -59,8 +60,8 @@ class BlocklistPage extends StatelessWidget {
|
|||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
onPressed: () => showConfirmationDialog(
|
onPressed: () => showConfirmationDialog(
|
||||||
'Unblock $jid?',
|
t.pages.blocklist.unblockJidConfirmTitle(jid: jid),
|
||||||
'Are you sure you want to unblock $jid? You will receive messages from this user again.',
|
t.pages.blocklist.unblockJidConfirmBody(jid: jid),
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
context.read<BlocklistBloc>().add(UnblockedJidEvent(jid));
|
context.read<BlocklistBloc>().add(UnblockedJidEvent(jid));
|
||||||
@ -79,15 +80,15 @@ class BlocklistPage extends StatelessWidget {
|
|||||||
return BlocBuilder<BlocklistBloc, BlocklistState>(
|
return BlocBuilder<BlocklistBloc, BlocklistState>(
|
||||||
builder: (context, state) => Scaffold(
|
builder: (context, state) => Scaffold(
|
||||||
appBar: BorderlessTopbar.simple(
|
appBar: BorderlessTopbar.simple(
|
||||||
'Blocklist',
|
t.pages.blocklist.title,
|
||||||
extra: [
|
extra: [
|
||||||
Expanded(child: Container()),
|
Expanded(child: Container()),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
onSelected: (BlocklistOptions result) {
|
onSelected: (BlocklistOptions result) {
|
||||||
if (result == BlocklistOptions.unblockAll) {
|
if (result == BlocklistOptions.unblockAll) {
|
||||||
showConfirmationDialog(
|
showConfirmationDialog(
|
||||||
'Are you sure?',
|
t.pages.blocklist.unblockAllConfirmTitle,
|
||||||
'Are you sure you want to unblock all users?',
|
t.pages.blocklist.unblockAllConfirmBody,
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
context.read<BlocklistBloc>().add(UnblockedAllEvent());
|
context.read<BlocklistBloc>().add(UnblockedAllEvent());
|
||||||
@ -98,10 +99,10 @@ class BlocklistPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
itemBuilder: (BuildContext context) => [
|
itemBuilder: (BuildContext context) => [
|
||||||
const PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: BlocklistOptions.unblockAll,
|
value: BlocklistOptions.unblockAll,
|
||||||
child: Text('Unblock all'),
|
child: Text(t.pages.blocklist.unblockAll),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:moxxmpp/moxxmpp.dart';
|
import 'package:moxxmpp/moxxmpp.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/conversation_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/conversation_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/conversations_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/conversations_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/profile_bloc.dart' as profile;
|
import 'package:moxxyv2/ui/bloc/profile_bloc.dart' as profile;
|
||||||
@ -59,9 +60,9 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case ChatState.paused:
|
case ChatState.paused:
|
||||||
case ChatState.active:
|
case ChatState.active:
|
||||||
return const Text(
|
return Text(
|
||||||
'Online',
|
t.pages.conversation.online,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.green,
|
color: Colors.green,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -130,8 +131,8 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget
|
|||||||
const Icon(Icons.lock) :
|
const Icon(Icons.lock) :
|
||||||
const Icon(Icons.lock_open),
|
const Icon(Icons.lock_open),
|
||||||
itemBuilder: (BuildContext c) => [
|
itemBuilder: (BuildContext c) => [
|
||||||
popupItemWithIcon(EncryptionOption.none, 'Unencrypted', Icons.lock_open),
|
popupItemWithIcon(EncryptionOption.none, t.pages.conversation.unencrypted, Icons.lock_open),
|
||||||
popupItemWithIcon(EncryptionOption.omemo, 'Encrypted', Icons.lock),
|
popupItemWithIcon(EncryptionOption.omemo, t.pages.conversation.encrypted, Icons.lock),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
@ -140,8 +141,8 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget
|
|||||||
switch (result) {
|
switch (result) {
|
||||||
case ConversationOption.close: {
|
case ConversationOption.close: {
|
||||||
showConfirmationDialog(
|
showConfirmationDialog(
|
||||||
'Close Chat',
|
t.pages.conversation.closeChatConfirmTitle,
|
||||||
'Are you sure you want to close this chat?',
|
t.pages.conversation.closeChatConfirmSubtext,
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
context.read<ConversationsBloc>().add(
|
context.read<ConversationsBloc>().add(
|
||||||
@ -159,8 +160,8 @@ class ConversationTopbar extends StatelessWidget implements PreferredSizeWidget
|
|||||||
},
|
},
|
||||||
icon: const Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
itemBuilder: (BuildContext c) => [
|
itemBuilder: (BuildContext c) => [
|
||||||
popupItemWithIcon(ConversationOption.close, 'Close chat', Icons.close),
|
popupItemWithIcon(ConversationOption.close, t.pages.conversation.closeChat, Icons.close),
|
||||||
popupItemWithIcon(ConversationOption.block, 'Block contact', Icons.block)
|
popupItemWithIcon(ConversationOption.block, t.pages.conversation.blockUser, Icons.block)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -40,7 +40,7 @@ class Intro extends StatelessWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge),
|
padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge),
|
||||||
child: Text(
|
child: Text(
|
||||||
t.pages.intro.subtitle,
|
t.global.moxxySubtitle,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: fontsizeBody,
|
fontSize: fontsizeBody,
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/devices_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/devices_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/helpers.dart';
|
import 'package:moxxyv2/ui/helpers.dart';
|
||||||
@ -60,8 +61,8 @@ class DevicesPage extends StatelessWidget {
|
|||||||
|
|
||||||
void _recreateSessions(BuildContext context) {
|
void _recreateSessions(BuildContext context) {
|
||||||
showConfirmationDialog(
|
showConfirmationDialog(
|
||||||
'Recreate sessions?',
|
t.pages.profile.devices.recreateSessionsConfirmTitle,
|
||||||
"This will recreate the cryptographic sessions with the contact. Use only if this device throws decryption errors or your contact's devices throw decryption errors.",
|
t.pages.profile.devices.recreateSessionsConfirmBody,
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
context.read<DevicesBloc>().add(SessionsRecreatedEvent());
|
context.read<DevicesBloc>().add(SessionsRecreatedEvent());
|
||||||
@ -74,7 +75,7 @@ class DevicesPage extends StatelessWidget {
|
|||||||
return BlocBuilder<DevicesBloc, DevicesState>(
|
return BlocBuilder<DevicesBloc, DevicesState>(
|
||||||
builder: (context, state) => Scaffold(
|
builder: (context, state) => Scaffold(
|
||||||
appBar: BorderlessTopbar.simple(
|
appBar: BorderlessTopbar.simple(
|
||||||
'Devices',
|
t.pages.profile.devices.title,
|
||||||
extra: [
|
extra: [
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
@ -88,7 +89,7 @@ class DevicesPage extends StatelessWidget {
|
|||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: DevicesOptions.recreateSessions,
|
value: DevicesOptions.recreateSessions,
|
||||||
enabled: state.devices.isNotEmpty,
|
enabled: state.devices.isNotEmpty,
|
||||||
child: const Text('Rebuild sessions'),
|
child: Text(t.pages.profile.devices.recreateSessions),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/own_devices_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/own_devices_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/helpers.dart';
|
import 'package:moxxyv2/ui/helpers.dart';
|
||||||
@ -65,15 +66,15 @@ class OwnDevicesPage extends StatelessWidget {
|
|||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Align(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 16,
|
left: 16,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'This device',
|
t.pages.profile.owndevices.thisDevice,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: fontsizeSubtitle,
|
fontSize: fontsizeSubtitle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -90,16 +91,16 @@ class OwnDevicesPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
...state.keys.isNotEmpty ?
|
...state.keys.isNotEmpty ?
|
||||||
[
|
[
|
||||||
const Align(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 32,
|
top: 32,
|
||||||
left: 16,
|
left: 16,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Other devices',
|
t.pages.profile.owndevices.otherDevices,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: fontsizeSubtitle,
|
fontSize: fontsizeSubtitle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -139,8 +140,8 @@ class OwnDevicesPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
onDeletePressed: () {
|
onDeletePressed: () {
|
||||||
showConfirmationDialog(
|
showConfirmationDialog(
|
||||||
'Delete device',
|
t.pages.profile.owndevices.deleteDeviceConfirmTitle,
|
||||||
'This means that contacts will not be able to encrypt for that device. Continue?',
|
t.pages.profile.owndevices.deleteDeviceConfirmBody,
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
context.read<OwnDevicesBloc>().add(OwnDeviceRemovedEvent(item.deviceId));
|
context.read<OwnDevicesBloc>().add(OwnDeviceRemovedEvent(item.deviceId));
|
||||||
@ -154,8 +155,8 @@ class OwnDevicesPage extends StatelessWidget {
|
|||||||
|
|
||||||
void _recreateSessions(BuildContext context) {
|
void _recreateSessions(BuildContext context) {
|
||||||
showConfirmationDialog(
|
showConfirmationDialog(
|
||||||
'Recreate own sessions?',
|
t.pages.profile.owndevices.recreateOwnSessionsConfirmTitle,
|
||||||
'This will recreate the cryptographic sessions with your own devices. Use only if your own devices throw decryption errors.',
|
t.pages.profile.owndevices.recreateOwnSessionsConfirmBody,
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
context.read<OwnDevicesBloc>().add(OwnSessionsRecreatedEvent());
|
context.read<OwnDevicesBloc>().add(OwnSessionsRecreatedEvent());
|
||||||
@ -165,8 +166,8 @@ class OwnDevicesPage extends StatelessWidget {
|
|||||||
|
|
||||||
void _recreateDevice(BuildContext context) {
|
void _recreateDevice(BuildContext context) {
|
||||||
showConfirmationDialog(
|
showConfirmationDialog(
|
||||||
'Recreate own device?',
|
t.pages.profile.owndevices.recreateOwnDeviceConfirmTitle,
|
||||||
"This will recreate this device's cryptographic identity. It might take some time and will cause decryption errors until you sent a message to your contacts. If they verified your device, they will have to do it again. Continue?",
|
t.pages.profile.owndevices.recreateOwnDeviceConfirmBody,
|
||||||
context,
|
context,
|
||||||
() {
|
() {
|
||||||
context.read<OwnDevicesBloc>().add(OwnDeviceRegeneratedEvent());
|
context.read<OwnDevicesBloc>().add(OwnDeviceRegeneratedEvent());
|
||||||
@ -179,7 +180,7 @@ class OwnDevicesPage extends StatelessWidget {
|
|||||||
return BlocBuilder<OwnDevicesBloc, OwnDevicesState>(
|
return BlocBuilder<OwnDevicesBloc, OwnDevicesState>(
|
||||||
builder: (context, state) => Scaffold(
|
builder: (context, state) => Scaffold(
|
||||||
appBar: BorderlessTopbar.simple(
|
appBar: BorderlessTopbar.simple(
|
||||||
'Own Devices',
|
t.pages.profile.owndevices.title,
|
||||||
extra: [
|
extra: [
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
@ -198,11 +199,11 @@ class OwnDevicesPage extends StatelessWidget {
|
|||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: OwnDevicesOptions.recreateSessions,
|
value: OwnDevicesOptions.recreateSessions,
|
||||||
enabled: state.keys.isNotEmpty,
|
enabled: state.keys.isNotEmpty,
|
||||||
child: const Text('Rebuild sessions'),
|
child: Text(t.pages.profile.owndevices.recreateOwnSessions),
|
||||||
),
|
),
|
||||||
const PopupMenuItem(
|
PopupMenuItem(
|
||||||
value: OwnDevicesOptions.recreateDevice,
|
value: OwnDevicesOptions.recreateDevice,
|
||||||
child: Text('Recreate identity'),
|
child: Text(t.pages.profile.owndevices.recreateOwnDevice),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
@ -24,7 +25,7 @@ class SettingsAboutPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: BorderlessTopbar.simple('About'),
|
appBar: BorderlessTopbar.simple(t.pages.settings.about.title),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge),
|
padding: const EdgeInsets.symmetric(horizontal: paddingVeryLarge),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -33,26 +34,26 @@ class SettingsAboutPage extends StatelessWidget {
|
|||||||
'assets/images/logo.png',
|
'assets/images/logo.png',
|
||||||
width: 200, height: 200,
|
width: 200, height: 200,
|
||||||
),
|
),
|
||||||
const Text(
|
Text(
|
||||||
'moxxy',
|
t.global.title,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 40,
|
fontSize: 40,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
'An experimental XMPP client that is beautiful, modern and easy to use',
|
t.global.moxxySubtitle,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Text('Licensed under GPL3'),
|
Text(t.pages.settings.about.licensed),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
child: const Text('View source code'),
|
child: Text(t.pages.settings.about.viewSourceCode),
|
||||||
onPressed: () => _openUrl('https://github.com/PapaTutuWawa/moxxyv2'),
|
onPressed: () => _openUrl('https://github.com/PapaTutuWawa/moxxyv2'),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/cropbackground_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/cropbackground_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||||
@ -63,16 +64,16 @@ class ConversationSettingsPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: BorderlessTopbar.simple('Chat'),
|
appBar: BorderlessTopbar.simple(t.pages.settings.conversation.title),
|
||||||
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
||||||
builder: (context, state) => SettingsList(
|
builder: (context, state) => SettingsList(
|
||||||
sections: [
|
sections: [
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Appearance'),
|
title: Text(t.pages.settings.conversation.appearance),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Select background image'),
|
title: Text(t.pages.settings.conversation.selectBackgroundImage),
|
||||||
description: const Text('This image will be the background of all your chats'),
|
description: Text(t.pages.settings.conversation.selectBackgroundImageDescription),
|
||||||
onPressed: (context) async {
|
onPressed: (context) async {
|
||||||
final backgroundPath = await _pickBackgroundImage();
|
final backgroundPath = await _pickBackgroundImage();
|
||||||
|
|
||||||
@ -85,11 +86,11 @@ class ConversationSettingsPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Remove background image'),
|
title: Text(t.pages.settings.conversation.removeBackgroundImage),
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
showConfirmationDialog(
|
showConfirmationDialog(
|
||||||
'Are you sure?',
|
t.pages.settings.conversation.removeBackgroundImageConfirmTitle,
|
||||||
'Are you sure you want to remove your conversation background image?',
|
t.pages.settings.conversation.removeBackgroundImageConfirmBody,
|
||||||
context,
|
context,
|
||||||
() async {
|
() async {
|
||||||
await _removeBackgroundImage(context, state);
|
await _removeBackgroundImage(context, state);
|
||||||
@ -100,10 +101,10 @@ class ConversationSettingsPage extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('New Conversations'),
|
title: Text(t.pages.settings.conversation.newChatsSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Mute new chats by default'),
|
title: Text(t.pages.settings.conversation.newChatsMuteByDefault),
|
||||||
initialValue: state.defaultMuteState,
|
initialValue: state.defaultMuteState,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -112,7 +113,7 @@ class ConversationSettingsPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Enable end-to-end encryption by default. WARNING: Experimental'),
|
title: Text(t.pages.settings.conversation.newChatsE2EE),
|
||||||
initialValue: state.enableOmemoByDefault,
|
initialValue: state.enableOmemoByDefault,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
@ -7,7 +8,6 @@ import 'package:moxxyv2/ui/widgets/topbar.dart';
|
|||||||
import 'package:settings_ui/settings_ui.dart';
|
import 'package:settings_ui/settings_ui.dart';
|
||||||
|
|
||||||
class DebuggingPage extends StatelessWidget {
|
class DebuggingPage extends StatelessWidget {
|
||||||
|
|
||||||
DebuggingPage({ super.key })
|
DebuggingPage({ super.key })
|
||||||
: _ipController = TextEditingController(),
|
: _ipController = TextEditingController(),
|
||||||
_passphraseController = TextEditingController(),
|
_passphraseController = TextEditingController(),
|
||||||
@ -26,15 +26,15 @@ class DebuggingPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: BorderlessTopbar.simple('Debugging'),
|
appBar: BorderlessTopbar.simple(t.pages.settings.debugging.title),
|
||||||
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
||||||
builder: (context, state) => SettingsList(
|
builder: (context, state) => SettingsList(
|
||||||
sections: [
|
sections: [
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('General'),
|
title: Text(t.pages.settings.debugging.generalSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Enable debugging'),
|
title: Text(t.pages.settings.debugging.generalEnableDebugging),
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
state.copyWith(debugEnabled: value),
|
state.copyWith(debugEnabled: value),
|
||||||
@ -43,14 +43,14 @@ class DebuggingPage extends StatelessWidget {
|
|||||||
initialValue: state.debugEnabled,
|
initialValue: state.debugEnabled,
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Encryption password'),
|
title: Text(t.pages.settings.debugging.generalEncryptionPassword),
|
||||||
description: const Text('The logs may contain sensitive information so pick a strong passphrase'),
|
description: Text(t.pages.settings.debugging.generalEncryptionPasswordSubtext),
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
showDialog<void>(
|
showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => AlertDialog(
|
||||||
title: const Text('Debug Passphrase'),
|
title: Text(t.pages.settings.debugging.generalEncryptionPassword),
|
||||||
content: TextField(
|
content: TextField(
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
@ -58,7 +58,7 @@ class DebuggingPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Okay'),
|
child: Text(t.global.dialogAccept),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.read<PreferencesBloc>().add(
|
context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -74,21 +74,21 @@ class DebuggingPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Logging IP'),
|
title: Text(t.pages.settings.debugging.generalLoggingIp),
|
||||||
description: const Text('The IP the logs should be sent to'),
|
description: Text(t.pages.settings.debugging.generalLoggingIpSubtext),
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
showDialog<void>(
|
showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => AlertDialog(
|
||||||
title: const Text('Logging IP'),
|
title: Text(t.pages.settings.debugging.generalLoggingIp),
|
||||||
content: TextField(
|
content: TextField(
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
controller: _ipController,
|
controller: _ipController,
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Okay'),
|
child: Text(t.global.dialogAccept),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.read<PreferencesBloc>().add(
|
context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -104,14 +104,14 @@ class DebuggingPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Logging Port'),
|
title: Text(t.pages.settings.debugging.generalLoggingPort),
|
||||||
description: const Text('The Port the logs should be sent to'),
|
description: Text(t.pages.settings.debugging.generalLoggingPortSubtext),
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
showDialog<void>(
|
showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: true,
|
barrierDismissible: true,
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => AlertDialog(
|
||||||
title: const Text('Logging Port'),
|
title: Text(t.pages.settings.debugging.generalLoggingPort),
|
||||||
content: TextField(
|
content: TextField(
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
controller: _portController,
|
controller: _portController,
|
||||||
@ -119,7 +119,7 @@ class DebuggingPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Okay'),
|
child: Text(t.global.dialogAccept),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.read<PreferencesBloc>().add(
|
context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
import 'package:moxxyv2/ui/widgets/topbar.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
@ -31,7 +32,7 @@ class LicenseRow extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(library.name),
|
title: Text(library.name),
|
||||||
subtitle: Text('Licensed under ${library.license}'),
|
subtitle: Text(t.pages.settings.licenses.licensedUnder(license: library.license)),
|
||||||
onTap: _openUrl,
|
onTap: _openUrl,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -50,7 +51,7 @@ class SettingsLicensesPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: BorderlessTopbar.simple('Licenses'),
|
appBar: BorderlessTopbar.simple(t.pages.settings.licenses.title),
|
||||||
body: ListView.builder(
|
body: ListView.builder(
|
||||||
itemCount: usedLibraryList.length,
|
itemCount: usedLibraryList.length,
|
||||||
itemBuilder: (context, index) => LicenseRow(library: usedLibraryList[index]),
|
itemBuilder: (context, index) => LicenseRow(library: usedLibraryList[index]),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
@ -66,18 +67,18 @@ class NetworkPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: BorderlessTopbar.simple('Network'),
|
appBar: BorderlessTopbar.simple(t.pages.settings.network.title),
|
||||||
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
||||||
builder: (context, state) => SettingsList(
|
builder: (context, state) => SettingsList(
|
||||||
sections: [
|
sections: [
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Automatic Downloads'),
|
title: Text(t.pages.settings.network.automaticDownloadsSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Moxxy will automatically download files on...'),
|
title: Text(t.pages.settings.network.automaticDownloadsText),
|
||||||
),
|
),
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Wifi'),
|
title: Text(t.pages.settings.network.wifi),
|
||||||
initialValue: state.autoDownloadWifi,
|
initialValue: state.autoDownloadWifi,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -86,7 +87,7 @@ class NetworkPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Mobile Data'),
|
title: Text(t.pages.settings.network.mobileData),
|
||||||
initialValue: state.autoDownloadMobile,
|
initialValue: state.autoDownloadMobile,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -95,8 +96,8 @@ class NetworkPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Maximum Download Size'),
|
title: Text(t.pages.settings.network.automaticDownloadsMaximumSize),
|
||||||
description: const Text('The maximum file size for a file to be automatically downloaded'),
|
description: Text(t.pages.settings.network.automaticDownloadsMaximumSizeSubtext),
|
||||||
onPressed: (context) {
|
onPressed: (context) {
|
||||||
showModalBottomSheet<dynamic>(
|
showModalBottomSheet<dynamic>(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
@ -20,16 +21,16 @@ class PrivacyPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: BorderlessTopbar.simple('Privacy'),
|
appBar: BorderlessTopbar.simple(t.pages.settings.privacy.title),
|
||||||
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
body: BlocBuilder<PreferencesBloc, PreferencesState>(
|
||||||
builder: (context, state) => SettingsList(
|
builder: (context, state) => SettingsList(
|
||||||
sections: [
|
sections: [
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('General'),
|
title: Text(t.pages.settings.privacy.generalSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Show contact requests'),
|
title: Text(t.pages.settings.privacy.showContactRequests),
|
||||||
description: const Text('This will show people who added you to their contact list but sent no message yet'),
|
description: Text(t.pages.settings.privacy.showContactRequestsSubtext),
|
||||||
initialValue: state.showSubscriptionRequests,
|
initialValue: state.showSubscriptionRequests,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -38,8 +39,8 @@ class PrivacyPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Make profile picture public'),
|
title: Text(t.pages.settings.privacy.profilePictureVisibility),
|
||||||
description: const Text('If enabled, everyone can see your profile picture. If disabled, only users on your contact list can see your profile picture.'),
|
description: Text(t.pages.settings.privacy.profilePictureVisibilitSubtext),
|
||||||
initialValue: state.isAvatarPublic,
|
initialValue: state.isAvatarPublic,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -48,8 +49,8 @@ class PrivacyPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Auto-accept subscription requests'),
|
title: Text(t.pages.settings.privacy.autoAcceptSubscriptionRequests),
|
||||||
description: const Text('If enabled, subscription requests will be automatically accepted if the user is in the contact list.'),
|
description: Text(t.pages.settings.privacy.autoAcceptSubscriptionRequestsSubtext),
|
||||||
initialValue: state.autoAcceptSubscriptionRequests,
|
initialValue: state.autoAcceptSubscriptionRequests,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -60,11 +61,11 @@ class PrivacyPage extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Conversation'),
|
title: Text(t.pages.settings.privacy.conversationsSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Send chat markers'),
|
title: Text(t.pages.settings.privacy.sendChatMarkers),
|
||||||
description: const Text('This will tell your conversation partner if you received or read a message'),
|
description: Text(t.pages.settings.privacy.sendChatMarkersSubtext),
|
||||||
initialValue: state.sendChatMarkers,
|
initialValue: state.sendChatMarkers,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -73,8 +74,8 @@ class PrivacyPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
title: const Text('Send chat states'),
|
title: Text(t.pages.settings.privacy.sendChatStates),
|
||||||
description: const Text('This will show your conversation partner if you are typing or looking at the chat'),
|
description: Text(t.pages.settings.privacy.sendChatStatesSubtext),
|
||||||
initialValue: state.sendChatStates,
|
initialValue: state.sendChatStates,
|
||||||
onToggle: (value) => context.read<PreferencesBloc>().add(
|
onToggle: (value) => context.read<PreferencesBloc>().add(
|
||||||
PreferencesChangedEvent(
|
PreferencesChangedEvent(
|
||||||
@ -85,7 +86,7 @@ class PrivacyPage extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Redirects'),
|
title: Text(t.pages.settings.privacy.redirectsSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
RedirectSettingsTile(
|
RedirectSettingsTile(
|
||||||
'Youtube',
|
'Youtube',
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/widgets/textfield.dart';
|
import 'package:moxxyv2/ui/widgets/textfield.dart';
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ class RedirectDialogState extends State<RedirectDialog> {
|
|||||||
|
|
||||||
if (value.isEmpty) {
|
if (value.isEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
errorText = 'URL cannot be empty';
|
errorText = t.pages.settings.privacy.urlEmpty;
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -30,7 +31,7 @@ class RedirectDialogState extends State<RedirectDialog> {
|
|||||||
final parsed = Uri.tryParse(value);
|
final parsed = Uri.tryParse(value);
|
||||||
if (parsed == null) {
|
if (parsed == null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
errorText = 'Invalid URL';
|
errorText = t.pages.settings.privacy.urlInvalid;
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -48,7 +49,9 @@ class RedirectDialogState extends State<RedirectDialog> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text('${widget.serviceName} Redirect'),
|
title: Text(
|
||||||
|
t.pages.settings.privacy.redirectDialogTitle(serviceName: widget.serviceName),
|
||||||
|
),
|
||||||
content: Padding(
|
content: Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -76,7 +79,7 @@ class RedirectDialogState extends State<RedirectDialog> {
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Okay'),
|
child: Text(t.global.dialogAccept),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_validateUrl()) {
|
if (_validateUrl()) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@ -86,7 +89,7 @@ class RedirectDialogState extends State<RedirectDialog> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: const Text('Cancel'),
|
child: Text(t.global.dialogCancel),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/shared/models/preferences.dart';
|
import 'package:moxxyv2/shared/models/preferences.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/helpers.dart';
|
import 'package:moxxyv2/ui/helpers.dart';
|
||||||
@ -27,16 +28,23 @@ class RedirectSettingsTile extends AbstractSettingsTile {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<PreferencesBloc, PreferencesState>(
|
return BlocBuilder<PreferencesBloc, PreferencesState>(
|
||||||
builder: (context, state) => SettingsTile(
|
builder: (context, state) => SettingsTile(
|
||||||
title: Text('$serviceName Redirect'),
|
title: Text(t.pages.settings.privacy.redirectsTitle(serviceName: serviceName)),
|
||||||
description: Column(
|
description: Column(
|
||||||
children: [
|
children: [
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text('This will redirect $serviceName links that you tap to a proxy service, e.g. $exampleProxy'),
|
child: Text(
|
||||||
|
t.pages.settings.privacy.redirectText(
|
||||||
|
serviceName: serviceName,
|
||||||
|
exampleProxy: exampleProxy,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text('Currently selected: ${getProxy(state)}'),
|
child: Text(
|
||||||
|
t.pages.settings.privacy.currentlySelected(proxy: getProxy(state)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -58,8 +66,8 @@ class RedirectSettingsTile extends AbstractSettingsTile {
|
|||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (getProxy(state).isEmpty) {
|
if (getProxy(state).isEmpty) {
|
||||||
showInfoDialog(
|
showInfoDialog(
|
||||||
'Cannot enable $serviceName redirects',
|
t.pages.settings.privacy.cannotEnableRedirect(serviceName: serviceName),
|
||||||
'You must first set a proxy service to redirect to. To do so, tap the field next to the switch.',
|
t.pages.settings.privacy.cannotEnableRedirectSubtext,
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:moxxyv2/i18n/strings.g.dart';
|
||||||
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
import 'package:moxxyv2/ui/bloc/preferences_bloc.dart';
|
||||||
import 'package:moxxyv2/ui/constants.dart';
|
import 'package:moxxyv2/ui/constants.dart';
|
||||||
import 'package:moxxyv2/ui/helpers.dart';
|
import 'package:moxxyv2/ui/helpers.dart';
|
||||||
@ -20,43 +21,43 @@ class SettingsPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: BorderlessTopbar.simple('Settings'),
|
appBar: BorderlessTopbar.simple(t.pages.settings.settings.title),
|
||||||
body: SettingsList(
|
body: SettingsList(
|
||||||
sections: [
|
sections: [
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Conversations'),
|
title: Text(t.pages.settings.settings.conversationsSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Chat'),
|
title: Text(t.pages.settings.conversation.title),
|
||||||
leading: const Icon(Icons.chat_bubble),
|
leading: const Icon(Icons.chat_bubble),
|
||||||
onPressed: (context) => Navigator.pushNamed(context, conversationSettingsRoute),
|
onPressed: (context) => Navigator.pushNamed(context, conversationSettingsRoute),
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Network'),
|
title: Text(t.pages.settings.network.title),
|
||||||
leading: const Icon(Icons.network_wifi),
|
leading: const Icon(Icons.network_wifi),
|
||||||
onPressed: (context) => Navigator.pushNamed(context, networkRoute),
|
onPressed: (context) => Navigator.pushNamed(context, networkRoute),
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Privacy'),
|
title: Text(t.pages.settings.privacy.title),
|
||||||
leading: const Icon(Icons.shield),
|
leading: const Icon(Icons.shield),
|
||||||
onPressed: (context) => Navigator.pushNamed(context, privacyRoute),
|
onPressed: (context) => Navigator.pushNamed(context, privacyRoute),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Account'),
|
title: Text(t.pages.settings.settings.accountSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Blocklist'),
|
title: Text(t.pages.blocklist.title),
|
||||||
leading: const Icon(Icons.block),
|
leading: const Icon(Icons.block),
|
||||||
onPressed: (context) => Navigator.pushNamed(context, blocklistRoute),
|
onPressed: (context) => Navigator.pushNamed(context, blocklistRoute),
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Sign out'),
|
title: Text(t.pages.settings.settings.signOut),
|
||||||
leading: const Icon(Icons.logout),
|
leading: const Icon(Icons.logout),
|
||||||
onPressed: (context) => showConfirmationDialog(
|
onPressed: (context) => showConfirmationDialog(
|
||||||
'Sign Out',
|
t.pages.settings.settings.signOutConfirmTitle,
|
||||||
'You are about to sign out. Proceed?',
|
t.pages.settings.settings.signOutConfirmBody,
|
||||||
context,
|
context,
|
||||||
() async {
|
() async {
|
||||||
GetIt.I.get<PreferencesBloc>().add(SignedOutEvent());
|
GetIt.I.get<PreferencesBloc>().add(SignedOutEvent());
|
||||||
@ -66,15 +67,15 @@ class SettingsPage extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Miscellaneous'),
|
title: Text(t.pages.settings.settings.miscellaneousSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('About'),
|
title: Text(t.pages.settings.about.title),
|
||||||
leading: const Icon(Icons.info),
|
leading: const Icon(Icons.info),
|
||||||
onPressed: (context) => Navigator.pushNamed(context, aboutRoute),
|
onPressed: (context) => Navigator.pushNamed(context, aboutRoute),
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Open-Source licenses'),
|
title: Text(t.pages.settings.licenses.title),
|
||||||
leading: const Icon(Icons.description),
|
leading: const Icon(Icons.description),
|
||||||
onPressed: (context) => Navigator.pushNamed(context, licensesRoute),
|
onPressed: (context) => Navigator.pushNamed(context, licensesRoute),
|
||||||
)
|
)
|
||||||
@ -83,10 +84,10 @@ class SettingsPage extends StatelessWidget {
|
|||||||
// TODO(Unknown): Maybe also have a switch somewhere
|
// TODO(Unknown): Maybe also have a switch somewhere
|
||||||
...kDebugMode ? [
|
...kDebugMode ? [
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: const Text('Debugging'),
|
title: Text(t.pages.settings.settings.debuggingSection),
|
||||||
tiles: [
|
tiles: [
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
title: const Text('Debugging options'),
|
title: Text(t.pages.settings.debugging.title),
|
||||||
leading: const Icon(Icons.info),
|
leading: const Icon(Icons.info),
|
||||||
onPressed: (context) => Navigator.pushNamed(context, debuggingRoute),
|
onPressed: (context) => Navigator.pushNamed(context, debuggingRoute),
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user