Merge branch 'nsis' of git.openprivacy.ca:cwtch.im/cwtch-ui into nsis

This commit is contained in:
Dan Ballard 2021-06-30 12:40:20 -07:00
commit 24f0c84471
14 changed files with 209 additions and 179 deletions

View File

@ -1 +1 @@
v1.0.0-7-g520d35a-2021-06-25-16-34 v1.0.0-12-g2e0b6ef-2021-06-29-23-42

View File

@ -60,10 +60,11 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
val evt = MainActivity.AppbusEvent(Cwtch.getAppBusEvent()) val evt = MainActivity.AppbusEvent(Cwtch.getAppBusEvent())
if (evt.EventType == "NewMessageFromPeer" || evt.EventType == "NewMessageFromGroup") { if (evt.EventType == "NewMessageFromPeer" || evt.EventType == "NewMessageFromGroup") {
val data = JSONObject(evt.Data) val data = JSONObject(evt.Data)
val handle = if (evt.EventType == "NewMessageFromPeer") data.getString("RemotePeer") else data.getString("GroupID");
if (data["RemotePeer"] != data["ProfileOnion"]) { if (data["RemotePeer"] != data["ProfileOnion"]) {
val channelId = val channelId =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createMessageNotificationChannel(data.getString("RemotePeer"), data.getString("RemotePeer")) createMessageNotificationChannel(handle, handle)
} else { } else {
// If earlier version channel ID is not used // If earlier version channel ID is not used
// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context) // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
@ -74,11 +75,12 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
val key = loader.getLookupKeyForAsset("assets/" + data.getString("Picture"))//"assets/profiles/001-centaur.png") val key = loader.getLookupKeyForAsset("assets/" + data.getString("Picture"))//"assets/profiles/001-centaur.png")
val fh = applicationContext.assets.open(key) val fh = applicationContext.assets.open(key)
val clickIntent = Intent(applicationContext, MainActivity::class.java).also { intent -> val clickIntent = Intent(applicationContext, MainActivity::class.java).also { intent ->
intent.action = Intent.ACTION_RUN intent.action = Intent.ACTION_RUN
intent.putExtra("EventType", "NotificationClicked") intent.putExtra("EventType", "NotificationClicked")
intent.putExtra("ProfileOnion", data.getString("ProfileOnion")) intent.putExtra("ProfileOnion", data.getString("ProfileOnion"))
intent.putExtra("RemotePeer", if (evt.EventType == "NewMessageFromPeer") data.getString("RemotePeer") else data.getString("GroupID")) intent.putExtra("Handle", handle)
} }
val newNotification = NotificationCompat.Builder(applicationContext, channelId) val newNotification = NotificationCompat.Builder(applicationContext, channelId)
@ -89,7 +91,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
.setContentIntent(PendingIntent.getActivity(applicationContext, 1, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT)) .setContentIntent(PendingIntent.getActivity(applicationContext, 1, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setAutoCancel(true) .setAutoCancel(true)
.build() .build()
notificationManager.notify(getNotificationID(data.getString("ProfileOnion"), data.getString("RemotePeer")), newNotification) notificationManager.notify(getNotificationID(data.getString("ProfileOnion"), handle), newNotification)
} }
} }
@ -176,7 +178,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
"CreateGroup" -> { "CreateGroup" -> {
val profile = (a.get("ProfileOnion") as? String) ?: "" val profile = (a.get("ProfileOnion") as? String) ?: ""
val server = (a.get("server") as? String) ?: "" val server = (a.get("server") as? String) ?: ""
val groupName = (a.get("groupname") as? String) ?: "" val groupName = (a.get("groupName") as? String) ?: ""
Cwtch.createGroup(profile, server, groupName) Cwtch.createGroup(profile, server, groupName)
} }
"DeleteProfile" -> { "DeleteProfile" -> {

View File

@ -52,13 +52,13 @@ class MainActivity: FlutterActivity() {
if (notificationClickChannel == null || intent.extras == null) return if (notificationClickChannel == null || intent.extras == null) return
if (intent.extras!!.getString("EventType") == "NotificationClicked") { if (intent.extras!!.getString("EventType") == "NotificationClicked") {
if (!intent.extras!!.containsKey("ProfileOnion") || !intent.extras!!.containsKey("RemotePeer")) { if (!intent.extras!!.containsKey("ProfileOnion") || !intent.extras!!.containsKey("Handle")) {
Log.i("onNewIntent", "got notification clicked intent with no onions") Log.i("onNewIntent", "got notification clicked intent with no onions")
return return
} }
val profile = intent.extras!!.getString("ProfileOnion") val profile = intent.extras!!.getString("ProfileOnion")
val handle = intent.extras!!.getString("RemotePeer") val handle = intent.extras!!.getString("Handle")
val mappo = mapOf("ProfileOnion" to profile, "RemotePeer" to handle) val mappo = mapOf("ProfileOnion" to profile, "Handle" to handle)
val j = JSONObject(mappo) val j = JSONObject(mappo)
notificationClickChannel!!.invokeMethod("NotificationClicked", j.toString()) notificationClickChannel!!.invokeMethod("NotificationClicked", j.toString())
} else if (intent.extras!!.getString("EventType") == "ShutdownClicked") { } else if (intent.extras!!.getString("EventType") == "ShutdownClicked") {

View File

@ -245,6 +245,7 @@ class CwtchNotifier {
break; break;
case "ServerStateChange": case "ServerStateChange":
// Update the Server Cache // Update the Server Cache
EnvironmentConfig.debugLog("server state changes $data");
profileCN.getProfile(data["ProfileOnion"])?.updateServerStatusCache(data["GroupServer"], data["ConnectionState"]); profileCN.getProfile(data["ProfileOnion"])?.updateServerStatusCache(data["GroupServer"], data["ConnectionState"]);
profileCN.getProfile(data["ProfileOnion"])?.contactList.contacts.forEach((contact) { profileCN.getProfile(data["ProfileOnion"])?.contactList.contacts.forEach((contact) {
if (contact.isGroup == true && contact.server == data["GroupServer"]) { if (contact.isGroup == true && contact.server == data["GroupServer"]) {

View File

@ -1,6 +1,8 @@
{ {
"@@locale": "de", "@@locale": "de",
"@@last_modified": "2021-06-25T21:14:59+02:00", "@@last_modified": "2021-06-29T19:15:43+02:00",
"tooltipRejectContactRequest": "Reject this contact request",
"tooltipAcceptContactRequest": "Accept this contact request.",
"notificationNewMessageFromGroup": "Neue Nachricht in einer Gruppe!", "notificationNewMessageFromGroup": "Neue Nachricht in einer Gruppe!",
"notificationNewMessageFromPeer": "Neue Nachricht von einem Kontakt!", "notificationNewMessageFromPeer": "Neue Nachricht von einem Kontakt!",
"tooltipHidePassword": "Password verstecken", "tooltipHidePassword": "Password verstecken",
@ -192,4 +194,4 @@
"createGroupBtn": "Anlegen", "createGroupBtn": "Anlegen",
"defaultGroupName": "Tolle Gruppe", "defaultGroupName": "Tolle Gruppe",
"createGroupTitle": "Gruppe Anlegen" "createGroupTitle": "Gruppe Anlegen"
} }

View File

@ -1,6 +1,8 @@
{ {
"@@locale": "en", "@@locale": "en",
"@@last_modified": "2021-06-25T18:57:59+02:00", "@@last_modified": "2021-06-29T19:15:43+02:00",
"tooltipRejectContactRequest": "Reject this contact request",
"tooltipAcceptContactRequest": "Accept this contact request.",
"notificationNewMessageFromGroup": "New message in a group!", "notificationNewMessageFromGroup": "New message in a group!",
"notificationNewMessageFromPeer": "New message from a contact!", "notificationNewMessageFromPeer": "New message from a contact!",
"tooltipHidePassword": "Hide Password", "tooltipHidePassword": "Hide Password",

View File

@ -1,6 +1,8 @@
{ {
"@@locale": "es", "@@locale": "es",
"@@last_modified": "2021-06-25T18:57:59+02:00", "@@last_modified": "2021-06-29T19:15:43+02:00",
"tooltipRejectContactRequest": "Reject this contact request",
"tooltipAcceptContactRequest": "Accept this contact request.",
"notificationNewMessageFromGroup": "New message in a group!", "notificationNewMessageFromGroup": "New message in a group!",
"notificationNewMessageFromPeer": "New message from a contact!", "notificationNewMessageFromPeer": "New message from a contact!",
"tooltipHidePassword": "Hide Password", "tooltipHidePassword": "Hide Password",

View File

@ -1,138 +1,140 @@
{ {
"@@locale": "fr", "@@locale": "fr",
"@@last_modified": "2021-06-25T18:57:59+02:00", "@@last_modified": "2021-06-29T19:15:43+02:00",
"notificationNewMessageFromGroup": "New message in a group!", "tooltipRejectContactRequest": "Reject this contact request",
"notificationNewMessageFromPeer": "New message from a contact!", "tooltipAcceptContactRequest": "Accept this contact request.",
"tooltipHidePassword": "Hide Password", "notificationNewMessageFromGroup": "Nouveau message dans un groupe !",
"tooltipShowPassword": "Show Password", "notificationNewMessageFromPeer": "Nouveau message d'un contact !",
"serverNotSynced": "Syncing New Messages (This can take some time)...", "tooltipHidePassword": "Masquer le mot de passe",
"groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.", "tooltipShowPassword": "Afficher le mot de passe",
"shutdownCwtchAction": "Shutdown Cwtch", "serverNotSynced": "Synchronisation des nouveaux messages (Cela peut prendre un certain temps)...",
"shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.", "groupInviteSettingsWarning": "Vous avez été invité à rejoindre un groupe ! Veuillez activer l'expérience de discussion de groupe dans les paramètres pour afficher cette invitation.",
"shutdownCwtchDialogTitle": "Shutdown Cwtch?", "shutdownCwtchAction": "Arrêt Cwtch",
"shutdownCwtchTooltip": "Shutdown Cwtch", "shutdownCwtchDialog": "Êtes-vous sûr de vouloir arrêter Cwtch ? Ceci fermera toutes les connexions, et quittera l'application.",
"malformedMessage": "Malformed message", "shutdownCwtchDialogTitle": "Arrêter Cwtch ?",
"profileDeleteSuccess": "Successfully deleted profile", "shutdownCwtchTooltip": "Arrêt Cwtch",
"debugLog": "Turn on console debug logging", "malformedMessage": "Message mal formé",
"torNetworkStatus": "Tor network status", "profileDeleteSuccess": "Le profil a été supprimé avec succès",
"addContactFirst": "Add or pick a contact to begin chatting.", "debugLog": "Activer le journal de la console de débogage",
"createProfileToBegin": "Please create or unlock a profile to begin", "torNetworkStatus": "Statut du réseau Tor",
"nickChangeSuccess": "Profile nickname changed successfully", "addContactFirst": "Ajoutez ou choisissez un contact pour commencer à discuter.",
"addServerFirst": "You need to add a server before you can create a group", "createProfileToBegin": "Veuillez créer ou déverrouiller un profil pour commencer",
"deleteProfileSuccess": "Successfully deleted profile", "nickChangeSuccess": "Le pseudo du profil a été modifié avec succès",
"sendInvite": "Send a contact or group invite", "addServerFirst": "Vous devez ajouter un serveur avant de pouvoir créer un groupe.",
"sendMessage": "Send Message", "deleteProfileSuccess": "Le profil a été supprimé avec succès",
"cancel": "Cancel", "sendInvite": "Envoyer une invitation à un contact ou à un groupe",
"resetTor": "Reset", "sendMessage": "Envoyer un message",
"torStatus": "Tor Status", "cancel": "Annuler",
"torVersion": "Tor Version", "resetTor": "Réinitialiser",
"sendAnInvitation": "You sent an invitation for: ", "torStatus": "Statut de Tor",
"contactSuggestion": "This is a contact suggestion for: ", "torVersion": "Version de Tor",
"rejected": "Rejected!", "sendAnInvitation": "Vous avez envoyé une invitation pour : ",
"accepted": "Accepted!", "contactSuggestion": "Il s'agit d'une suggestion de contact pour : ",
"chatHistoryDefault": "This conversation will be deleted when Cwtch is closed! Message history can be enabled per-conversation via the Settings menu in the upper right.", "rejected": "Rejeté !",
"newPassword": "New Password", "accepted": "Accepté !",
"yesLeave": "Yes, Leave This Conversation", "chatHistoryDefault": "Cette conversation sera supprimée lorsque Cwtch sera fermé ! L'historique des messages peut être activé pour la conversation via le menu Paramètres en haut à droite.",
"reallyLeaveThisGroupPrompt": "Are you sure you want to leave this conversation? All messages and attributes will be deleted.", "newPassword": "Nouveau mot de passe",
"leaveGroup": "Leave This Conversation", "yesLeave": "Oui, quittez cette conversation",
"inviteToGroup": "You have been invited to join a group:", "reallyLeaveThisGroupPrompt": "Êtes-vous sûr de vouloir quitter cette conversation ? Tous les messages et attributs seront supprimés.",
"pasteAddressToAddContact": "... coller une adresse ici pour ajouter un contact...", "leaveGroup": "Quittez cette conversation",
"tooltipAddContact": "Add a new contact or conversation", "inviteToGroup": "Vous avez été invité à rejoindre un groupe :",
"pasteAddressToAddContact": "Collez une adresse cwtch, une invitation ou un ensemble de clés ici pour ajouter une nouvelle conversation",
"tooltipAddContact": "Ajouter un nouveau contact ou une nouvelle conversation",
"titleManageContacts": "Conversations", "titleManageContacts": "Conversations",
"titleManageServers": "Manage Servers", "titleManageServers": "Gérer les serveurs",
"dateMonthsAgo": "Months Ago", "dateMonthsAgo": "Il y a plusieurs mois",
"dateNever": "Never", "dateNever": "Jamais",
"dateYearsAgo": "X Years Ago (displayed next to a contact row to indicate time of last action)", "dateYearsAgo": "Il y a X ans (affiché à côté d'une ligne de contact pour indiquer l'heure de la dernière action)",
"dateLastYear": "Last Year", "dateLastYear": "L'année dernière",
"dateYesterday": "Yesterday", "dateYesterday": "Hier",
"dateLastMonth": "Last Month", "dateLastMonth": "Le mois dernier",
"dateWeeksAgo": "Weeks Ago", "dateWeeksAgo": "Il y a quelques semaines",
"dateDaysAgo": "Days Ago", "dateDaysAgo": "Il y a quelques jours",
"dateHoursAgo": "Hours Ago", "dateHoursAgo": "Il y a quelques heures",
"dateMinutesAgo": "Minutes Ago", "dateMinutesAgo": "Il y a quelques minutes",
"dateRightNow": "Right Now", "dateRightNow": "Maintenant",
"successfullAddedContact": "Successfully added ", "successfullAddedContact": "Ajouté avec succès ",
"descriptionBlockUnknownConnections": "If turned on, this option will automatically close connections from Cwtch users that have not been added to your contact list.", "descriptionBlockUnknownConnections": "Si elle est activée, cette option fermera automatiquement les connexions des utilisateurs de Cwtch qui n'ont pas été ajoutés à votre liste de contacts.",
"descriptionExperimentsGroups": "The group experiment allows Cwtch to connect with untrusted server infrastructure to facilitate communication with more than one contact.", "descriptionExperimentsGroups": "L'expérience de groupe permet à Cwtch de se connecter à une infrastructure de serveurs non fiables pour faciliter la communication avec plus d'un contact.",
"descriptionExperiments": "Cwtch experiments are optional, opt-in features that add additional functionality to Cwtch that may have different privacy considerations than traditional 1:1 metadata resistant chat e.g. group chat, bot integration etc.", "descriptionExperiments": "Les expériences de Cwtch sont des fonctionnalités optionnelles et facultatives qui ajoutent des fonctionnalités supplémentaires à Cwtch et qui peuvent avoir des considérations de confidentialité différentes de celles du chat traditionnel résistant aux métadonnées 1:1, par exemple le chat de groupe, l'intégration de robots, etc.",
"titleManageProfiles": "Manage Cwtch Profiles", "titleManageProfiles": "Gérer les profils Cwtch",
"tooltipUnlockProfiles": "Unlock encrypted profiles by entering their password.", "tooltipUnlockProfiles": "Déverrouillez les profils chiffrés en saisissant leur mot de passe.",
"tooltipOpenSettings": "Open the settings pane", "tooltipOpenSettings": "Ouvrez le volet des paramètres",
"invalidImportString": "Invalid import string", "invalidImportString": "Chaîne d'importation non valide",
"contactAlreadyExists": "Contact Already Exists", "contactAlreadyExists": "Le contact existe déjà",
"conversationSettings": "Conversation Settings", "conversationSettings": "Paramètres de conversation",
"enterCurrentPasswordForDelete": "Please enter current password to delete this profile.", "enterCurrentPasswordForDelete": "Veuillez entrer le mot de passe actuel pour supprimer ce profil.",
"enableGroups": "Enable Group Chat", "enableGroups": "Activer la discussion de groupe",
"experimentsEnabled": "Enable Experiments", "experimentsEnabled": "Activer les expériences",
"localeIt": "Italiana", "localeIt": "Italienne",
"localeEs": "Espanol", "localeEs": "Espagnol",
"addListItem": "Ajouter un nouvel élément", "addListItem": "Ajouter un nouvel élément de liste",
"addNewItem": "Ajouter un nouvel élément à la liste", "addNewItem": "Ajouter un nouvel élément à la liste",
"todoPlaceholder": "A faire...", "todoPlaceholder": "À faire...",
"newConnectionPaneTitle": "New Connection", "newConnectionPaneTitle": "Nouvelle connexion",
"networkStatusOnline": "Online", "networkStatusOnline": "En ligne",
"networkStatusConnecting": "Connecting to network and peers...", "networkStatusConnecting": "Se connecter au réseau et aux pairs...",
"networkStatusAttemptingTor": "Attempting to connect to Tor network", "networkStatusAttemptingTor": "Tentative de connexion au réseau Tor",
"networkStatusDisconnected": "Disconnected from the internet, check your connection", "networkStatusDisconnected": "Déconnecté d'Internet, vérifiez votre connexion",
"viewGroupMembershipTooltip": "View Group Membership", "viewGroupMembershipTooltip": "Afficher les membres du groupe",
"loadingTor": "Loading tor...", "loadingTor": "Chargement de tor...",
"smallTextLabel": "Petit", "smallTextLabel": "Petit",
"defaultScalingText": "Taille par défaut du texte (échelle:", "defaultScalingText": "Taille par défaut du texte (échelle:",
"builddate": "Built on: %2", "builddate": "Construit sur : 2%",
"version": "Version %1", "version": "Version 1%",
"versionTor": "Version %1 with tor %2", "versionTor": "Version 1% avec tor 2%",
"themeDark": "Dark", "themeDark": "Sombre",
"themeLight": "Light", "themeLight": "Clair",
"settingTheme": "Theme", "settingTheme": "Thème",
"largeTextLabel": "Large", "largeTextLabel": "Large",
"settingInterfaceZoom": "Zoom level", "settingInterfaceZoom": "Niveau de zoom",
"localeDe": "Deutsche", "localeDe": "Allemand",
"localePt": "Portuguesa", "localePt": "Portugais",
"localeFr": "Frances", "localeFr": "Français",
"localeEn": "English", "localeEn": "Anglais",
"settingLanguage": "Language", "settingLanguage": "Langue",
"blockUnknownLabel": "Block Unknown Peers", "blockUnknownLabel": "Bloquer les pairs inconnus",
"zoomLabel": "Interface zoom (essentiellement la taille du texte et des composants de l'interface)", "zoomLabel": "Interface zoom (essentiellement la taille du texte et des composants de l'interface)",
"versionBuilddate": "Version: %1 Built on: %2", "versionBuilddate": "Version 1% avec tor 2%",
"cwtchSettingsTitle": "Préférences Cwtch", "cwtchSettingsTitle": "Préférences Cwtch",
"unlock": "Unlock", "unlock": "Déverrouiller",
"yourServers": "Your Servers", "yourServers": "Vos serveurs",
"yourProfiles": "Your Profiles", "yourProfiles": "Vos profils",
"error0ProfilesLoadedForPassword": "0 profiles loaded with that password", "error0ProfilesLoadedForPassword": "Aucun profils chargés avec ce mot de passe",
"password": "Password", "password": "Mot de passe",
"enterProfilePassword": "Enter a password to view your profiles", "enterProfilePassword": "Entrez un mot de passe pour consulter vos profils",
"addNewProfileBtn": "Add new profile", "addNewProfileBtn": "Ajouter un nouveau profil",
"deleteConfirmText": "DELETE", "deleteConfirmText": "SUPPRIMER",
"deleteProfileConfirmBtn": "Really Delete Profile", "deleteProfileConfirmBtn": "Vraiment supprimer le profil",
"deleteConfirmLabel": "Type DELETE to confirm", "deleteConfirmLabel": "Tapez SUPPRIMER pour confirmer",
"deleteProfileBtn": "Delete Profile", "deleteProfileBtn": "Supprimer le profil",
"passwordChangeError": "Error changing password: Supplied password rejected", "passwordChangeError": "Erreur lors de la modification du mot de passe : le mot de passe fourni est rejeté",
"passwordErrorMatch": "Passwords do not match", "passwordErrorMatch": "Les mots de passe ne correspondent pas",
"saveProfileBtn": "Save Profile", "saveProfileBtn": "Sauvegarder le profil",
"createProfileBtn": "Create Profile", "createProfileBtn": "Créer un profil",
"passwordErrorEmpty": "Password cannot be empty", "passwordErrorEmpty": "Le mot de passe ne peut pas être vide",
"password2Label": "Reenter password", "password2Label": "Saisissez à nouveau le mot de passe",
"password1Label": "Password", "password1Label": "Mot de passe",
"currentPasswordLabel": "Current Password", "currentPasswordLabel": "Mot de passe actuel",
"yourDisplayName": "Your Display Name", "yourDisplayName": "Pseudo",
"profileOnionLabel": "Send this address to peers you want to connect with", "profileOnionLabel": "Envoyez cette adresse aux personnes avec lesquelles vous souhaitez entrer en contact.",
"noPasswordWarning": "Not using a password on this account means that all data stored locally will not be encrypted", "noPasswordWarning": "Ne pas utiliser de mot de passe sur ce compte signifie que toutes les données stockées localement ne seront pas chiffrées.",
"radioNoPassword": "Unencrypted (No password)", "radioNoPassword": "Non chiffré (pas de mot de passe)",
"radioUsePassword": "Password", "radioUsePassword": "Mot de passe",
"copiedToClipboardNotification": "Copié dans le presse-papier", "copiedToClipboardNotification": "Copié dans le presse-papier",
"copyBtn": "Copier", "copyBtn": "Copier",
"editProfile": "Edit Profille", "editProfile": "Modifier le profil",
"newProfile": "New Profile", "newProfile": "Nouveau profil",
"defaultProfileName": "Alice", "defaultProfileName": "Alice",
"profileName": "Display name", "profileName": "Pseudo",
"editProfileTitle": "Edit Profile", "editProfileTitle": "Modifier le profil",
"addProfileTitle": "Add new profile", "addProfileTitle": "Ajouter un nouveau profil",
"deleteBtn": "Effacer", "deleteBtn": "Effacer",
"unblockBtn": "Unblock Peer", "unblockBtn": "Débloquer le pair",
"dontSavePeerHistory": "Delete Peer History", "dontSavePeerHistory": "Supprimer l'historique des pairs",
"savePeerHistoryDescription": "Determines whether or not to delete any history associated with the peer.", "savePeerHistoryDescription": "Détermine s'il faut ou non supprimer tout historique associé au pair.",
"savePeerHistory": "Save Peer History", "savePeerHistory": "Sauvegarder l'historique des pairs",
"blockBtn": "Block Peer", "blockBtn": "Bloquer le pair",
"saveBtn": "Sauvegarder", "saveBtn": "Sauvegarder",
"displayNameLabel": "Pseudo", "displayNameLabel": "Pseudo",
"addressLabel": "Adresse", "addressLabel": "Adresse",
@ -145,50 +147,50 @@
"acceptGroupInviteLabel": "Voulez-vous accepter l'invitation au groupe", "acceptGroupInviteLabel": "Voulez-vous accepter l'invitation au groupe",
"newGroupBtn": "Créer un nouveau groupe", "newGroupBtn": "Créer un nouveau groupe",
"copiedClipboardNotification": "Copié dans le presse-papier", "copiedClipboardNotification": "Copié dans le presse-papier",
"peerOfflineMessage": "Peer is offline, messages can't be delivered right now", "peerOfflineMessage": "Le pair est hors ligne, les messages ne peuvent pas être remis pour le moment",
"peerBlockedMessage": "Peer is blocked", "peerBlockedMessage": "Le pair est bloqué",
"pendingLabel": "En attente", "pendingLabel": "En attente",
"acknowledgedLabel": "Confirmé", "acknowledgedLabel": "Confirmé",
"couldNotSendMsgError": "Impossible d'envoyer ce message", "couldNotSendMsgError": "Impossible d'envoyer ce message",
"dmTooltip": "Envoyer un message privé", "dmTooltip": "Envoyer un message privé",
"membershipDescription": "Liste des utilisateurs ayant envoyés un ou plusieurs messages au groupe. Cette liste peut ne pas être representatives de l'ensemble des membres du groupe.", "membershipDescription": "Liste des utilisateurs ayant envoyés un ou plusieurs messages au groupe. Cette liste peut ne pas être representatives de l'ensemble des membres du groupe.",
"addListItemBtn": "Add Item", "addListItemBtn": "Ajouter un élément",
"peerNotOnline": "Peer is Offline. Applications cannot be used right now.", "peerNotOnline": "Le pair est hors ligne, les messages ne peuvent pas être remis pour le moment",
"searchList": "Search List", "searchList": "Liste de recherche",
"update": "Update", "update": "Mise à jour",
"inviteBtn": "Invitation", "inviteBtn": "Invitation",
"inviteToGroupLabel": "Inviter quelqu'un", "inviteToGroupLabel": "Inviter quelqu'un",
"groupNameLabel": "Nom du groupe", "groupNameLabel": "Nom du groupe",
"viewServerInfo": "Server Info", "viewServerInfo": "Informations sur le serveur",
"serverSynced": "Synced", "serverSynced": "Synchronisé",
"serverConnectivityDisconnected": "Server Disconnected", "serverConnectivityDisconnected": "Serveur déconnecté",
"serverConnectivityConnected": "Server Connected", "serverConnectivityConnected": "Serveur connecté",
"serverInfo": "Server Information", "serverInfo": "Informations sur le serveur",
"invitationLabel": "Invitation", "invitationLabel": "Invitation",
"serverLabel": "Serveur", "serverLabel": "Serveur",
"search": "Search...", "search": "Recherche...",
"cycleColoursDesktop": "Click to cycle colours.\nRight-click to reset.", "cycleColoursDesktop": "Cliquez pour faire défiler les couleurs.\nCliquez avec le bouton droit de la souris pour réinitialiser.",
"cycleColoursAndroid": "Click to cycle colours.\nLong-press to reset.", "cycleColoursAndroid": "Cliquez pour faire défiler les couleurs.\nAppuyez longuement pour réinitialiser.",
"cycleMorphsDesktop": "Click to cycle morphs.\nRight-click to reset.", "cycleMorphsDesktop": "Cliquez pour faire défiler les morphes.\n Faites un clic droit pour réinitialiser.",
"cycleMorphsAndroid": "Click to cycle morphs.\nLong-press to reset.", "cycleMorphsAndroid": "Cliquez pour faire défiler les morphes.\n Appuyez longuement pour réinitialiser.",
"cycleCatsDesktop": "Click to cycle category.\nRight-click to reset.", "cycleCatsDesktop": "Cliquez pour parcourir la catégorie.\n Faites un clic droit pour réinitialiser.",
"cycleCatsAndroid": "Click to cycle category.\nLong-press to reset.", "cycleCatsAndroid": "Cliquez pour faire défiler les catégories.\nAppuyez longuement pour réinitialiser.",
"blocked": "Blocked", "blocked": "Bloqué",
"titlePlaceholder": "titre...", "titlePlaceholder": "titre...",
"postNewBulletinLabel": "Envoyer un nouveau bulletin", "postNewBulletinLabel": "Envoyer un nouveau bulletin",
"newBulletinLabel": "Nouveau bulletin", "newBulletinLabel": "Nouveau bulletin",
"joinGroup": "Join group", "joinGroup": "Rejoindre le groupe",
"createGroup": "Create group", "createGroup": "Créer un groupe",
"addPeer": "Add Peer", "addPeer": "Ajouter un pair",
"groupAddr": "Address", "groupAddr": "Adresse",
"invitation": "Invitation", "invitation": "Invitation",
"server": "Server", "server": "Serveur",
"groupName": "Group name", "groupName": "Nom du groupe",
"peerName": "Name", "peerName": "Nom",
"peerAddress": "Address", "peerAddress": "Adresse",
"joinGroupTab": "Join a group", "joinGroupTab": "Rejoindre un groupe",
"createGroupTab": "Create a group", "createGroupTab": "Créer un groupe",
"addPeerTab": "Add a peer", "addPeerTab": "Ajouter un pair",
"createGroupBtn": "Créer", "createGroupBtn": "Créer",
"defaultGroupName": "Un super groupe", "defaultGroupName": "Un super groupe",
"createGroupTitle": "Créer un groupe" "createGroupTitle": "Créer un groupe"

View File

@ -1,6 +1,8 @@
{ {
"@@locale": "it", "@@locale": "it",
"@@last_modified": "2021-06-25T18:57:59+02:00", "@@last_modified": "2021-06-29T19:15:43+02:00",
"tooltipRejectContactRequest": "Reject this contact request",
"tooltipAcceptContactRequest": "Accept this contact request.",
"notificationNewMessageFromGroup": "New message in a group!", "notificationNewMessageFromGroup": "New message in a group!",
"notificationNewMessageFromPeer": "New message from a contact!", "notificationNewMessageFromPeer": "New message from a contact!",
"tooltipHidePassword": "Hide Password", "tooltipHidePassword": "Hide Password",

View File

@ -1,6 +1,8 @@
{ {
"@@locale": "pt", "@@locale": "pt",
"@@last_modified": "2021-06-25T18:57:59+02:00", "@@last_modified": "2021-06-29T19:15:43+02:00",
"tooltipRejectContactRequest": "Reject this contact request",
"tooltipAcceptContactRequest": "Accept this contact request.",
"notificationNewMessageFromGroup": "New message in a group!", "notificationNewMessageFromGroup": "New message in a group!",
"notificationNewMessageFromPeer": "New message from a contact!", "notificationNewMessageFromPeer": "New message from a contact!",
"tooltipHidePassword": "Hide Password", "tooltipHidePassword": "Hide Password",

View File

@ -167,8 +167,8 @@ class FlwtchState extends State<Flwtch> {
Future<void> _externalNotificationClicked(MethodCall call) async { Future<void> _externalNotificationClicked(MethodCall call) async {
var args = jsonDecode(call.arguments); var args = jsonDecode(call.arguments);
var profile = profs.getProfile(args["ProfileOnion"])!; var profile = profs.getProfile(args["ProfileOnion"])!;
var contact = profile.contactList.getContact(args["RemotePeer"])!; var convo = profile.contactList.getContact(args["Handle"])!;
contact.unreadMessages = 0; convo.unreadMessages = 0;
// single pane mode pushes; double pane mode reads AppState.selectedProfile/Conversation // single pane mode pushes; double pane mode reads AppState.selectedProfile/Conversation
var isLandscape = Provider.of<AppState>(navKey.currentContext!, listen: false).isLandscape(navKey.currentContext!); var isLandscape = Provider.of<AppState>(navKey.currentContext!, listen: false).isLandscape(navKey.currentContext!);
@ -183,7 +183,7 @@ class FlwtchState extends State<Flwtch> {
return MultiProvider( return MultiProvider(
providers: [ providers: [
ChangeNotifierProvider.value(value: profile), ChangeNotifierProvider.value(value: profile),
ChangeNotifierProvider.value(value: contact), ChangeNotifierProvider.value(value: convo),
], ],
builder: (context, child) => MessageView(), builder: (context, child) => MessageView(),
); );
@ -192,7 +192,7 @@ class FlwtchState extends State<Flwtch> {
); );
} else { //dual pane } else { //dual pane
Provider.of<AppState>(navKey.currentContext!, listen: false).selectedProfile = args["ProfileOnion"]; Provider.of<AppState>(navKey.currentContext!, listen: false).selectedProfile = args["ProfileOnion"];
Provider.of<AppState>(navKey.currentContext!, listen: false).selectedConversation = args["RemotePeer"]; Provider.of<AppState>(navKey.currentContext!, listen: false).selectedConversation = args["Handle"];
} }
} }

View File

@ -152,9 +152,14 @@ class _AddContactViewState extends State<AddContactView> {
Future.delayed(const Duration(milliseconds: 500), () { Future.delayed(const Duration(milliseconds: 500), () {
if (globalErrorHandler.importBundleSuccess) { if (globalErrorHandler.importBundleSuccess) {
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.successfullAddedContact + importBundle)); // TODO: This isn't ideal, but because onChange can be fired during this future check
ScaffoldMessenger.of(context).showSnackBar(snackBar); // and because the context can change after being popped we have this kind of double assertion...
Navigator.pop(context); // There is probably a better pattern to handle this...
if (AppLocalizations.of(context) != null) {
final snackBar = SnackBar(content: Text(AppLocalizations.of(context)!.successfullAddedContact + importBundle));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
Navigator.popUntil(context, (route) => route.settings.name == "conversations");
}
} }
}); });
}, },

View File

@ -60,13 +60,15 @@ class _ContactRowState extends State<ContactRow> {
IconButton( IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 16, iconSize: 16,
icon: Icon(Icons.favorite, color: Provider.of<Settings>(context).theme.mainTextColor()), icon: Icon(Icons.favorite, color: Provider.of<Settings>(context).theme.mainTextColor(),),
tooltip: AppLocalizations.of(context)!.tooltipAcceptContactRequest,
onPressed: _btnApprove, onPressed: _btnApprove,
), ),
IconButton( IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 16, iconSize: 16,
icon: Icon(Icons.delete, color: Provider.of<Settings>(context).theme.mainTextColor()), icon: Icon(Icons.delete, color: Provider.of<Settings>(context).theme.mainTextColor()),
tooltip: AppLocalizations.of(context)!.tooltipRejectContactRequest,
onPressed: _btnReject, onPressed: _btnReject,
) )
]) ])

View File

@ -16,10 +16,18 @@ class _MessageListState extends State<MessageList> {
@override @override
Widget build(BuildContext outerContext) { Widget build(BuildContext outerContext) {
bool showEphemeralWarning = (Provider.of<ContactInfoState>(context).isGroup == false && Provider.of<ContactInfoState>(context).savePeerHistory != "SaveHistory");
bool isP2P = !Provider.of<ContactInfoState>(context).isGroup;
bool isGroupAndSyncing = Provider.of<ContactInfoState>(context).isGroup == true && Provider.of<ContactInfoState>(context).status == "Authenticated";
bool isGroupAndSynced = Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status == "Synced";
bool isGroupAndNotAuthenticated= Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status != "Authenticated";
bool showEphemeralWarning = (isP2P && Provider.of<ContactInfoState>(context).savePeerHistory != "SaveHistory");
bool showOfflineWarning = Provider.of<ContactInfoState>(context).isOnline() == false; bool showOfflineWarning = Provider.of<ContactInfoState>(context).isOnline() == false;
bool showMessageWarning = showEphemeralWarning || showOfflineWarning; bool showSyncing = isGroupAndSyncing;
bool showSyncing = Provider.of<ContactInfoState>(context).isGroup == true && Provider.of<ContactInfoState>(context).status != "Synced"; bool showMessageWarning = showEphemeralWarning || showOfflineWarning || showSyncing;
// Only load historical messages when the conversation is with a p2p contact OR the conversation is a server and *not* syncing.
bool loadMessages = isP2P || (isGroupAndSynced || isGroupAndNotAuthenticated);
return RepaintBoundary( return RepaintBoundary(
child: Container( child: Container(
@ -56,7 +64,7 @@ class _MessageListState extends State<MessageList> {
image: AssetImage("assets/core/negative_heart_512px.png"), image: AssetImage("assets/core/negative_heart_512px.png"),
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.hilightElementTextColor(), BlendMode.srcIn))), colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.hilightElementTextColor(), BlendMode.srcIn))),
// Don't load messages for syncing server... // Don't load messages for syncing server...
child: ListView.builder( child: loadMessages ? ListView.builder(
controller: ctrlr1, controller: ctrlr1,
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages, itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction... reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction...
@ -78,7 +86,7 @@ class _MessageListState extends State<MessageList> {
return RepaintBoundary(child: MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx))); return RepaintBoundary(child: MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx)));
}); });
}, },
)))) ) : null )))
]))); ])));
} }
} }