From 3f5428eff881dcbb42f946500e444faf425e1c1a Mon Sep 17 00:00:00 2001 From: Dan Ballard Date: Sat, 20 Nov 2021 10:09:06 -0800 Subject: [PATCH] complete profile level server managment --- lib/l10n/intl_de.arb | 15 ++- lib/l10n/intl_en.arb | 15 ++- lib/l10n/intl_es.arb | 15 ++- lib/l10n/intl_fr.arb | 19 +++- lib/l10n/intl_it.arb | 135 ++++++++++++------------ lib/l10n/intl_pl.arb | 123 +++++++++++----------- lib/l10n/intl_pt.arb | 15 ++- lib/model.dart | 12 ++- lib/models/profileservers.dart | 23 +++-- lib/views/addeditprofileview.dart | 3 +- lib/views/contactsview.dart | 6 +- lib/views/profileserversview.dart | 98 +++++++++++++++++- lib/views/remoteserverview.dart | 164 ++++++++++++++---------------- lib/widgets/remoteserverrow.dart | 85 ++++++++-------- 14 files changed, 433 insertions(+), 295 deletions(-) diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index b3793cca..b08f6de8 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -1,6 +1,16 @@ { "@@locale": "de", - "@@last_modified": "2021-11-11T01:02:08+01:00", + "@@last_modified": "2021-11-21T17:42:07+01:00", + "manageKnownServersShort": "Servers", + "manageKnownServersLong": "Manage Known Servers", + "displayNameTooltip": "Please enter a display name", + "manageKnownServersButton": "Manage Known Servers", + "fieldDescriptionLabel": "Description", + "groupsOnThisServerLabel": "Groups I am in hosted on this server", + "importLocalServerButton": "Import %1", + "importLocalServerSelectText": "Select Local Server", + "importLocalServerLabel": "Import a locally hosted server", + "savePeerHistoryDescription": "Legt fest, ob ein mit dem anderen Nutzer verknüpfter Verlauf gelöscht werden soll oder nicht.", "newMessagesLabel": "New Messages", "localeRU": "Russian", "copyServerKeys": "Copy keys", @@ -55,7 +65,6 @@ "peerOfflineMessage": "Anderer Nutzer ist offline, Nachrichten können derzeit nicht zugestellt werden", "blockBtn": "Anderen Nutzer blockieren", "savePeerHistory": "Peer-Verlauf speichern", - "savePeerHistoryDescription": "Legt fest, ob ein mit dem anderen Nutzer verknüpfter Verlauf gelöscht werden soll oder nicht.", "dontSavePeerHistory": "Verlauf mit anderem Nutzer löschen", "unblockBtn": "Anderen Nutzer entsperren", "blockUnknownLabel": "Unbekannte Peers blockieren", @@ -190,7 +199,6 @@ "radioNoPassword": "Unverschlüsselt (kein Passwort)", "radioUsePassword": "Passwort", "copiedToClipboardNotification": "in die Zwischenablage kopiert", - "copyBtn": "Kopieren", "editProfile": "Profil bearbeiten", "newProfile": "Neues Profil", "defaultProfileName": "Alice", @@ -210,6 +218,7 @@ "acceptGroupInviteLabel": "Möchtest Du die Einladung annehmen", "newGroupBtn": "Neue Gruppe anlegen", "copiedClipboardNotification": "in die Zwischenablage kopiert", + "copyBtn": "Kopieren", "pendingLabel": "Bestätigung ausstehend", "acknowledgedLabel": "bestätigt", "couldNotSendMsgError": "Nachricht konnte nicht gesendet werden", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 70f13992..4069f313 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,6 +1,16 @@ { "@@locale": "en", - "@@last_modified": "2021-11-11T01:02:08+01:00", + "@@last_modified": "2021-11-21T17:42:07+01:00", + "manageKnownServersShort": "Servers", + "manageKnownServersLong": "Manage Known Servers", + "displayNameTooltip": "Please enter a display name", + "manageKnownServersButton": "Manage Known Servers", + "fieldDescriptionLabel": "Description", + "groupsOnThisServerLabel": "Groups I am in hosted on this server", + "importLocalServerButton": "Import %1", + "importLocalServerSelectText": "Select Local Server", + "importLocalServerLabel": "Import a locally hosted server", + "savePeerHistoryDescription": "Determines whether to delete any history associated with the contact.", "newMessagesLabel": "New Messages", "localeRU": "Russian", "copyServerKeys": "Copy keys", @@ -55,7 +65,6 @@ "peerOfflineMessage": "Contact is offline, messages can't be delivered right now", "blockBtn": "Block Contact", "savePeerHistory": "Save History", - "savePeerHistoryDescription": "Determines whether or not to delete any history associated with the contact.", "dontSavePeerHistory": "Delete History", "unblockBtn": "Unblock Contact", "blockUnknownLabel": "Block Unknown Contacts", @@ -190,7 +199,6 @@ "radioNoPassword": "Unencrypted (No password)", "radioUsePassword": "Password", "copiedToClipboardNotification": "Copied to Clipboard", - "copyBtn": "Copy", "editProfile": "Edit Profille", "newProfile": "New Profile", "defaultProfileName": "Alice", @@ -210,6 +218,7 @@ "acceptGroupInviteLabel": "Do you want to accept the invitation to", "newGroupBtn": "Create new group", "copiedClipboardNotification": "Copied to clipboard", + "copyBtn": "Copy", "pendingLabel": "Pending", "acknowledgedLabel": "Acknowledged", "couldNotSendMsgError": "Could not send this message", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index ba0a54bc..bb62828f 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -1,6 +1,16 @@ { "@@locale": "es", - "@@last_modified": "2021-11-11T01:02:08+01:00", + "@@last_modified": "2021-11-21T17:42:07+01:00", + "manageKnownServersShort": "Servers", + "manageKnownServersLong": "Manage Known Servers", + "displayNameTooltip": "Please enter a display name", + "manageKnownServersButton": "Manage Known Servers", + "fieldDescriptionLabel": "Description", + "groupsOnThisServerLabel": "Groups I am in hosted on this server", + "importLocalServerButton": "Import %1", + "importLocalServerSelectText": "Select Local Server", + "importLocalServerLabel": "Import a locally hosted server", + "savePeerHistoryDescription": "Determina si eliminar o no el historial asociado con el contacto.", "newMessagesLabel": "New Messages", "localeRU": "Russian", "copyServerKeys": "Copy keys", @@ -55,7 +65,6 @@ "peerOfflineMessage": "Este contacto no está en línea, los mensajes no pueden ser entregados en este momento", "blockBtn": "Bloquear contacto", "savePeerHistory": "Guardar el historial con contacto", - "savePeerHistoryDescription": "Determina si eliminar o no el historial asociado con el contacto.", "dontSavePeerHistory": "Eliminar historial de contacto", "unblockBtn": "Desbloquear contacto", "blockUnknownLabel": "Bloquear conexiones desconocidas", @@ -190,7 +199,6 @@ "radioNoPassword": "Sin cifrado (sin contraseña)", "radioUsePassword": "Contraseña", "copiedToClipboardNotification": "Copiado al portapapeles", - "copyBtn": "Copiar", "editProfile": "Editar perfil", "newProfile": "Nuevo perfil", "defaultProfileName": "Alicia", @@ -210,6 +218,7 @@ "acceptGroupInviteLabel": "¿Quieres aceptar la invitación a ", "newGroupBtn": "Crear un nuevo grupo de chat", "copiedClipboardNotification": "Copiado al portapapeles", + "copyBtn": "Copiar", "pendingLabel": "Pendiente", "acknowledgedLabel": "Reconocido", "couldNotSendMsgError": "No se pudo enviar este mensaje", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index bb6e8810..fdd9808f 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -1,8 +1,18 @@ { "@@locale": "fr", - "@@last_modified": "2021-11-11T01:02:08+01:00", - "newMessagesLabel": "New Messages", - "localeRU": "Russian", + "@@last_modified": "2021-11-21T17:42:07+01:00", + "manageKnownServersShort": "Servers", + "manageKnownServersLong": "Manage Known Servers", + "displayNameTooltip": "Veuillez entrer un nom d'usage s'il vous plaît", + "manageKnownServersButton": "Gérer les serveurs connus", + "fieldDescriptionLabel": "Description", + "groupsOnThisServerLabel": "Les groupes dont je fais partie sont hébergés sur ce serveur", + "importLocalServerButton": "Importer %1", + "importLocalServerSelectText": "Sélectionnez le serveur local", + "importLocalServerLabel": "Importer un serveur hébergé localement", + "savePeerHistoryDescription": "Détermine s'il faut ou non supprimer tout historique associé au contact.", + "newMessagesLabel": "Nouveaux messages", + "localeRU": "Russe", "copyServerKeys": "Copier les clés", "verfiyResumeButton": "Vérifier\/reprendre", "fileCheckingStatus": "Vérification de l'état du téléchargement", @@ -55,7 +65,6 @@ "peerOfflineMessage": "Le contact est hors ligne, les messages ne peuvent pas être transmis pour le moment.", "blockBtn": "Bloquer le contact", "savePeerHistory": "Enregistrer l'historique", - "savePeerHistoryDescription": "Détermine s'il faut ou non supprimer tout historique associé au contact.", "dontSavePeerHistory": "Supprimer l'historique", "unblockBtn": "Débloquer le contact", "blockUnknownLabel": "Bloquer les pairs inconnus", @@ -190,7 +199,6 @@ "radioNoPassword": "Non chiffré (pas de mot de passe)", "radioUsePassword": "Mot de passe", "copiedToClipboardNotification": "Copié dans le presse-papier", - "copyBtn": "Copier", "editProfile": "Modifier le profil", "newProfile": "Nouveau profil", "defaultProfileName": "Alice", @@ -210,6 +218,7 @@ "acceptGroupInviteLabel": "Voulez-vous accepter l'invitation au groupe", "newGroupBtn": "Créer un nouveau groupe", "copiedClipboardNotification": "Copié dans le presse-papier", + "copyBtn": "Copier", "pendingLabel": "En attente", "acknowledgedLabel": "Accusé de réception", "couldNotSendMsgError": "Impossible d'envoyer ce message", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index fce93d69..113411cd 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -1,52 +1,62 @@ { "@@locale": "it", - "@@last_modified": "2021-11-11T01:02:08+01:00", - "newMessagesLabel": "New Messages", - "localeRU": "Russian", - "copyServerKeys": "Copy keys", - "verfiyResumeButton": "Verify\/resume", - "fileCheckingStatus": "Checking download status", - "fileInterrupted": "Interrupted", - "fileSavedTo": "Saved to", - "plainServerDescription": "We recommend that you protect your Cwtch servers with a password. If you do not set a password on this server then anyone who has access to this device may be able to access information about this server, including sensitive cryptographic keys.", - "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", - "deleteServerConfirmBtn": "Really delete server", - "deleteServerSuccess": "Successfully deleted server", - "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", - "copyAddress": "Copy Address", - "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", - "settingServers": "Hosting Servers", - "enterServerPassword": "Enter password to unlock server", - "unlockProfileTip": "Please create or unlock a profile to begin!", - "unlockServerTip": "Please create or unlock a server to begin!", - "addServerTooltip": "Add new server", - "serversManagerTitleShort": "Servers", - "serversManagerTitleLong": "Servers You Host", - "saveServerButton": "Save Server", - "serverAutostartDescription": "Controls if the application will automatically launch the server on start", - "serverAutostartLabel": "Autostart", - "serverEnabledDescription": "Start or stop the server", - "serverEnabled": "Server Enabled", - "serverDescriptionDescription": "Your description of the server for personal management use only, will never be shared", - "serverDescriptionLabel": "Server Description", - "serverAddress": "Server Address", - "editServerTitle": "Edit Server", - "addServerTitle": "Add Server", - "titleManageProfilesShort": "Profiles", - "descriptionStreamerMode": "If turned on, this option makes the app more visually private for streaming or presenting with, for example, hiding profile and contact addresses", + "@@last_modified": "2021-11-21T17:42:07+01:00", + "manageKnownServersShort": "Servers", + "manageKnownServersLong": "Manage Known Servers", + "displayNameTooltip": "Please enter a display name", + "manageKnownServersButton": "Manage Known Servers", + "fieldDescriptionLabel": "Description", + "groupsOnThisServerLabel": "Groups I am in hosted on this server", + "importLocalServerButton": "Import %1", + "importLocalServerSelectText": "Select Local Server", + "importLocalServerLabel": "Import a locally hosted server", + "savePeerHistoryDescription": "Determina se eliminare o meno ogni cronologia eventualmente associata al peer.", + "newMessagesLabel": "Nuovi messaggi", + "localeRU": "Russo", + "copyServerKeys": "Copia chiavi", + "verfiyResumeButton": "Verifica\/riprendi", + "fileCheckingStatus": "Controllo dello stato del download", + "fileInterrupted": "Interrotto", + "fileSavedTo": "Salvato in", + "plainServerDescription": "Ti raccomandiamo di proteggere i tuoi server Cwtch con una password. Se non imposti una password su questo server, chiunque abbia accesso a questo dispositivo potrebbe essere in grado di accedere alle relativ informazioni, compresi dati sensibili come le chiavi crittografiche.", + "encryptedServerDescription": "Criptare un server con una password lo protegge da altre persone che potrebbero usare questo dispositivo. I server criptati non possono essere decriptati, visualizzati o accessibili finché non viene inserita la password corretta per sbloccarli.", + "deleteServerConfirmBtn": "Elimina davvero il server", + "deleteServerSuccess": "Server eliminato con successo", + "enterCurrentPasswordForDeleteServer": "Inserisci la password attuale per eliminare questo server", + "copyAddress": "Copia indirizzo", + "settingServersDescription": "L'esperimento dei server di hosting permette di allocare e gestire i server Cwtch", + "settingServers": "Server di hosting", + "enterServerPassword": "Inserisci la password per sbloccare il server", + "unlockProfileTip": "Crea o sblocca un profilo per iniziare!", + "unlockServerTip": "Crea o sblocca un server per iniziare!", + "addServerTooltip": "Aggiungi nuovo server", + "serversManagerTitleShort": "Gestisci i server", + "serversManagerTitleLong": "Server che gestisci", + "saveServerButton": "Salva il server", + "serverAutostartDescription": "Controlla se l'applicazione avvierà automaticamente il server all'avvio", + "serverAutostartLabel": "Avvio automatico", + "serverEnabledDescription": "Avvia o arresta il server", + "serverEnabled": "Server abilitato", + "serverDescriptionDescription": "La tua descrizione del server solo per gestione personale, non sarà mai condivisa", + "serverDescriptionLabel": "Descrizione del server", + "serverAddress": "Indirizzo del server", + "editServerTitle": "Modifica il server", + "addServerTitle": "Aggiungi server", + "titleManageProfilesShort": "Profili", + "descriptionStreamerMode": "Se attivata, questa opzione rende l'applicazione visivamente più privata per lo streaming o la presentazione, ad esempio nascondendo il profilo e gli indirizzi di contatto", "descriptionFileSharing": "L'esperimento di condivisione dei file ti consente di inviare e ricevere file dai contatti e dai gruppi di Cwtch. Tieni presente che la condivisione di un file con un gruppo farà sì che i membri di quel gruppo si colleghino con te direttamente su Cwtch per scaricarlo.", "settingFileSharing": "Condivisione file", "tooltipSendFile": "Invia file", "messageFileOffered": "Il contatto offre l'invio di un file", - "messageFileSent": "You sent a file", - "messageEnableFileSharing": "Enable the file sharing experiment to view this message.", - "labelFilesize": "Size", - "labelFilename": "Filename", - "downloadFileButton": "Download", - "openFolderButton": "Open Folder", - "retrievingManifestMessage": "Retrieving file information...", - "streamerModeLabel": "Streamer\/Presentation Mode", - "archiveConversation": "Archive this Conversation", + "messageFileSent": "Hai inviato un file", + "messageEnableFileSharing": "Abilita l'esperimento di condivisione dei file per visualizzare questo messaggio.", + "labelFilesize": "Dimensione", + "labelFilename": "Nome del file", + "downloadFileButton": "Scarica", + "openFolderButton": "Apri cartella", + "retrievingManifestMessage": "Recupero delle informazioni sul file in corso...", + "streamerModeLabel": "Modalità Streamer\/Presentazione", + "archiveConversation": "Archivia questa conversazione", "profileOnionLabel": "Inviare questo indirizzo ai peer con cui si desidera connettersi", "addPeerTab": "Aggiungi un peer", "addPeer": "Aggiungi peer", @@ -55,29 +65,28 @@ "peerOfflineMessage": "Il peer è offline, i messaggi non possono essere recapitati in questo momento", "blockBtn": "Blocca il peer", "savePeerHistory": "Salva cronologia peer", - "savePeerHistoryDescription": "Determina se eliminare o meno ogni cronologia eventualmente associata al peer.", "dontSavePeerHistory": "Elimina cronologia dei peer", "unblockBtn": "Sblocca il peer", "blockUnknownLabel": "Blocca peer sconosciuti", - "blockUnknownConnectionsEnabledDescription": "Connections from unknown contacts are blocked. You can change this in Settings", + "blockUnknownConnectionsEnabledDescription": "Le connessioni da contatti sconosciuti sono bloccate. Puoi modificare questa impostazione in Impostazioni", "networkStatusConnecting": "Connessione alla rete e ai peer ...", - "showMessageButton": "Show Message", - "blockedMessageMessage": "This message is from a profile you have blocked.", - "placeholderEnterMessage": "Type a message...", - "plainProfileDescription": "We recommend that you protect your Cwtch profiles with a password. If you do not set a password on this profile then anyone who has access to this device may be able to access information about this profile, including contacts, messages and sensitive cryptographic keys.", - "encryptedProfileDescription": "Encrypting a profile with a password protects it from other people who may also use this device. Encrypted profiles cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", - "addContactConfirm": "Add contact %1", - "addContact": "Add contact", - "contactGoto": "Go to conversation with %1", - "settingUIColumnOptionSame": "Same as portrait mode setting", - "settingUIColumnDouble14Ratio": "Double (1:4)", - "settingUIColumnDouble12Ratio": "Double (1:2)", - "settingUIColumnSingle": "Single", - "settingUIColumnLandscape": "UI Columns in Landscape Mode", - "settingUIColumnPortrait": "UI Columns in Portrait Mode", - "localePl": "Polish", - "tooltipRemoveThisQuotedMessage": "Remove quoted message.", - "tooltipReplyToThisMessage": "Reply to this message", + "showMessageButton": "Mostra il messaggio", + "blockedMessageMessage": "Questo messaggio proviene da un profilo che hai bloccato.", + "placeholderEnterMessage": "Scrivi un messaggio...", + "plainProfileDescription": "Ti raccomandiamo di proteggere i tuoi profili Cwtch con una password. Se non imposti una password su questo profilo, chiunque abbia accesso a questo dispositivo potrebbe essere in grado di accedere alle relative informazioni, compresi contatti, messaggi e altri dati sensibili come le chiavi crittografiche.", + "encryptedProfileDescription": "Criptare un profilo con una password lo protegge da altre persone che potrebbero usare questo dispositivo. I profili criptati non possono essere decriptati, visualizzati o accessibili finché non viene inserita la password corretta per sbloccarli.", + "addContactConfirm": "Aggiungi %1 come contatto", + "addContact": "Aggiungi contatto", + "contactGoto": "Vai alla conversazione con %1", + "settingUIColumnOptionSame": "Stessa impostazione della modalità verticale", + "settingUIColumnDouble14Ratio": "Doppia (1:4)", + "settingUIColumnDouble12Ratio": "Doppia (1:2)", + "settingUIColumnSingle": "Singola", + "settingUIColumnLandscape": "Colonne dell'interfaccia utente in modalità orizzontale", + "settingUIColumnPortrait": "Colonne dell'interfaccia utente in modalità verticale", + "localePl": "Polacco", + "tooltipRemoveThisQuotedMessage": "Rimuovi il messaggio citato.", + "tooltipReplyToThisMessage": "Rispondi a questo messaggio", "tooltipRejectContactRequest": "Rifiuta questa richiesta di contatto", "tooltipAcceptContactRequest": "Accetta questa richiesta di contatto.", "notificationNewMessageFromGroup": "Nuovo messaggio in un gruppo!", @@ -190,7 +199,6 @@ "radioNoPassword": "Non criptato (senza password)", "radioUsePassword": "Password", "copiedToClipboardNotification": "Copiato negli Appunti", - "copyBtn": "Copia", "editProfile": "Modifica profilo", "newProfile": "Nuovo profilo", "defaultProfileName": "Alice", @@ -210,6 +218,7 @@ "acceptGroupInviteLabel": "Vuoi accettare l'invito a", "newGroupBtn": "Crea un nuovo gruppo", "copiedClipboardNotification": "Copiato negli Appunti", + "copyBtn": "Copia", "pendingLabel": "In corso", "acknowledgedLabel": "Riconosciuto", "couldNotSendMsgError": "Impossibile inviare questo messaggio", diff --git a/lib/l10n/intl_pl.arb b/lib/l10n/intl_pl.arb index aa2e5366..a8fd1a3e 100644 --- a/lib/l10n/intl_pl.arb +++ b/lib/l10n/intl_pl.arb @@ -1,8 +1,18 @@ { "@@locale": "pl", - "@@last_modified": "2021-11-11T01:02:08+01:00", - "newMessagesLabel": "New Messages", - "localeRU": "Russian", + "@@last_modified": "2021-11-21T17:42:07+01:00", + "manageKnownServersShort": "Servers", + "manageKnownServersLong": "Manage Known Servers", + "displayNameTooltip": "Please enter a display name", + "manageKnownServersButton": "Manage Known Servers", + "fieldDescriptionLabel": "Description", + "groupsOnThisServerLabel": "Groups I am in hosted on this server", + "importLocalServerButton": "Import %1", + "importLocalServerSelectText": "Select Local Server", + "importLocalServerLabel": "Import a locally hosted server", + "savePeerHistoryDescription": "Determines whether to delete any history associated with the contact.", + "newMessagesLabel": "Nowe wiadomości", + "localeRU": "Rosyjski", "copyServerKeys": "Kopiuj klucze", "verfiyResumeButton": "Zweryfikuj\/wznów", "fileCheckingStatus": "Sprawdzanie stanu pobierania", @@ -12,26 +22,26 @@ "encryptedServerDescription": "Encrypting a server with a password protects it from other people who may also use this device. Encrypted servers cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", "deleteServerConfirmBtn": "Naprawdę usuń serwer", "deleteServerSuccess": "Pomyślnie usunięto serwer", - "enterCurrentPasswordForDeleteServer": "Please enter current password to delete this server", + "enterCurrentPasswordForDeleteServer": "Wprowadź aktualne hasło, aby usunąć ten serwer", "copyAddress": "Skopiuj adres", "settingServersDescription": "The hosting servers experiment enables hosting and managing Cwtch servers", - "settingServers": "Hosting Servers", - "enterServerPassword": "Enter password to unlock server", + "settingServers": "Hosting serwerów", + "enterServerPassword": "Wprowadź hasło, aby odblokować serwer", "unlockProfileTip": "Please create or unlock a profile to begin!", "unlockServerTip": "Please create or unlock a server to begin!", - "addServerTooltip": "Add new server", - "serversManagerTitleShort": "Servers", - "serversManagerTitleLong": "Servers You Host", - "saveServerButton": "Save Server", + "addServerTooltip": "Dodaj nowy serwer", + "serversManagerTitleShort": "Serwery", + "serversManagerTitleLong": "Serwery, które hostujesz", + "saveServerButton": "Zapisz serwer", "serverAutostartDescription": "Controls if the application will automatically launch the server on start", "serverAutostartLabel": "Autostart", - "serverEnabledDescription": "Start or stop the server", - "serverEnabled": "Server Enabled", + "serverEnabledDescription": "Uruchom lub zatrzymaj serwer", + "serverEnabled": "Serwer włączony", "serverDescriptionDescription": "Your description of the server for personal management use only, will never be shared", - "serverDescriptionLabel": "Server Description", - "serverAddress": "Server Address", - "editServerTitle": "Edit Server", - "addServerTitle": "Add Server", + "serverDescriptionLabel": "Opis serwera", + "serverAddress": "Adres serwera", + "editServerTitle": "Edytuj serwer", + "addServerTitle": "Dodaj serwer", "titleManageProfilesShort": "Profile", "descriptionStreamerMode": "If turned on, this option makes the app more visually private for streaming or presenting with, for example, hiding profile and contact addresses", "descriptionFileSharing": "Eksperyment udostępniania plików pozwala na wysyłanie i odbieranie plików od kontaktów i grup Cwtch. Zauważ, że udostępnienie pliku grupie spowoduje, że członkowie tej grupy połączą się z Tobą bezpośrednio przez Cwtch, aby go pobrać.", @@ -55,70 +65,69 @@ "peerOfflineMessage": "Contact is offline, messages can't be delivered right now", "blockBtn": "Block Contact", "savePeerHistory": "Save History", - "savePeerHistoryDescription": "Determines whether or not to delete any history associated with the contact.", "dontSavePeerHistory": "Delete History", "unblockBtn": "Unblock Contact", "blockUnknownLabel": "Block Unknown Contacts", "blockUnknownConnectionsEnabledDescription": "Połączenia od nieznanych kontaktów są blokowane. Można to zmienić w Ustawieniach", "networkStatusConnecting": "Connecting to network and contacts...", - "showMessageButton": "Show Message", - "blockedMessageMessage": "This message is from a profile you have blocked.", - "placeholderEnterMessage": "Type a message...", + "showMessageButton": "Pokaż wiadomość", + "blockedMessageMessage": "Ta wiadomość pochodzi z profilu, który został przez Ciebie zablokowany.", + "placeholderEnterMessage": "Wpisz wiadomość...", "plainProfileDescription": "We recommend that you protect your Cwtch profiles with a password. If you do not set a password on this profile then anyone who has access to this device may be able to access information about this profile, including contacts, messages and sensitive cryptographic keys.", "encryptedProfileDescription": "Encrypting a profile with a password protects it from other people who may also use this device. Encrypted profiles cannot be decrypted, displayed or accessed until the correct password is entered to unlock them.", - "addContactConfirm": "Add contact %1", - "addContact": "Add contact", - "contactGoto": "Go to conversation with %1", - "settingUIColumnOptionSame": "Same as portrait mode setting", - "settingUIColumnDouble14Ratio": "Double (1:4)", - "settingUIColumnDouble12Ratio": "Double (1:2)", - "settingUIColumnSingle": "Single", + "addContactConfirm": "Dodaj kontakt %1", + "addContact": "Dodaj kontakt", + "contactGoto": "Przejdź do rozmowy z %1", + "settingUIColumnOptionSame": "Tak samo jak w przypadku trybu portretowego", + "settingUIColumnDouble14Ratio": "Podwójny (1:4)", + "settingUIColumnDouble12Ratio": "Podwójny (1:2)", + "settingUIColumnSingle": "Pojedynczy", "settingUIColumnLandscape": "UI Columns in Landscape Mode", "settingUIColumnPortrait": "UI Columns in Portrait Mode", - "localePl": "Polish", - "tooltipRemoveThisQuotedMessage": "Remove quoted message.", - "tooltipReplyToThisMessage": "Reply to this message", - "tooltipRejectContactRequest": "Reject this contact request", - "tooltipAcceptContactRequest": "Accept this contact request.", - "notificationNewMessageFromGroup": "New message in a group!", - "notificationNewMessageFromPeer": "New message from a contact!", - "tooltipHidePassword": "Hide Password", - "tooltipShowPassword": "Show Password", + "localePl": "Polski", + "tooltipRemoveThisQuotedMessage": "Usuń cytowaną wiadomość.", + "tooltipReplyToThisMessage": "Odpowiedz na tę wiadomość", + "tooltipRejectContactRequest": "Odrzuć tę prośbę o kontakt", + "tooltipAcceptContactRequest": "Zaakceptuj tę prośbę o kontakt.", + "notificationNewMessageFromGroup": "Nowa wiadomość w grupie!", + "notificationNewMessageFromPeer": "Nowa wiadomość od kontaktu!", + "tooltipHidePassword": "Ukryj hasło", + "tooltipShowPassword": "Pokaż hasło", "serverNotSynced": "Syncing New Messages (This can take some time)...", "groupInviteSettingsWarning": "You have been invited to join a group! Please enable the Group Chat Experiment in Settings to view this Invitation.", - "shutdownCwtchAction": "Shutdown Cwtch", + "shutdownCwtchAction": "Zamknij Cwtch", "shutdownCwtchDialog": "Are you sure you want to shutdown Cwtch? This will close all connections, and exit the application.", - "shutdownCwtchDialogTitle": "Shutdown Cwtch?", - "shutdownCwtchTooltip": "Shutdown Cwtch", - "malformedMessage": "Malformed message", - "profileDeleteSuccess": "Successfully deleted profile", - "debugLog": "Turn on console debug logging", - "torNetworkStatus": "Tor network status", + "shutdownCwtchDialogTitle": "Zamknąć Cwtch?", + "shutdownCwtchTooltip": "Zamknij Cwtch", + "malformedMessage": "Źle sformatowana wiadomość", + "profileDeleteSuccess": "Pomyślnie usunięto profil", + "debugLog": "Włącz logowanie debugowania konsoli", + "torNetworkStatus": "Stan sieci Tor", "addContactFirst": "Add or pick a contact to begin chatting.", "createProfileToBegin": "Please create or unlock a profile to begin", - "nickChangeSuccess": "Profile nickname changed successfully", + "nickChangeSuccess": "Nick w profilu został zmieniony pomyślnie", "addServerFirst": "You need to add a server before you can create a group", - "deleteProfileSuccess": "Successfully deleted profile", - "sendInvite": "Send a contact or group invite", - "sendMessage": "Send Message", - "cancel": "Cancel", + "deleteProfileSuccess": "Pomyślnie usunięto profil", + "sendInvite": "Wyślij kontakt lub zaproszenie do grupy", + "sendMessage": "Wyślij wiadomość", + "cancel": "Anuluj", "resetTor": "Reset", - "torStatus": "Tor Status", - "torVersion": "Tor Version", + "torStatus": "Status Tor", + "torVersion": "Wersja Tor", "sendAnInvitation": "You sent an invitation for: ", "contactSuggestion": "This is a contact suggestion for: ", - "rejected": "Rejected!", - "accepted": "Accepted!", + "rejected": "Odrzucone!", + "accepted": "Przyjęte!", "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.", - "newPassword": "New Password", - "yesLeave": "Yes, Leave This Conversation", + "newPassword": "Nowe hasło", + "yesLeave": "Tak, wyjdź z tej rozmowy", "reallyLeaveThisGroupPrompt": "Are you sure you want to leave this conversation? All messages and attributes will be deleted.", - "leaveGroup": "Leave This Conversation", + "leaveGroup": "Wyjdź z tej rozmowy", "inviteToGroup": "You have been invited to join a group:", "pasteAddressToAddContact": "Paste a cwtch address, invitation or key bundle here to add a new conversation", "tooltipAddContact": "Add a new contact or conversation", "titleManageContacts": "Conversations", - "titleManageServers": "Manage Servers", + "titleManageServers": "Zarządzaj serwerami", "dateNever": "Never", "dateLastYear": "Last Year", "dateYesterday": "Yesterday", @@ -190,7 +199,6 @@ "radioNoPassword": "Unencrypted (No password)", "radioUsePassword": "Password", "copiedToClipboardNotification": "Copied to Clipboard", - "copyBtn": "Copy", "editProfile": "Edit Profille", "newProfile": "New Profile", "defaultProfileName": "Alice", @@ -210,6 +218,7 @@ "acceptGroupInviteLabel": "Do you want to accept the invitation to", "newGroupBtn": "Create new group", "copiedClipboardNotification": "Copied to clipboard", + "copyBtn": "Copy", "pendingLabel": "Pending", "acknowledgedLabel": "Acknowledged", "couldNotSendMsgError": "Could not send this message", diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index 137e8a2b..533631d0 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -1,6 +1,16 @@ { "@@locale": "pt", - "@@last_modified": "2021-11-11T01:02:08+01:00", + "@@last_modified": "2021-11-21T17:42:07+01:00", + "manageKnownServersShort": "Servers", + "manageKnownServersLong": "Manage Known Servers", + "displayNameTooltip": "Please enter a display name", + "manageKnownServersButton": "Manage Known Servers", + "fieldDescriptionLabel": "Description", + "groupsOnThisServerLabel": "Groups I am in hosted on this server", + "importLocalServerButton": "Import %1", + "importLocalServerSelectText": "Select Local Server", + "importLocalServerLabel": "Import a locally hosted server", + "savePeerHistoryDescription": "Determines whether to delete any history associated with the contact.", "newMessagesLabel": "New Messages", "localeRU": "Russian", "copyServerKeys": "Copy keys", @@ -55,7 +65,6 @@ "peerOfflineMessage": "Contact is offline, messages can't be delivered right now", "blockBtn": "Block Contact", "savePeerHistory": "Save History", - "savePeerHistoryDescription": "Determines whether or not to delete any history associated with the contact.", "dontSavePeerHistory": "Delete History", "unblockBtn": "Unblock Contact", "blockUnknownLabel": "Block Unknown Contacts", @@ -190,7 +199,6 @@ "radioNoPassword": "Unencrypted (No password)", "radioUsePassword": "Password", "copiedToClipboardNotification": "Copiado", - "copyBtn": "Copiar", "editProfile": "Edit Profille", "newProfile": "New Profile", "defaultProfileName": "Alice", @@ -210,6 +218,7 @@ "acceptGroupInviteLabel": "Você quer aceitar o convite para", "newGroupBtn": "Criar novo grupo", "copiedClipboardNotification": "Copiado", + "copyBtn": "Copiar", "pendingLabel": "Pendente", "acknowledgedLabel": "Confirmada", "couldNotSendMsgError": "Não deu para enviar esta mensagem", diff --git a/lib/model.dart b/lib/model.dart index d2f68bda..9435dc3f 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -142,14 +142,10 @@ class ContactListState extends ChangeNotifier { } void addAll(Iterable newContacts) { - print("****** contactListState.addAll()... *********"); _contacts.addAll(newContacts); servers?.clearGroups(); - print("contact len: ${_contacts.length}"); _contacts.forEach((contact) { - //print("looking at contact ${contact.onion} (${contact.isGroup})..."); if (contact.isGroup) { - print("contactList adding group ${contact.onion} to ${contact.server}"); servers?.addGroup(contact); } }); @@ -159,7 +155,6 @@ class ContactListState extends ChangeNotifier { void add(ContactInfoState newContact) { _contacts.add(newContact); if (newContact.isGroup) { - print("contactList adding group ${newContact.onion} to ${newContact.server}"); servers?.addGroup(newContact); } notifyListeners(); @@ -299,6 +294,13 @@ class ProfileInfoState extends ChangeNotifier { // TODO Keys... return RemoteServerInfoState(onion: server["onion"], description: server["description"], status: server["status"]); })); + + this._contacts.contacts.forEach((contact) { + if (contact.isGroup) { + _servers.addGroup(contact); + } + }); + notifyListeners(); } } diff --git a/lib/models/profileservers.dart b/lib/models/profileservers.dart index ebd1cf99..cdf103f3 100644 --- a/lib/models/profileservers.dart +++ b/lib/models/profileservers.dart @@ -19,7 +19,7 @@ class ProfileServerListState extends ChangeNotifier { void updateServerState(String onion, String status) { int idx = _servers.indexWhere((element) => element.onion == onion); if (idx >= 0) { - _servers[idx] = RemoteServerInfoState(onion: onion, description: _servers[idx].description, status: status); + _servers[idx].status = status; } else { print("Tried to update server cache without a starting state...this is probably an error"); } @@ -31,11 +31,21 @@ class ProfileServerListState extends ChangeNotifier { _servers.sort((RemoteServerInfoState a, RemoteServerInfoState b) { // return -1 = a first in list // return 1 = b first in list + + // online v offline if (a.status == "Synced" && b.status != "Synced") { return -1; } else if (a.status != "Synced" && b.status == "Synced") { return 1; } + + // num of groups + if (a.groups.length > b.groups.length) { + return -1; + } else if (b.groups.length > a.groups.length) { + return 1; + } + return 0; }); } @@ -45,8 +55,6 @@ class ProfileServerListState extends ChangeNotifier { } void addGroup(ContactInfoState group) { - print("serverList adding group ${group.onion} to ${group.server}"); - int idx = _servers.indexWhere((element) => element.onion == group.server); if (idx >= 0) { _servers[idx].addGroup(group); @@ -59,7 +67,7 @@ class ProfileServerListState extends ChangeNotifier { class RemoteServerInfoState extends ChangeNotifier { final String onion; - final String status; + String status; String description; List _groups = []; @@ -71,21 +79,14 @@ class RemoteServerInfoState extends ChangeNotifier { } void clearGroups() { - print("Server CLEARING group"); - description = "cleared groups"; _groups = []; } void addGroup(ContactInfoState group) { - print("server $onion adding group ${group.onion}"); _groups.add(group); - print("now has ${_groups.length}"); - description = "i have ${_groups.length} groups"; notifyListeners(); } - int get groupsLen => _groups.length; - List get groups => _groups.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier } diff --git a/lib/views/addeditprofileview.dart b/lib/views/addeditprofileview.dart index 2355fd57..03084ca2 100644 --- a/lib/views/addeditprofileview.dart +++ b/lib/views/addeditprofileview.dart @@ -107,8 +107,7 @@ class _AddEditProfileViewState extends State { labelText: AppLocalizations.of(context)!.yourDisplayName, validator: (value) { if (value.isEmpty) { - // TODO l10n ize - return "Please enter a display name"; + return AppLocalizations.of(context)!.displayNameTooltip; } return null; }, diff --git a/lib/views/contactsview.dart b/lib/views/contactsview.dart index af776607..a05ef4df 100644 --- a/lib/views/contactsview.dart +++ b/lib/views/contactsview.dart @@ -113,11 +113,11 @@ class _ContactsViewState extends State { Clipboard.setData(new ClipboardData(text: Provider.of(context, listen: false).onion)); })); - // Manage servers + // Manage known Servers if (Provider.of(context, listen: false).isExperimentEnabled(ServerManagementExperiment)) { actions.add(IconButton( icon: Icon(CwtchIcons.dns_24px), - tooltip: "Manage known servers", //AppLocalizations.of(context)!.copyAddress, + tooltip: AppLocalizations.of(context)!.manageKnownServersButton, onPressed: () { _pushServers(); })); @@ -176,7 +176,7 @@ class _ContactsViewState extends State { Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) { return MultiProvider( - providers: [ChangeNotifierProvider(create: (context) => profile.serverList), Provider.value(value: Provider.of(context))], + providers: [ChangeNotifierProvider(create: (context) => profile), Provider.value(value: Provider.of(context))], child: ProfileServersView(), ); }, diff --git a/lib/views/profileserversview.dart b/lib/views/profileserversview.dart index aad94f85..7822ff96 100644 --- a/lib/views/profileserversview.dart +++ b/lib/views/profileserversview.dart @@ -5,7 +5,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:provider/provider.dart'; +import '../cwtch_icons_icons.dart'; +import '../main.dart'; import '../model.dart'; +import '../settings.dart'; class ProfileServersView extends StatefulWidget { @@ -23,16 +26,31 @@ class _ProfileServersView extends State { @override Widget build(BuildContext context) { + var knownServers = Provider.of(context).serverList.servers.map((RemoteServerInfoState remoteServer) { return remoteServer.onion + ".onion"; }).toSet(); + var importServerList = Provider.of(context).servers.where((server) => !knownServers.contains(server.onion) ).map>((ServerInfoState serverInfo) { + return DropdownMenuItem( + value: serverInfo.onion, + child: Text( + serverInfo.description.isNotEmpty ? serverInfo.description : serverInfo.onion, + overflow: TextOverflow.ellipsis, + ), + ); + }).toList(); + + importServerList.insert(0, DropdownMenuItem( + value: "", + child: Text(AppLocalizations.of(context)!.importLocalServerSelectText))); + return Scaffold( appBar: AppBar( title: Text(MediaQuery .of(context) .size - .width > 600 ? AppLocalizations.of(context)!.serversManagerTitleLong : AppLocalizations.of(context)!.serversManagerTitleShort), + .width > 600 ? AppLocalizations.of(context)!.manageKnownServersLong : AppLocalizations.of(context)!.manageKnownServersShort), //actions: getActions(), ), - body: Consumer( - builder: (context, servers, child) { + body: Consumer(builder: (context, profile, child) { + ProfileServerListState servers = profile.serverList; final tiles = servers.servers.map((RemoteServerInfoState server) { return ChangeNotifierProvider.value( value: server, @@ -46,14 +64,84 @@ class _ProfileServersView extends State { tiles: tiles, ).toList(); - // TODO: add import row from global servers - divided.insert(0, Row( children: [Text("Import server from global list if any")])); + final importCard = Card( child: ListTile( + title: Text(AppLocalizations.of(context)!.importLocalServerLabel), + leading: Icon(CwtchIcons.add_circle_24px , color: Provider.of(context).current().mainTextColor()), + trailing: DropdownButton( + onChanged: (String? importServer) { + if (importServer!.isNotEmpty) { + var server = Provider.of(context).getServer(importServer)!; + showImportConfirm(context, profile.onion, server.onion, server.description, server.serverBundle); + } + + }, + value: "", + items: importServerList, + + ))); + + return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) { + return Scrollbar( + isAlwaysShown: true, + child: SingleChildScrollView( + clipBehavior: Clip.antiAlias, + child: + Container( + margin: EdgeInsets.fromLTRB(5, 0, 5, 10), + padding: EdgeInsets.fromLTRB(5, 0, 5, 10), + child: Column(children: [ + + if (importServerList.length > 1) importCard, + + Column( children: divided ) + ]))));}); return ListView(children: divided); }, )); } + showImportConfirm(BuildContext context, String profileHandle, String serverHandle, String serverDesc, String bundle) { + var serverLabel = serverDesc.isNotEmpty ? serverDesc : serverHandle; + serverHandle = serverHandle.substring(0, serverHandle.length-6 ); // remove '.onion' + // set up the buttons + Widget cancelButton = ElevatedButton( + child: Text(AppLocalizations.of(context)!.cancel), + onPressed: () { + Navigator.of(context).pop(); // dismiss dialog + }, + ); + Widget continueButton = ElevatedButton( + child: Text(AppLocalizations.of(context)!.importLocalServerButton.replaceAll("%1", serverLabel)), + onPressed: () { + Provider.of(context, listen: false).cwtch.ImportBundle(profileHandle, bundle); + // Wait 500ms and hope the server is imported and add it's description in the UI and as an attribute + Future.delayed(const Duration(milliseconds: 500), () { + var profile = Provider.of(context); + profile.serverList.getServer(serverHandle)?.updateDescription(serverDesc); + Provider.of(context, listen: false).cwtch.SetContactAttribute(profile.onion, serverHandle, "local.server.description", serverDesc); + }); + Navigator.of(context).pop(); + }); + + // set up the AlertDialog + AlertDialog alert = AlertDialog( + title: Text(AppLocalizations.of(context)!.importLocalServerButton.replaceAll("%1", serverLabel)), + actions: [ + cancelButton, + continueButton, + ], + ); + + // show the dialog + showDialog( + context: context, + builder: (BuildContext context) { + return alert; + }, + ); + } + } \ No newline at end of file diff --git a/lib/views/remoteserverview.dart b/lib/views/remoteserverview.dart index 22bee1bf..e194da05 100644 --- a/lib/views/remoteserverview.dart +++ b/lib/views/remoteserverview.dart @@ -48,118 +48,102 @@ class _RemoteServerViewState extends State { @override Widget build(BuildContext context) { - return Consumer2(builder: (context, serverInfoState, settings, child) { + return Consumer3(builder: (context, profile, serverInfoState, settings, child) { return Scaffold( appBar: AppBar( title: Text(ctrlrDesc.text.isNotEmpty ? ctrlrDesc.text : serverInfoState.onion) ), - body: LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) { - return Scrollbar( - isAlwaysShown: true, - child: SingleChildScrollView( - clipBehavior: Clip.antiAlias, - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, - ), - child: Form( - key: _formKey, - child: Container( - margin: EdgeInsets.fromLTRB(30, 0, 30, 10), - padding: EdgeInsets.fromLTRB(20, 0, 20, 10), - child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + body: Container( + margin: EdgeInsets.fromLTRB(30, 0, 30, 10), + padding: EdgeInsets.fromLTRB(20, 0, 20, 10), + child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ + SizedBox( + height: 20, + ), + CwtchLabel(label: AppLocalizations.of(context)!.serverAddress), + SizedBox( + height: 20, + ), + SelectableText( + serverInfoState.onion + ), - Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - height: 20, - ), - CwtchLabel(label: AppLocalizations.of(context)!.serverAddress), - SizedBox( - height: 20, - ), - SelectableText( - serverInfoState.onion - ) - ]), + // Description + SizedBox( + height: 20, + ), + CwtchLabel(label: AppLocalizations.of(context)!.serverDescriptionLabel), + Text(AppLocalizations.of(context)!.serverDescriptionDescription), + SizedBox( + height: 20, + ), + CwtchButtonTextField( + controller: ctrlrDesc, + readonly: false, + tooltip: AppLocalizations.of(context)!.saveBtn, + labelText: AppLocalizations.of(context)!.fieldDescriptionLabel, + icon: Icon(Icons.save), + onPressed: () { + Provider.of(context, listen: false).cwtch.SetContactAttribute(profile.onion, serverInfoState.onion, "local.server.description", ctrlrDesc.text); + serverInfoState.updateDescription(ctrlrDesc.text); + }, + ), - // Description - Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - height: 20, - ), - CwtchLabel(label: AppLocalizations.of(context)!.serverDescriptionLabel), - Text(AppLocalizations.of(context)!.serverDescriptionDescription), - SizedBox( - height: 20, - ), - CwtchButtonTextField( - controller: ctrlrDesc, - readonly: false, - tooltip: "Save", //TODO localize - labelText: "Description", // TODO localize - icon: Icon(Icons.save), - onPressed: () { - // TODO save - }, - ) - ]), + SizedBox( + height: 20, + ), - Text("Groups on this server"), - _buildGroupsList(serverInfoState), + Padding(padding: EdgeInsets.all(8), child: Text( AppLocalizations.of(context)!.groupsOnThisServerLabel),), + Expanded(child: _buildGroupsList(serverInfoState)) + ]))); - ])))))); - }),); - }); + }); } Widget _buildGroupsList(RemoteServerInfoState serverInfoState) { - print("groups: ${serverInfoState.groups} lenMethod: ${serverInfoState.groupsLen} len: ${serverInfoState.groups.length}"); final tiles = serverInfoState.groups.map((ContactInfoState group) { - print("building group tile for ${group.onion}"); - return ChangeNotifierProvider.value(key: ValueKey(group.profileOnion + "" + group.onion), value: group, builder: (_, __) => RepaintBoundary(child: _buildGroupRow(group))); - }); + return ChangeNotifierProvider.value( + value: group, + builder: (context, child) => RepaintBoundary(child: _buildGroupRow(group)), // ServerRow()), + ); + }, + ); + final divided = ListTile.divideTiles( context: context, tiles: tiles, ).toList(); - return RepaintBoundary(child: ListView(children: divided)); - } - void _savePressed() { + var size = MediaQuery.of(context).size; - var server = Provider.of(context, listen: false); + int cols = ((size.width - 50) / 500).ceil(); + final double itemHeight = 60; // magic arbitary + final double itemWidth = (size.width - 50 /* magic padding guess */) / cols; - Provider.of(context, listen: false) - .cwtch.SetServerAttribute(server.onion, "description", ctrlrDesc.text); - server.setDescription(ctrlrDesc.text); - - - if (_formKey.currentState!.validate()) { - // TODO support change password - } - Navigator.of(context).pop(); + return GridView.count(crossAxisCount: cols, childAspectRatio: (itemWidth / itemHeight), children: divided); } Widget _buildGroupRow(ContactInfoState group) { - return Column( - children: [ - Text( - group.nickname, - style: Provider.of(context).biggerFont.apply(color: Provider.of(context).theme.portraitOnlineBorderColor()), - softWrap: true, - overflow: TextOverflow.ellipsis, - ), - Visibility( - visible: !Provider.of(context).streamerMode, - child: ExcludeSemantics( - child: Text( - group.onion, - softWrap: true, - overflow: TextOverflow.ellipsis, - style: TextStyle(color: Provider.of(context).theme.portraitOnlineBorderColor()), - ))) - ], + return Padding( + padding: const EdgeInsets.all(6.0), //border size + child: Column( + children: [ + Text( + group.nickname, + style: Provider.of(context).biggerFont.apply(color: Provider.of(context).theme.portraitOnlineBorderColor()), + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + Visibility( + visible: !Provider.of(context).streamerMode, + child: ExcludeSemantics( + child: Text( + group.onion, + softWrap: true, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: Provider.of(context).theme.portraitOnlineBorderColor()), + ))) + ]) ); } diff --git a/lib/widgets/remoteserverrow.dart b/lib/widgets/remoteserverrow.dart index 0df655d2..339a170d 100644 --- a/lib/widgets/remoteserverrow.dart +++ b/lib/widgets/remoteserverrow.dart @@ -25,53 +25,54 @@ class _RemoteServerRowState extends State { var server = Provider.of(context); var description = server.description.isNotEmpty ? server.description : server.onion; var running = server.status == "Synced"; - return Card(clipBehavior: Clip.antiAlias, - margin: EdgeInsets.all(0.0), - child: InkWell( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.all(6.0), //border size - child: Icon(CwtchIcons.dns_24px, - color: running ? Provider.of(context).theme.portraitOnlineBorderColor() : Provider.of(context).theme.portraitOfflineBorderColor(), - size: 64) + return Consumer( + builder: (context, profile, child) { + return Card(clipBehavior: Clip.antiAlias, + margin: EdgeInsets.all(0.0), + child: InkWell( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(6.0), //border size + child: Icon(CwtchIcons.dns_24px, + color: running ? Provider.of(context).theme.portraitOnlineBorderColor() : Provider.of(context).theme.portraitOfflineBorderColor(), + size: 64) - ), - Expanded( - child: Column( - children: [ - Text( - description, - semanticsLabel: description, - style: Provider.of(context).biggerFont.apply(color: running ? Provider.of(context).theme.portraitOnlineBorderColor() : Provider.of(context).theme.portraitOfflineBorderColor()), - softWrap: true, - overflow: TextOverflow.ellipsis, - ), - Visibility( - visible: !Provider.of(context).streamerMode, - child: ExcludeSemantics( - child: Text( - server.onion, - softWrap: true, - overflow: TextOverflow.ellipsis, - style: TextStyle(color: running ? Provider.of(context).theme.portraitOnlineBorderColor() : Provider.of(context).theme.portraitOfflineBorderColor()), - ))) - ], - )), + ), + Expanded( + child: Column( + children: [ + Text( + description, + semanticsLabel: description, + style: Provider.of(context).biggerFont.apply(color: running ? Provider.of(context).theme.portraitOnlineBorderColor() : Provider.of(context).theme.portraitOfflineBorderColor()), + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + Visibility( + visible: !Provider.of(context).streamerMode, + child: ExcludeSemantics( + child: Text( + server.onion, + softWrap: true, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: running ? Provider.of(context).theme.portraitOnlineBorderColor() : Provider.of(context).theme.portraitOfflineBorderColor()), + ))) + ], + )), - ]), - onTap: () { - Navigator.of(context).push(MaterialPageRoute( + ]), + onTap: () { + Navigator.of(context).push(MaterialPageRoute( settings: RouteSettings(name: "remoteserverview"), builder: (BuildContext context) { return MultiProvider( - providers: [ChangeNotifierProvider(create: (context) => server), Provider.value(value: Provider.of(context))], + providers: [Provider.value(value: profile), ChangeNotifierProvider(create: (context) => server), Provider.value(value: Provider.of(context))], child: RemoteServerView(), ); })); - } - )); - } - -} \ No newline at end of file + } + ));}); + } +}