diff --git a/dist/android/sources b/dist/android/sources index 65fae394ca791b990578f5dde1e49f5e97fd34fa..17788c85b43b1fa75287a80454349948068cc457 160000 --- a/dist/android/sources +++ b/dist/android/sources @@ -1 +1 @@ -Subproject commit 65fae394ca791b990578f5dde1e49f5e97fd34fa +Subproject commit 17788c85b43b1fa75287a80454349948068cc457 diff --git a/doc/build_ios.md b/doc/build_ios.md index 155d549d0168a642babaf63b31be58e1793ca6a8..6856698c6f156d2fd1adb89ca23cb1de3d4b5c70 100644 --- a/doc/build_ios.md +++ b/doc/build_ios.md @@ -82,7 +82,7 @@ npm install -g nw-gyp node-pre-gyp 2. Install global dependencies (see [Development Guide](./development_guide.md) for versions to used) : ``` -npm install -g yarn gulp@3.9.1 cordova @ionic/cli@6.6.0 +npm install -g yarn gulp cordova @ionic/cli@6.20.9 ``` 3. Install project dependencies : diff --git a/package.json b/package.json index 6b12f65dbef7534e16845d226a96e3455215444d..356ca61bfff6d5820c2ba9d03a3264fc1c35b8f4 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "cordova-plugin-customurlscheme": "^5.0.2", "cordova-plugin-device": "^2.1.0", "cordova-plugin-dialogs": "^2.0.2", - "cordova-plugin-file": "^6.0.2", + "cordova-plugin-file": "^8.0.0", "cordova-plugin-ionic-keyboard": "^2.2.0", "cordova-plugin-ionic-webview": "^5.0.0", "cordova-plugin-network-information": "~3.0.0", @@ -156,7 +156,7 @@ "map-stream": "0.0.7", "merge2": "^1.3.0", "mv": "^2.1.1", - "node-sass": "^8.0.0", + "node-sass": "^9.0.0", "phonegap-plugin-barcodescanner": "^8.1.0", "playup": "^1.1.0", "vinyl-fs": "^3.0.3", diff --git a/platforms/android b/platforms/android deleted file mode 160000 index 583a19c5d1733a606e68f72ecbb124ce2d1316cc..0000000000000000000000000000000000000000 --- a/platforms/android +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 583a19c5d1733a606e68f72ecbb124ce2d1316cc diff --git a/resources/android/build/app/libs/libsodium-jni-release.aar b/resources/android/build/app/libs/libsodium-jni-release.aar deleted file mode 100644 index a88fe7e2303dfc4648ee16dd53c0a9f43b747dac..0000000000000000000000000000000000000000 Binary files a/resources/android/build/app/libs/libsodium-jni-release.aar and /dev/null differ diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss index 39bd50f55e2e8dfc6a8ee2250c9f0a61717a32be..fba9deb1811e3566aa054eb53a91ac5bdead6aa5 100644 --- a/scss/ionic.app.scss +++ b/scss/ionic.app.scss @@ -1282,10 +1282,11 @@ html, body { } } -.stable-100-bg { - background-color: $stable-100-bg !important; +.popover-wallet-tx-actions { + height: 120px; } + /****** * TX view (wallet or identity) *******/ @@ -1394,6 +1395,7 @@ html, body { filter: alpha(opacity=80); } + .card.stable-900-bg, .card .stable-900-bg, .item.stable-900-bg, @@ -2570,6 +2572,11 @@ div[drop-zone]:hover { /********** Wot identity **********/ + +.stable-100-bg { + background-color: $stable-100-bg !important; +} + .hero.dark-100-bg { background-color: $dark-100-bg; } diff --git a/www/i18n/locale-ca.json b/www/i18n/locale-ca.json index a93f3cb02ca8e783fcaaf5f70daab7a3dbdbfe37..8c1613b1188c35daab8398d8128db5b3d1157aab 100644 --- a/www/i18n/locale-ca.json +++ b/www/i18n/locale-ca.json @@ -51,6 +51,7 @@ "LOADING": "Esperi si us plau...", "LOADING_WAIT": "Esperi si us plau...<br/><small>(Cesium està interrogant el node Duniter)</small>", "SEARCHING": "Cerca en procés...", + "DOWNLOADING_DOTS": "Descarregant...", "FROM": "De", "TO": "A", "COPY": "Còpia", @@ -694,7 +695,7 @@ "NO_WALLET": "Sin monedero secundario", "BTN_DELETE": "Eliminar un monedero secundario…", "BTN_RENAME": "Renombrar el monedero", - "EXPORT_FILENAME": "monederos-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-monederos-{{pubkey}}.csv", "TOTAL_DOTS": "Total : ", "EDIT_POPOVER": { "TITLE": "Renombrar el monedero", @@ -728,7 +729,7 @@ "RECOVER_ID_SELECT_FILE": "Elija el <b>archivo para salvaguardar sus credenciales</b> a utilizar :", "GENERATE_KEYFILE": "Generar mi archivo de llaves…", "GENERATE_KEYFILE_HELP": "Genera un archivo que le permitirá atenticarse sin tener que introducir las credenciales.<br/><b>Cuidado:</b> este archivo contendrá su llave secreta; ¡Es muy importante conservarlo en un lugar seguro!", - "KEYFILE_FILENAME": "llavero-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-llavero-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Registrarse como miembro…", "MEMBERSHIP_IN_HELP": "Le permite <b>transformar</b> una cuenta de monedero simple <b>en una cuenta miembro</b>, enviando una petición de membresÃa. Solo si todavÃa no tiene una cuenta miembro.", "SEND_IDENTITY": "Publicar identidad…", @@ -760,16 +761,17 @@ "REVOCATION_WITH_FILE": "Revocar una identidad a partir de un fichero", "REVOCATION_WITH_FILE_DESCRIPTION": "Si ha perdido de forma permanente las credenciales de su cuenta miembro (o la seguridad de la cuenta se ve comprometida), puede usar <b>el archivo de revocación de la cuenta</b> para forzar la salida de la Red de Confianza.", "REVOCATION_WITH_FILE_HELP": "Para <b>revocar permanentemente</b> una cuenta miembro, arrastre el archivo de revocación en el cuadro siguiente o haga clic en el cuadro para seleccionar un archivo.", - "REVOCATION_FILENAME": "revocacion-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revocacion-{{uid}}-{{pubkey}}.txt", "REVOCATION_WALLET": "Revocar esta identidad", "SAVE_ID": "Guardar mis credenciales", "STRONG_LEVEL": "Alto <span class=\"hidden-xs \">(6 preguntas min.)</span>", "TITLE": "Cuenta y seguridad", "RECOVER_ID_HELP": "Si dispone de un <b>archivo de recuperación de sus credenciales</b>, las puede reobtener respondiendo correctamente a las preguntas personales elegidas en su momento.", "REVOCATION_WALLET_HELP": "Pedir la revocación de vuestra identidad comporta la <b>salida de la red de confianza</b> (definitiva para el seudónimo y la llave pública asociada). La cuenta no producirá ya más el Dividendo Universal.<br/>Podrá seguir usándola como monedero simple.", - "SAVE_ID_HELP": "Creación de un archivo de recuperación, para <b>reobtener su contraseña</b> (y frase secreta) en caso de olvido. El archivo se <b>cifra</b> con ayuda de las preguntas personales elegidas." + "SAVE_ID_HELP": "Creación de un archivo de recuperación, para <b>reobtener su contraseña</b> (y frase secreta) en caso de olvido. El archivo se <b>cifra</b> con ayuda de las preguntas personales elegidas.", + "SAVE_ID_FILENAME": "{{currency}}-credencials-{{pubkey}}.txt" }, - "FILE_NAME": "{{currency}}_HistorialDeCuenta_{{pubkey|formatPubkey}}_{{currentTime|formatDateForFile}}.csv", + "FILE_NAME": "{{currency}}-HistorialDeCuenta-{{pubkey}}-{{currentTime|formatDateForFile}}.csv", "HEADERS": { "TIME": "Fecha", "AMOUNT": "Cantidad", @@ -890,6 +892,7 @@ "GET_BLOCK_FAILED": "Error en la recuperación del bloque", "INVALID_BLOCK_HASH": "Bloque no encontrado (hash diferente)", "DOWNLOAD_REVOCATION_FAILED": "Debe seleccionar un fichero de texto", + "DOWNLOAD_SAVE_ID_FAILED": "Error en baixar l'arxiu de còpia de seguretat de les credencials.", "REVOCATION_FAILED": "Error en la revocación.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Frase secreta o contraseña incorrectos", "RECOVER_ID_FAILED": "Error en la recuperación de las credenciales", @@ -904,7 +907,8 @@ "INVALID_FILE_FORMAT": "Formato de archivo inválido.", "SAME_TX_RECIPIENT": "El destinatario debe ser diferente del emisor.", "SELF_CERTIFICATION": "No pots certificar la teva pròpia identitat.", - "TX_SANDBOX_FULL": "El node Duniter utilitzat per Cesium ja no pot rebre transferències noves, perquè la cua està plena.<br/><br/>Torneu-ho a provar o canvieu els nodes (a través del menú <b>Configuració</b>)." + "TX_SANDBOX_FULL": "El node Duniter utilitzat per Cesium ja no pot rebre transferències noves, perquè la cua està plena.<br/><br/>Torneu-ho a provar o canvieu els nodes (a través del menú <b>Configuració</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Error en descarregar l'extracte de compte" }, "INFO": { "POPUP_TITLE": "Información", @@ -921,7 +925,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "La <b>revocación de esta identidad</b> fue solicitada y está en espera de ser procesada.", "FEATURES_NOT_IMPLEMENTED": "Esta funcionalidad todavÃa está en proceso de desarrollo.<br/><br/>¿Por qué no <b>contribuir a Cesium</b>, para obtenerla más rápido? ;)", "EMPTY_TX_HISTORY": "Ninguna operación a exportar", - "LOADING_PENDING_TX": "Esperi si us plau...<br/><small>(Recuperant operacions pendents)</small>" + "LOADING_PENDING_TX": "Esperi si us plau...<br/><small>(Recuperant operacions pendents)</small>", + "FILE_DOWNLOADED": "Fitxer descarregat" }, "CONFIRM": { "EXIT_APP": "¿ Cerrar la aplicación ?", diff --git a/www/i18n/locale-de-DE.json b/www/i18n/locale-de-DE.json index dca7b56446bc030f9ac742735aa2d7676cc7fff4..162cbc7c9a861efda715eaea3c1857c6bb3e7460 100644 --- a/www/i18n/locale-de-DE.json +++ b/www/i18n/locale-de-DE.json @@ -51,6 +51,7 @@ "LOADING": "Lade...", "LOADING_WAIT": "Lade...<br/><small>(Cesium fragt den Duniter-Knoten ab)</small>", "SEARCHING": "Suche...", + "DOWNLOADING_DOTS": "Herunterladen...", "FROM": "Von", "TO": "An", "COPY": "Kopieren", @@ -615,7 +616,7 @@ "NO_WALLET": "Keine sekundäre Brieftasche", "BTN_DELETE": "Eine sekundäre Brieftasche entfernen...", "BTN_RENAME": "Brieftasche umbenennen", - "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-my_wallets-{{pubkey}}.csv", "TOTAL_DOTS": "Gesamt: ", "EDIT_POPOVER": { "TITLE": "Brieftasche umbenennen", @@ -637,7 +638,7 @@ "DOWNLOAD_REVOKE_HELP" : "Eine Sperrdatei ist wichtig, zum Beispiel bei Verlust von Zugangsdaten. Sie ermöglicht dir, <b>dieses Konto aus dem Netz des Vertrauens herauszuholen</b> und es zu einer einfachen Brieftasche zu machen.", "GENERATE_KEYFILE": "Meine Schlüsselbund-Datei generieren ...", "GENERATE_KEYFILE_HELP": "Generiere eine Datei, mit der du dich authentifizieren kannst, ohne deine Zugangsdaten einzugeben.<br/><b>Warnung:</b> Diese Datei enthält Ihren geheimen Schlüssel. Es ist daher sehr wichtig, sie an einem sicheren Ort aufzubewahren!", - "KEYFILE_FILENAME": "keychain-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-keychain-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Als Mitglied registrieren...", "MEMBERSHIP_IN_HELP": "Ermöglicht es dir, ein einfaches Brieftaschen-Konto <b>in ein Mitgliedskonto umzuwandeln</b>, indem du eine Mitgliedschaftsanfrage sendest. Nur erlaubt, wenn du noch kein anderes Mitgliedskonto hast.", "SEND_IDENTITY": "Pseudonym veröffentlichen...", @@ -673,9 +674,10 @@ "REVOCATION_WITH_FILE_HELP": "Um ein Mitgliedskonto <b>dauerhaft zu widerrufen</b>, ziehe bitte die Widerrufsdatei in das Feld unten oder klicke in das Feld, um nach einer Datei zu suchen.", "REVOCATION_WALLET": "Dieses Konto sofort widerrufen", "REVOCATION_WALLET_HELP": "Die Anforderung des Widerrufs Ihrer Identität führt dazu, dass <b>Ihre Mitgliedschaft widerrufen wird</b> (auf jeden Fall für das zugehörige Pseudonym und den öffentlichen Schlüssel). Das Konto ist dann nicht mehr in der Lage, eine Universaldividende zu produzieren.<br/>Sie können es jedoch weiterhin als einfache Brieftasche verwenden.", - "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revocation-{{uid}}-{{pubkey}}.txt", "SAVE_ID": "Meine Zugangsdaten speichern...", "SAVE_ID_HELP": "Erstellen einer Sicherungsdatei, um <b>dein Passwort</b> (und den geheimen Benutzernamen) <b>wiederzuerlangen, falls du es vergisst</b>. Die Datei ist mit personenbezogenen Fragen <b>gesichert</b> (verschlüsselt).", + "SAVE_ID_FILENAME": "{{currency}}-anmeldeinformationen-{{pubkey}}.txt", "STRONG_LEVEL": "Hoch <span class=\"hidden-xs \">(6 Fragen Minimum)</span>", "TITLE": "Konto and Sicherheit", "KEYFILE": { @@ -696,7 +698,7 @@ } } }, - "FILE_NAME": "{{currency}} - Kontozusammenfassung {{pubkey|formatPubkey}} {{currentTime|formatDateForFile}}.csv", + "FILE_NAME": "{{currency}}-Kontozusammenfassung-{{pubkey}}-{{currentTime|formatDateForFile}}.csv", "HEADERS": { "TIME": "Datum", "AMOUNT": "Betrag", @@ -809,6 +811,7 @@ "GET_BLOCK_FAILED": "Fehler beim Holen eines Blocks", "INVALID_BLOCK_HASH": "Block nicht gefunden (falscher Hashwert)", "DOWNLOAD_REVOCATION_FAILED": "Fehler beim Herunterladen der Widerrufsdatei.", + "DOWNLOAD_SAVE_ID_FAILED": "Fehler beim Herunterladen der Sicherungsdatei für die Anmeldeinformationen.", "REVOCATION_FAILED": "Fehler bei dem Versuch, die Identität zu widerrufen.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Falscher geheimer Benutzername oder Passwort", "RECOVER_ID_FAILED": "Konnte Passwort nicht wiederherstellen", @@ -833,7 +836,8 @@ "INVALID_FILE_FORMAT": "Ungültiges Dateiformat.", "SAME_TX_RECIPIENT": "Der Empfänger muss sich vom Auftraggeber unterscheiden.", "SELF_CERTIFICATION": "Sie können Ihre eigene Identität nicht zertifizieren.", - "TX_SANDBOX_FULL": "Der von Cesium verwendete Duniter-Knoten kann keine neuen Überweisungen mehr bearbeiten, da die Warteschlange voll ist.<br/><br/>Versuche es später erneut oder wähle einen anderen Duniter-Knoten (in den <b>Einstellungen</b>)." + "TX_SANDBOX_FULL": "Der von Cesium verwendete Duniter-Knoten kann keine neuen Überweisungen mehr bearbeiten, da die Warteschlange voll ist.<br/><br/>Versuche es später erneut oder wähle einen anderen Duniter-Knoten (in den <b>Einstellungen</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Fehler beim Herunterladen des Kontoauszugs" }, "INFO": { "POPUP_TITLE": "Hinweis", @@ -851,7 +855,8 @@ "FEATURE_NOT_AVAILABLE_ON_DEMO": "Diese Funktion ist auf der Demo-Version nicht verfügbar.<br/>Aus <b>Sicherheitsgründen</b> empfehlen wir dir, eine Kopie der Software zu <b>installieren</b>.<br/>Besuche die Webseite <a href='https://cesium.app'>www.cesium.app</a> für Hilfe und weitere Informationen.", "FEATURES_NOT_IMPLEMENTED": "Diese Funktion ist noch nicht implementiert.<br/><br/>Warum nicht mitwirken, um sie schneller zu erhalten? ;)", "EMPTY_TX_HISTORY": "Keine Tansaktionen für den Export vorhanden.", - "LOADING_PENDING_TX": "Lade...<br/><small>(Abrufen von ausstehenden Operationen)</small>" + "LOADING_PENDING_TX": "Lade...<br/><small>(Abrufen von ausstehenden Operationen)</small>", + "FILE_DOWNLOADED": "Datei heruntergeladen" }, "CONFIRM": { "CAN_CONTINUE": "<b>Bist du sicher</b>, dass du fortfahren möchtest?", diff --git a/www/i18n/locale-en-GB.json b/www/i18n/locale-en-GB.json index 97ae039e5f7f530d3d17393dda71acba509c5a5f..70a4df1cd558fc0301f469260250dde697064ddf 100644 --- a/www/i18n/locale-en-GB.json +++ b/www/i18n/locale-en-GB.json @@ -51,6 +51,7 @@ "LOADING": "Loading...", "LOADING_WAIT": "Loading...<br/><small>(Cesium is querying the Duniter peer)</small>", "SEARCHING": "Searching...", + "DOWNLOADING_DOTS": "Downloading...", "FROM": "From", "TO": "To", "COPY": "Copy", @@ -601,7 +602,7 @@ "NO_WALLET": "No secondary wallet", "BTN_DELETE": "Remove a secondary wallet...", "BTN_RENAME": "Rename the wallet", - "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-my_wallets-{{pubkey}}.csv", "TOTAL_DOTS": "Total: ", "EDIT_POPOVER": { "TITLE": "Rename the wallet", @@ -623,7 +624,7 @@ "DOWNLOAD_REVOKE_HELP" : "Having a revocation file is important, for example in case of loss of identifiers. It allows you to <b>get this account out of the Web Of Trust</b>, thus becoming a simple wallet.", "GENERATE_KEYFILE": "Generate my keychain file ...", "GENERATE_KEYFILE_HELP": "Generate a file allowing you to authenticate without entering your identifiers.<br/><b>Warning:</b> this file will contain your secret key; It is therefore very important to put it in a safe place!", - "KEYFILE_FILENAME": "keychain-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-keychain-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Register as member...", "MEMBERSHIP_IN_HELP": "Allows you to <b>transform </b> a simple wallet account <b>into a member account</b>, by sending a membership request. Useful only if you do not already have another member account.", "SEND_IDENTITY": "Publish identity...", @@ -659,7 +660,7 @@ "REVOCATION_WITH_FILE_HELP": "To <b>permanently revoke</ b> a member account, please drag the revocation file in the box below, or click in the box to search for a file.", "REVOCATION_WALLET": "Revoke this account immediately", "REVOCATION_WALLET_HELP": "Requesting revocation of your identity causes <b>will revoke your membership</ b> (definitely for the associated pseudonym and public key). The account will no longer be able to produce a Universal Dividend.<br/>However, you can still use it as a simple wallet.", - "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revocation-{{uid}}-{{pubkey}}.txt", "SAVE_ID": "Save my credentials...", "SAVE_ID_HELP": "Creating a backup file, to <b>retrieve your password</b> (and the secret identifier) <b> in case of forgetting</b>. The file is <b>secured</ b> (encrypted) using personal questions.", "STRONG_LEVEL": "Strong <span class=\"hidden-xs \">(6 questions minimum)</span>", @@ -795,6 +796,7 @@ "GET_BLOCK_FAILED": "Error while getting block", "INVALID_BLOCK_HASH": "Block not found (incorrect hash)", "DOWNLOAD_REVOCATION_FAILED": "Error while downloading revocation file.", + "DOWNLOAD_SAVE_ID_FAILED": "Failed to download the credentials backup file.", "REVOCATION_FAILED": "Error while trying to revoke the identity.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Wrong secret identifier or password ", "RECOVER_ID_FAILED": "Could not recover password", @@ -819,7 +821,8 @@ "INVALID_FILE_FORMAT": "Invalid file format.", "SAME_TX_RECIPIENT": "The recipient must be different from the issuer.", "SELF_CERTIFICATION": "You cannot certify your own identity.", - "TX_SANDBOX_FULL": "The Duniter peer used by Cesium can no longer process new transfers, as its queue is full.<br/><br/>Please try again later or change the peer (in the <b>Settings</b>)." + "TX_SANDBOX_FULL": "The Duniter peer used by Cesium can no longer process new transfers, as its queue is full.<br/><br/>Please try again later or change the peer (in the <b>Settings</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Error downloading the account statement" }, "INFO": { "POPUP_TITLE": "Information", @@ -836,7 +839,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.", "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)", "EMPTY_TX_HISTORY": "No operations to export", - "LOADING_PENDING_TX": "Please wait...<br/><small>(Retrieving pending operations)</small>" + "LOADING_PENDING_TX": "Please wait...<br/><small>(Retrieving pending operations)</small>", + "FILE_DOWNLOADED": "File downloaded" }, "CONFIRM": { "CAN_CONTINUE": "<b>Are you sure</b> you want to continue?", diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json index a23d15730163dab1e1bd53a918f2421b07531f8b..3ad8f8db22291afe0449d38569ee0b12cd5aed8c 100644 --- a/www/i18n/locale-en.json +++ b/www/i18n/locale-en.json @@ -51,6 +51,7 @@ "LOADING": "Loading...", "LOADING_WAIT": "Loading...<br/><small>(Cesium is querying the Duniter peer)</small>", "SEARCHING": "Searching...", + "DOWNLOADING_DOTS": "Downloading...", "FROM": "From", "TO": "To", "COPY": "Copy", @@ -601,7 +602,7 @@ "NO_WALLET": "No secondary wallet", "BTN_DELETE": "Remove a secondary wallet...", "BTN_RENAME": "Rename the wallet", - "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-my_wallets-{{pubkey}}.csv", "TOTAL_DOTS": "Total: ", "EDIT_POPOVER": { "TITLE": "Rename the wallet", @@ -623,7 +624,7 @@ "DOWNLOAD_REVOKE_HELP" : "Having a revocation file is important, for example in case of loss of identifiers. It allows you to <b>get this account out of the Web Of Trust</b>, thus becoming a simple wallet.", "GENERATE_KEYFILE": "Generate my keychain file ...", "GENERATE_KEYFILE_HELP": "Generate a file allowing you to authenticate without entering your identifiers.<br/><b>Warning:</b> this file will contain your secret key; It is therefore very important to put it in a safe place!", - "KEYFILE_FILENAME": "keychain-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-keychain-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Register as member...", "MEMBERSHIP_IN_HELP": "Allows you to <b>transform </b> a simple wallet account <b>into a member account</b>, by sending a membership request. Useful only if you do not already have another member account.", "SEND_IDENTITY": "Publish identity...", @@ -659,9 +660,10 @@ "REVOCATION_WITH_FILE_HELP": "To <b>permanently revoke</ b> a member account, please drag the revocation file in the box below, or click in the box to search for a file.", "REVOCATION_WALLET": "Revoke this account immediately", "REVOCATION_WALLET_HELP": "Requesting revocation of your identity causes <b>will revoke your membership</ b> (definitely for the associated pseudonym and public key). The account will no longer be able to produce a Universal Dividend.<br/>However, you can still use it as a simple wallet.", - "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revocation-{{uid}}-{{pubkey}}.txt", "SAVE_ID": "Save my credentials...", - "SAVE_ID_HELP": "Creating a backup file, to <b>retrieve your password</b> (and the secret identifier) <b> in case of forgetting</b>. The file is <b>secured</ b> (encrypted) using personal questions.", + "SAVE_ID_HELP": "Creating a backup file, to <b>retrieve your password</b> (and the secret identifier) <b>in case of forgetting</b>. The file is <b>secured</ b> (encrypted) using personal questions.", + "SAVE_ID_FILENAME": "{{currency}}-credentials-{{pubkey}}.txt", "STRONG_LEVEL": "Strong <span class=\"hidden-xs \">(6 questions minimum)</span>", "TITLE": "Account and security", "KEYFILE": { @@ -682,7 +684,7 @@ } } }, - "FILE_NAME": "{{currency}} - Account statement {{pubkey|formatPubkey}} to {{currentTime|formatDateForFile}}.csv", + "FILE_NAME": "{{currency}}-Account_statement-{{pubkey}}-{{currentTime|formatDateForFile}}.csv", "HEADERS": { "TIME": "Date", "AMOUNT": "Amount", @@ -795,6 +797,7 @@ "GET_BLOCK_FAILED": "Error while getting block", "INVALID_BLOCK_HASH": "Block not found (incorrect hash)", "DOWNLOAD_REVOCATION_FAILED": "Error while downloading revocation file.", + "DOWNLOAD_SAVE_ID_FAILED": "Failed to download the credentials backup file.", "REVOCATION_FAILED": "Error while trying to revoke the identity.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Wrong secret identifier or password ", "RECOVER_ID_FAILED": "Could not recover password", @@ -819,7 +822,8 @@ "INVALID_FILE_FORMAT": "Invalid file format.", "SAME_TX_RECIPIENT": "The recipient must be different from the issuer.", "SELF_CERTIFICATION": "You cannot certify your own identity.", - "TX_SANDBOX_FULL": "The Duniter peer used by Cesium can no longer process new transfers, as its queue is full.<br/><br/>Please try again later or change the peer (in the <b>Settings</b>)." + "TX_SANDBOX_FULL": "The Duniter peer used by Cesium can no longer process new transfers, as its queue is full.<br/><br/>Please try again later or change the peer (in the <b>Settings</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Error downloading the account statement" }, "INFO": { "POPUP_TITLE": "Information", @@ -836,7 +840,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "Revocation <b>has been sent successfully</b>. It is awaiting processing.", "FEATURES_NOT_IMPLEMENTED": "This features is not implemented yet.<br/><br/>Why not to contribute to get it faster? ;)", "EMPTY_TX_HISTORY": "No operations to export", - "LOADING_PENDING_TX": "Please wait...<br/><small>(Retrieving pending operations)</small>" + "LOADING_PENDING_TX": "Please wait...<br/><small>(Retrieving pending operations)</small>", + "FILE_DOWNLOADED": "File downloaded" }, "CONFIRM": { "CAN_CONTINUE": "<b>Are you sure</b> you want to continue?", diff --git a/www/i18n/locale-eo-EO.json b/www/i18n/locale-eo-EO.json index b355afdff59712f41e5b807be21524ea3232470e..5a5dda2647454ebb81c778a7288837dbb322b394 100644 --- a/www/i18n/locale-eo-EO.json +++ b/www/i18n/locale-eo-EO.json @@ -51,6 +51,7 @@ "LOADING": "Bonvolu pacienci...", "LOADING_WAIT": "Bonvolu pacienci...<br/><small>(Cesium demandas la Duniter-nodon)</small>", "SEARCHING": "Serĉanta...", + "DOWNLOADING_DOTS": "ElÅutanta...", "FROM": "De", "TO": "Al", "COPY": "Kopii", @@ -600,7 +601,7 @@ "NO_WALLET": "Neniu kroma monujo", "BTN_DELETE": "Forigi kroman monujon...", "BTN_RENAME": "Renomi la monujon", - "EXPORT_FILENAME": "miaj_monujoj-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-miaj_monujoj-{{pubkey}}.csv", "TOTAL_DOTS": "Sumo: ", "EDIT_POPOVER": { "TITLE": "Renomi la monujon", @@ -622,7 +623,7 @@ "DOWNLOAD_REVOKE_HELP": "Disponi dosieron pri nuligo estas grave, ekzemple kaze de perdo de viaj identigiloj. Äœi ebligas al vi <b>elirigi tiun konton el la reto de fido</b>, tiel ke Äi refariÄu simpla monujo.", "GENERATE_KEYFILE": "Krei mian dosieron pri Ålosilaro...", "GENERATE_KEYFILE_HELP": "Kreas dosieron, kiu ebligas al vi aÅtentiÄi sen tajpi viajn identigilojn.<br/><b>Atenton:</b> tiu dosiero entenos vian konto-Ålosilaron (publikan kaj sekretan Ålosilojn); do tre gravas meti Äin en sekuran lokon!", - "KEYFILE_FILENAME": "Ålosilaro-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-Ålosilaro-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Transformi en membro-konton...", "MEMBERSHIP_IN_HELP": "Ebligas <b>transformi</b> simplan monujo-konton <b>en membro-konton</b>, sendante aliÄo-peton. Utilas nur se vi ne havas jam alian membro-konton.", "SEND_IDENTITY": "Publikigi sian identecon...", @@ -658,9 +659,10 @@ "REVOCATION_WITH_FILE_HELP": "Por <b>definitive nuligi</b> membro-konton, bonvolu glitigi en la ĉi-suban zonon vian dosieron pri nuligo, aÅ alklaki la zonon por serĉadi dosieron.", "REVOCATION_WALLET": "Nuligi tiun ĉi konton tuj", "REVOCATION_WALLET_HELP": "Peti la nuligon de via identeco estigas la <b>eliradon el la reto de fido</b> (definitivan por la pseÅdonimo kaj la publika Ålosilo kunligitaj). La konto ne plu povos produkti Universalan Dividendon.<br/>Vi tamen daÅre povos konektiÄi al Äi, kiel al simpla monujo.", - "REVOCATION_FILENAME": "nuligo-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-nuligo-{{uid}}-{{pubkey}}.txt", "SAVE_ID": "Konservi miajn identigilojn...", "SAVE_ID_HELP": "Kreado de konserv-dosiero, por <b>retrovi vian pasvorton</b> (kaj la sekretan identigilon) <b>kaze de forgeso</b>. La dosiero estas <b>sekurigita</b> (ĉifrita) dank'al personaj demandoj.", + "SAVE_ID_FILENAME": "{{currency}}-ensalutigiloj-{{pubkey}}.txt", "STRONG_LEVEL": "Forta <span class=\"hidden-xs \">(6 demandoj minimume)</span>", "TITLE": "Konto kaj sekureco", "KEYFILE": { @@ -794,6 +796,7 @@ "GET_BLOCK_FAILED": "Malsukceso por ricevi la blokon.", "INVALID_BLOCK_HASH": "Bloko ne trovita (haketo malsama)", "DOWNLOAD_REVOCATION_FAILED": "Malsukceso por elÅuti la dosieron pri nuligo.", + "DOWNLOAD_SAVE_ID_FAILED": "Malsukcesis elÅuti la dosieron por konservi la ensalutigilojn.", "REVOCATION_FAILED": "Malsukceso pri nuligo.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Sekreta identigilo aÅ pasvorto malÄusta.", "RECOVER_ID_FAILED": "Malsukceso por ricevi la identigilojn", @@ -818,7 +821,8 @@ "INVALID_FILE_FORMAT": "Strukturo de dosiero nevalida.", "SAME_TX_RECIPIENT": "La adresito devas malsami ol la sendanto.", "SELF_CERTIFICATION": "Vi ne povas certigi vian propran identecon.", - "TX_SANDBOX_FULL": "La nodo Duniter uzata de Cesium ne plu povas prilabori novajn elspezojn, ĉar Äia atendovico estas plena.<br/><br/>Bonvolu provi denove poste aÅ ÅanÄi la nodon (en la <b>Agordoj</b>)." + "TX_SANDBOX_FULL": "La nodo Duniter uzata de Cesium ne plu povas prilabori novajn elspezojn, ĉar Äia atendovico estas plena.<br/><br/>Bonvolu provi denove poste aÅ ÅanÄi la nodon (en la <b>Agordoj</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Eraro dum la elÅuto de la konta raporto" }, "INFO": { "POPUP_TITLE": "Informo", @@ -835,7 +839,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "La <b>nuligo de tiu ĉi identeco</b> estis petita kaj atendas traktadon.", "FEATURES_NOT_IMPLEMENTED": "Tiu ĉi funkciaro ankoraÅ estas programiÄanta.<br/>Kial ne <b>kontribui al Cesium</b>, por ekhavi Äin pli rapide? ;)", "EMPTY_TX_HISTORY": "Neniu spezo elportota", - "LOADING_PENDING_TX": "Bonvolu pacienci...<br/><small>(Prenado de pendaj operacioj)</small>" + "LOADING_PENDING_TX": "Bonvolu pacienci...<br/><small>(Prenado de pendaj operacioj)</small>", + "FILE_DOWNLOADED": "Dosiero elÅutita" }, "CONFIRM": { "CAN_CONTINUE": "<b>Ĉu vi certas</b>, ke vi volas daÅrigi?", diff --git a/www/i18n/locale-es-ES.json b/www/i18n/locale-es-ES.json index f60c11f2e2b09e3b60b3734eef6de8ee1ead4004..99e6f21849882a7b7904d6f93b8dde0ef810c008 100644 --- a/www/i18n/locale-es-ES.json +++ b/www/i18n/locale-es-ES.json @@ -51,6 +51,7 @@ "LOADING": "Espere por favor...", "LOADING_WAIT": "Espere por favor...<br/><small>(Cesium está consultando al nodo Duniter)</small>", "SEARCHING": "Búsqueda en proceso…", + "DOWNLOADING_DOTS": "Descargando...", "FROM": "De", "TO": "A", "COPY": "Copiar", @@ -693,7 +694,7 @@ "NO_WALLET": "Sin monedero secundario", "BTN_DELETE": "Eliminar un monedero secundario…", "BTN_RENAME": "Renombrar el monedero", - "EXPORT_FILENAME": "monederos-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-monederos-{{pubkey}}.csv", "TOTAL_DOTS": "Total : ", "EDIT_POPOVER": { "TITLE": "Renombrar el monedero", @@ -727,7 +728,7 @@ "RECOVER_ID_SELECT_FILE": "Elija el <b>archivo para salvaguardar sus credenciales</b> a utilizar :", "GENERATE_KEYFILE": "Generar mi archivo de llaves…", "GENERATE_KEYFILE_HELP": "Genera un archivo que le permitirá atenticarse sin tener que introducir las credenciales.<br/><b>Cuidado:</b> este archivo contendrá su llave secreta; ¡Es muy importante conservarlo en un lugar seguro!", - "KEYFILE_FILENAME": "llavero-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-llavero-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Registrarse como miembro…", "MEMBERSHIP_IN_HELP": "Le permite <b>transformar</b> una cuenta de monedero simple <b>en una cuenta miembro</b>, enviando una petición de membresÃa. Solo si todavÃa no tiene una cuenta miembro.", "SEND_IDENTITY": "Publicar seudónimo/identidad…", @@ -759,16 +760,17 @@ "REVOCATION_WITH_FILE": "Revocar una identidad a partir de un fichero", "REVOCATION_WITH_FILE_DESCRIPTION": "Si ha perdido de forma permanente las credenciales de su cuenta miembro (o la seguridad de la cuenta se ve comprometida), puede usar <b>el archivo de revocación de la cuenta</b> para forzar la salida de la Red de Confianza.", "REVOCATION_WITH_FILE_HELP": "Para <b>revocar permanentemente</b> una cuenta miembro, arrastre el archivo de revocación en el cuadro siguiente o haga clic en el cuadro para seleccionar un archivo.", - "REVOCATION_FILENAME": "revocacion-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revocacion-{{uid}}-{{pubkey}}.txt", "REVOCATION_WALLET": "Revocar esta identidad", "SAVE_ID": "Guardar mis credenciales", "STRONG_LEVEL": "Alto <span class=\"hidden-xs \">(6 preguntas min.)</span>", "TITLE": "Cuenta y seguridad", "RECOVER_ID_HELP": "Si dispone de un <b>archivo de recuperación de sus credenciales</b>, las puede reobtener respondiendo correctamente a las preguntas personales elegidas en su momento.", "REVOCATION_WALLET_HELP": "Pedir la revocación de vuestra identidad comporta la <b>salida de la red de confianza</b> (definitiva para el seudónimo y la llave pública asociada). La cuenta no producirá ya más el Dividendo Universal.<br/>Podrá seguir usándola como monedero simple.", - "SAVE_ID_HELP": "Creación de un archivo de recuperación, para <b>reobtener su contraseña</b> (y frase secreta) en caso de olvido. El archivo se <b>cifra</b> con ayuda de las preguntas personales elegidas." + "SAVE_ID_HELP": "Creación de un archivo de recuperación, para <b>reobtener su contraseña</b> (y frase secreta) en caso de olvido. El archivo se <b>cifra</b> con ayuda de las preguntas personales elegidas.", + "SAVE_ID_FILENAME": "{{currency}}-credenciales-{{pubkey}}.txt" }, - "FILE_NAME": "{{currency}}_HistorialDeCuenta_{{pubkey|formatPubkey}}_{{currentTime|formatDateForFile}}.csv", + "FILE_NAME": "{{currency}}-HistorialDeCuenta-{{pubkey}}-{{currentTime|formatDateForFile}}.csv", "HEADERS": { "TIME": "Fecha", "AMOUNT": "Cantidad", @@ -889,6 +891,7 @@ "GET_BLOCK_FAILED": "Error en la recuperación del bloque", "INVALID_BLOCK_HASH": "Bloque no encontrado (hash diferente)", "DOWNLOAD_REVOCATION_FAILED": "Debe seleccionar un fichero de texto", + "DOWNLOAD_SAVE_ID_FAILED": "Error al descargar el archivo de copia de seguridad de las credenciales.", "REVOCATION_FAILED": "Error en la revocación.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Frase secreta o contraseña incorrectos", "RECOVER_ID_FAILED": "Error en la recuperación de las credenciales", @@ -903,7 +906,8 @@ "INVALID_FILE_FORMAT": "Formato de archivo inválido.", "SAME_TX_RECIPIENT": "El destinatario debe ser diferente del emisor.", "SELF_CERTIFICATION": "No puedes certificar tu propia identidad.", - "TX_SANDBOX_FULL": "El nodo Duniter utilizado por Cesium ya no puede procesar nuevas transferencias, ya que su cola está llena.<br/><br/>Por favor, inténtelo de nuevo más tarde o cambie de nodo (en las <b>Configuraciones</b>)." + "TX_SANDBOX_FULL": "El nodo Duniter utilizado por Cesium ya no puede procesar nuevas transferencias, ya que su cola está llena.<br/><br/>Por favor, inténtelo de nuevo más tarde o cambie de nodo (en las <b>Configuraciones</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Error al descargar el estado de cuenta" }, "INFO": { "POPUP_TITLE": "Información", @@ -920,7 +924,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "La <b>revocación de esta identidad</b> fue solicitada y está en espera de ser procesada.", "FEATURES_NOT_IMPLEMENTED": "Esta funcionalidad todavÃa está en proceso de desarrollo.<br/><br/>¿Por qué no <b>contribuir a Cesium</b>, para obtenerla más rápido? ;)", "EMPTY_TX_HISTORY": "Ninguna operación a exportar", - "LOADING_PENDING_TX": "Espere por favor...<br/><small>(Recuperando operaciones pendientes)</small>" + "LOADING_PENDING_TX": "Espere por favor...<br/><small>(Recuperando operaciones pendientes)</small>", + "FILE_DOWNLOADED": "Archivo descargado" }, "CONFIRM": { "CAN_CONTINUE": "¿Desea continuar?", diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index 121321c68376a0ba38717ed03e27e82cd2bd2195..71016cc67c57c226ea302f516b9fc2d43b891843 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -51,6 +51,7 @@ "LOADING": "Veuillez patienter...", "LOADING_WAIT": "Veuillez patienter...<br/><small>(Cesium interroge le nÅ“ud Duniter)</small>", "SEARCHING": "Recherche en cours...", + "DOWNLOADING_DOTS": "Téléchargement...", "FROM": "De", "TO": "À", "COPY": "Copier", @@ -603,7 +604,7 @@ "NO_WALLET": "Aucun portefeuille secondaire", "BTN_DELETE": "Retirer un portefeuille secondaire...", "BTN_RENAME": "Renommer le portefeuille", - "EXPORT_FILENAME": "mes_portefeuilles-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-mes_portefeuilles-{{pubkey}}.csv", "TOTAL_DOTS": "Total : ", "EDIT_POPOVER": { "TITLE": "Renommer le portefeuille", @@ -625,7 +626,7 @@ "DOWNLOAD_REVOKE_HELP": "Disposer d'un fichier de révocation est important, par exemple en cas de perte de vos identifiants. Il vous permet de <b>sortir ce compte de la toile de confiance</b>, en redevenant ainsi un simple portefeuille. Ne fonctionne pas sur smartphone.", "GENERATE_KEYFILE": "Générer mon fichier de trousseau...", "GENERATE_KEYFILE_HELP": "Génère un fichier permettant de vous authentifier sans saisir vos identifiants.<br/><b>Attention :</b> ce fichier contiendra votre trousseau de compte (clefs publique et secrète) ; il est donc très important de le mettre en lieu sûr !", - "KEYFILE_FILENAME": "trousseau-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-trousseau-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Transformer en compte membre...", "MEMBERSHIP_IN_HELP": "Permet de <b>transformer</b> un compte simple portefeuille <b>en compte membre</b>, en envoyant une demande d'adhésion. Utile uniquement si vous n'avez pas déjà un autre compte membre.", "SEND_IDENTITY": "Publier son identité...", @@ -661,9 +662,10 @@ "REVOCATION_WITH_FILE_HELP": "Pour <b>révoquer définitivement</b> un compte membre, veuillez glisser dans la zone ci-dessous votre fichier de révocation, ou bien cliquer dans la zone pour rechercher un fichier.", "REVOCATION_WALLET": "Révoquer immédiatement ce compte", "REVOCATION_WALLET_HELP": "Demander la révocation de votre identité entraîne la <b>sortie de la toile de confiance</b> (définitive pour le pseudonyme et la clé publique associés). Le compte ne pourra plus produire de Dividende Universel.<br/>Vous pourrez toutefois encore vous y connecter, comme à un simple portefeuille.", - "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revocation-{{uid}}-{{pubkey}}.txt", "SAVE_ID": "Sauvegarder mes identifiants...", "SAVE_ID_HELP": "Création d'un fichier de sauvegarde, pour <b>retrouver votre mot de passe</b> (et l'identifiant secret) <b>en cas de d'oubli</b>. Le fichier est <b>sécurisé</b> (chiffré) à l'aide de questions personnelles.", + "SAVE_ID_FILENAME": "{{currency}}-identifiants-{{pubkey}}.txt", "STRONG_LEVEL": "Fort <span class=\"hidden-xs \">(6 questions minimum)</span>", "TITLE": "Compte et sécurité", "KEYFILE": { @@ -684,7 +686,7 @@ } } }, - "FILE_NAME": "{{currency}} - Relevé du compte {{pubkey|formatPubkey}} au {{currentTime|formatDateForFile}}.csv", + "FILE_NAME": "{{currency}}-historique-{{pubkey}}-{{currentTime|formatDateForFile}}.csv", "HEADERS": { "TIME": "Date", "AMOUNT": "Montant", @@ -797,12 +799,13 @@ "GET_BLOCK_FAILED": "Échec de la récupération du bloc.", "INVALID_BLOCK_HASH": "Bloc non trouvé (hash différent).", "DOWNLOAD_REVOCATION_FAILED": "Échec du téléchargement du fichier de révocation.", + "DOWNLOAD_SAVE_ID_FAILED": "Échec du téléchargement du fichier de sauvegarde des identifiants.", "REVOCATION_FAILED": "Échec de la révocation.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Identifiant secret ou mot de passe incorrect.", "RECOVER_ID_FAILED": "Échec de la récupération des identifiants", "LOAD_FILE_FAILED" : "Échec du chargement du fichier", "NOT_VALID_REVOCATION_FILE": "Fichier de révocation non valide (mauvais format de fichier)", - "NOT_VALID_SAVE_ID_FILE": "Fichier de récupération non valide (mauvais format de fichier)", + "NOT_VALID_SAVE_ID_FILE": "Fichier de sauvegarde non valide (mauvais format de fichier)", "NOT_VALID_KEY_FILE": "Fichier de trousseau non valide (format non reconnu)", "EXISTING_ACCOUNT": "Vos identifiants correspondent à un compte déjà existant, dont la <a ng-click=\"showHelpModal('pubkey')\">clef publique</a> est :", "EXISTING_ACCOUNT_REQUEST": "Veuillez modifier vos identifiants afin qu'ils correspondent à un compte non utilisé.", @@ -821,7 +824,8 @@ "INVALID_FILE_FORMAT": "Format de fichier invalide.", "SAME_TX_RECIPIENT": "Le destinataire doit être différent de l'émetteur.", "SELF_CERTIFICATION": "Vous ne pouvez pas certifier votre propre identité.", - "TX_SANDBOX_FULL": "Le nÅ“ud Duniter utilisé par Cesium ne peut plus traité de nouveaux virements, car sa file d'attente est pleine.<br/><br/>Veuillez réessayer ultérieurement ou changer de nÅ“ud (dans les <b>Paramètres</b>)." + "TX_SANDBOX_FULL": "Le nÅ“ud Duniter utilisé par Cesium ne peut plus traité de nouveaux virements, car sa file d'attente est pleine.<br/><br/>Veuillez réessayer ultérieurement ou changer de nÅ“ud (dans les <b>Paramètres</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Erreur lors du téléchargement du relevé de compte" }, "INFO": { "POPUP_TITLE": "Information", @@ -838,7 +842,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "La <b>révocation de cette identité</b> a été demandée et est en attente de traitement.", "FEATURES_NOT_IMPLEMENTED": "Cette fonctionnalité est encore en cours de développement.<br/>Pourquoi ne pas <b>contribuer à Cesium</b>, pour l'obtenir plus rapidement ? ;)", "EMPTY_TX_HISTORY": "Aucune opération à exporter", - "LOADING_PENDING_TX": "Veuillez patienter...<br/><small>(Récupération des opérations en attente)</small>" + "LOADING_PENDING_TX": "Veuillez patienter...<br/><small>(Récupération des opérations en attente)</small>", + "FILE_DOWNLOADED": "Fichier téléchargé avec succès" }, "CONFIRM": { "CAN_CONTINUE": "<b>Êtes-vous sûr</b> de vouloir continuer ?", diff --git a/www/i18n/locale-it-IT.json b/www/i18n/locale-it-IT.json index b21269c1f87a5c18e511be6a7d4b35a009387a88..3b4edb919d381c24f1f61b1a6e870742738dcff4 100644 --- a/www/i18n/locale-it-IT.json +++ b/www/i18n/locale-it-IT.json @@ -51,6 +51,7 @@ "LOADING": "Caricando...", "LOADING_WAIT": "Caricando...<br/><small>(Cesium interroga il nodo nodo Duniter)</small>", "SEARCHING": "Cercando...", + "DOWNLOADING_DOTS": "Scaricamento...", "FROM": "Da", "TO": "A", "COPY": "Copiare", @@ -601,7 +602,7 @@ "NO_WALLET": "Nessun portafoglio secondario", "BTN_DELETE": "Rimuovi un portafoglio secondario ...", "BTN_RENAME": "Rinominare il portafoglio", - "EXPORT_FILENAME": "my_wallets-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-my_wallets-{{pubkey}}.csv", "TOTAL_DOTS": "Totale: ", "EDIT_POPOVER": { "TITLE": "Rinominare il portafoglio", @@ -623,7 +624,7 @@ "DOWNLOAD_REVOKE_HELP" : "Avere une file di revoca è necessario in caso di smarrimento delle tue credenziali. Ti permette <b> di rimuovere tuo conto dalla Rete di Fiducia</b>, per farlo tornare ad essere un semplice portafoglio.", "GENERATE_KEYFILE": "Genera il mio file portachiavi ...", "GENERATE_KEYFILE_HELP": "Genera un file che ti permette di autenticarti senza digitare le tue credenziali.<br/><b>Attenzione:</b> questo file contiene la tua chiave segreta: è perciò oltremodo importante salvarlo in un posto sicuro!", - "KEYFILE_FILENAME": "portachiavi-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-portachiavi-{{pubkey}}-{{format}}.dunikey", "MEMBERSHIP_IN": "Iscriviti come membro...", "MEMBERSHIP_IN_HELP": "Ti permette <b>convertire </b> un conto semplice <b>in un conto membro</b>, inviando una richiesta di adesione alla RdF. Utile solo se non sei già in possesso di un conto membro.", "SEND_IDENTITY": "Pubblica identità ...", @@ -659,9 +660,10 @@ "REVOCATION_WITH_FILE_HELP": "Se hai <b>definitivamente perso le tue credenziali (o se la sicurezza del tuo conto è compromessa), puoi usare <b>il file di revoca</b> del conto <b>per uscire dalla Rete di Fiducia</b>.", "REVOCATION_WALLET": "Revocare immediatamente questo conto", "REVOCATION_WALLET_HELP": "Richiedere la cancellazione dell'identità <b>revocherà la tua adesione alla Rete di Fiducia</ b> (definitivamente per lo pseudonimo e per la chiave pubblica associata). Il conto non potrà più produrre il Dividendo Universale.<br/>Nonostante ciò, puoi ancora usare il conto come semplice portafoglio.", - "REVOCATION_FILENAME": "revocation-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revocation-{{uid}}-{{pubkey}}.txt", "SAVE_ID": "Salvare le mie credenziali...", "SAVE_ID_HELP": "Creare un file di backup, per <b>recuperare la tua password</b> (e l'identificativo segreto) <b> in caso di smarrimento</b>. Il file è <b>sicuro</ b> (cifrato) utilizzando le domande personalizzate.", + "SAVE_ID_FILENAME": "{{currency}}-credenziali-{{pubkey}}.txt", "STRONG_LEVEL": "Alto <span class=\"hidden-xs \">(minimo di 6 domande)</span>", "TITLE": "Conto e sicurezza", "KEYFILE": { @@ -795,6 +797,7 @@ "GET_BLOCK_FAILED": "Impossibile caricare il blocco", "INVALID_BLOCK_HASH": "Blocco non trovato (hash errato)", "DOWNLOAD_REVOCATION_FAILED": "Errore avvenuto nel download del file di cancellazione d'identità .", + "DOWNLOAD_SAVE_ID_FAILED": "Scaricamento del file di backup delle credenziali non riuscito.", "REVOCATION_FAILED": "Errore avvenuto durante la richiesta di cancellazione dell'identità .", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Identificativo segreto o password sbagliati", "RECOVER_ID_FAILED": "Impossibile recuperare la password", @@ -819,7 +822,8 @@ "INVALID_FILE_FORMAT": "Formato file invalido.", "SAME_TX_RECIPIENT": "Il destinatario deve essere diverso dall'emittente.", "SELF_CERTIFICATION": "Non puoi certificare la tua stessa identità .", - "TX_SANDBOX_FULL": "Il nodo Duniter utilizzato dal Cesium non può più elaborare nuovi trasferimenti, perché la lista d'attesa è piena.<br/><br/>Riprova più tardi o scegli un'altro nodo Duniter (nelle <b>Impostazioni</b>)." + "TX_SANDBOX_FULL": "Il nodo Duniter utilizzato dal Cesium non può più elaborare nuovi trasferimenti, perché la lista d'attesa è piena.<br/><br/>Riprova più tardi o scegli un'altro nodo Duniter (nelle <b>Impostazioni</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Errore nel scaricare l'estratto conto" }, "INFO": { "POPUP_TITLE": "Informazioni", @@ -836,7 +840,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "Cancellazione dell'identità <b>inviata con successo</b>. In attesa di validazione.", "FEATURES_NOT_IMPLEMENTED": "Questa funzionalità non è ancora disponibile.<br/><br/>Vuoi contribuire per velocizzarne la disponibilità ? ;)", "EMPTY_TX_HISTORY": "Nessuna operazione da esportare", - "LOADING_PENDING_TX": "Caricando...<br/><small>(Recupero delle operazioni in sospeso)</small>" + "LOADING_PENDING_TX": "Caricando...<br/><small>(Recupero delle operazioni in sospeso)</small>", + "FILE_DOWNLOADED": "File scaricato" }, "CONFIRM": { "CAN_CONTINUE": "<b>Sei sicuro/a</b> di voler procedere?", diff --git a/www/i18n/locale-nl-NL.json b/www/i18n/locale-nl-NL.json index f04ac3aabe4c4e4b2f7ba906afdb27cecc17e58d..ab88116f227fe1c754170bae34e222a3ca089e6c 100644 --- a/www/i18n/locale-nl-NL.json +++ b/www/i18n/locale-nl-NL.json @@ -51,6 +51,7 @@ "LOADING": "Even geduld...", "LOADING_WAIT": "Even geduld...<br/><small>(Cesium vraagt de Duniter-node op)</small>", "SEARCHING": "Zoeken...", + "DOWNLOADING_DOTS": "Downloaden...", "FROM": "Van", "TO": "Aan", "COPY": "Kopieren", @@ -526,7 +527,10 @@ "REMINDER_TITLE": "Herinnering", "SHORT_LICENSE_REMINDER": "Je kunt de persoon eraan herinneren verschillende certificeringsparameters te certificeren:<br/><br/><ul><li> - Elk lid kan maximaal 100 andere identiteiten certificeren.</li><li> - De certificeringen worden met een interval van 5 dagen opgeslagen.</li><li> - Een nieuwe identiteit moet in minder dan 2 maanden minstens 5 certificeringen verzamelen.</li><li> - Een lid moet minstens eenmaal per jaar zijn lidmaatschap vernieuwen.</li><li> - Certificeringen hebben een levensduur van twee jaar.</li></ul>" }, - "FILE_NAME": "{{currency}} - Rekeningafschrift {{pubkey|formatPubkey}} {{currentTime|formatDateForFile}}.csv", + "SECURITY": { + "SAVE_ID_FILENAME": "{{currency}}-inloggegevens-{{pubkey}}.txt" + }, + "FILE_NAME": "{{currency}}-rekeningafschrift-{{pubkey}}-{{currentTime|formatDateForFile}}.csv", "HEADERS": { "TIME": "Datum", "AMOUNT": "Bedrag", @@ -579,6 +583,7 @@ "GET_CURRENCY_PARAMETER": "Could not get currency parameters.", "GET_CURRENCY_FAILED": "Could not load currency.", "SEND_TX_FAILED": "Could not send transaction.", + "DOWNLOAD_SAVE_ID_FAILED": "Downloaden van het back-upbestand voor inloggegevens mislukt.", "ALL_SOURCES_USED": "Please wait the next block computation (All transaction sources has been used).", "NOT_ENOUGH_SOURCES": "Not enough changes to send this amount in one time.<br/>Maximum amount: {{amount}} {{unit}}<sub>{{subUnit}}</sub>.", "ACCOUNT_CREATION_FAILED": "Error while creating your member account.", @@ -615,7 +620,8 @@ "EXISTING_ACCOUNT": "Je gegevens komen overeen met een bestaande rekening, met de <a ng-click=\"showHelpModal('pubkey')\">publieke sleutel</a>:", "EXISTING_ACCOUNT_REQUEST": "Gelieve je gegevens te wijzigen zodat ze met een niet gebruikte rekening overeenkomen.", "SELF_CERTIFICATION": "U kunt uw eigen identiteit niet certificeren.", - "TX_SANDBOX_FULL": "De Duniter-peer die door Cesium wordt gebruikt, kan geen nieuwe overschrijvingen meer verwerken, omdat de wachtrij vol is.<br/><br/>Probeer het later opnieuw of wijzig de peer (in de <b>Instellingen</b>)." + "TX_SANDBOX_FULL": "De Duniter-peer die door Cesium wordt gebruikt, kan geen nieuwe overschrijvingen meer verwerken, omdat de wachtrij vol is.<br/><br/>Probeer het later opnieuw of wijzig de peer (in de <b>Instellingen</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Fout bij het downloaden van het rekeningoverzicht" }, "INFO": { "POPUP_TITLE": "Informatie", @@ -630,7 +636,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "Intrekking <b>is succesvol verzonden</b>. Het wacht op verwerking.", "FEATURE_NOT_AVAILABLE_ON_DEMO": "Functionaliteit niet beschikbaar op deze demonstratiesite.<br/>Om <b>veiligheidsredenen</b> raden we u aan uw kopie van de software te <b>installeren</b>.<br/>Bezoek de website <a href='https://cesium.app'>www.cesium.app</a> voor hulp.", "EMPTY_TX_HISTORY": "Aucune operatie à exporteur", - "LOADING_PENDING_TX": "Even geduld...<br/><small>(Ophalen van hangende operaties)</small>" + "LOADING_PENDING_TX": "Even geduld...<br/><small>(Ophalen van hangende operaties)</small>", + "FILE_DOWNLOADED": "Bestand gedownload" }, "CONFIRM": { "CAN_CONTINUE": "<b>Weet je zeker</b> dat je door wil gaan?", diff --git a/www/i18n/locale-pt-PT.json b/www/i18n/locale-pt-PT.json index b7fc19e1230402dda1720a18f5d0fe751bdf50ba..c3c716576b27ecfd570973212f0b77164c6f35b8 100644 --- a/www/i18n/locale-pt-PT.json +++ b/www/i18n/locale-pt-PT.json @@ -51,6 +51,7 @@ "LOADING": "Aguarde por favor...", "LOADING_WAIT": "Aguarde por favor...<br/><small>(Cesium está a questionar o nó Duniter)</small>", "SEARCHING": "Procurando…", + "DOWNLOADING_DOTS": "Baixando...", "FROM": "De", "TO": "Para", "COPY": "Copiar", @@ -693,7 +694,7 @@ "NO_WALLET": "Sem carteira secundaria", "BTN_DELETE": "Eliminar una carteira secundaria…", "BTN_RENAME": "Renomear a carteira", - "EXPORT_FILENAME": "carteiras-{{pubkey|formatPubkey}}-{{currency}}.csv", + "EXPORT_FILENAME": "{{currency}}-carteiras-{{pubkey}}.csv", "TOTAL_DOTS": "Total : ", "EDIT_POPOVER": { "TITLE": "Renomear a carteira", @@ -727,7 +728,7 @@ "RECOVER_ID_SELECT_FILE": "Escolha o <b>arquivo para salvaguardar as suas credenciais</b> a utilizar :", "GENERATE_KEYFILE": "Gerar o meu arquivo de chaves…", "GENERATE_KEYFILE_HELP": "Gera um arquivo que permitirá autenticar se sem ter que introduzir as credenciais.<br/><b>Cuidado:</b> este arquivo conterá a sua chave secreta; É muito importante conservá-lo em lugar seguro!", - "KEYFILE_FILENAME": "llavero-{{pubkey|formatPubkey}}-{{currency}}-{{format}}.dunikey", + "KEYFILE_FILENAME": "{{currency}}-llavero-{{pubkey}}{{format}}.dunikey", "MEMBERSHIP_IN": "Registar como membro…", "MEMBERSHIP_IN_HELP": "Permite <b>transformar</b> uma conta de carteira simples <b>numa conta membro</b>, enviando um pedido de membro. Apenas se ainda não possui uma conta membro.", "SEND_IDENTITY": "Publicar identidade…", @@ -759,14 +760,15 @@ "REVOCATION_WITH_FILE": "Revogar uma identidade a partir de um ficheiro", "REVOCATION_WITH_FILE_DESCRIPTION": "Se perdeu de forma permanente as credenciais da sua conta de membro (ou a segurança da conta foi comprometida), pode usar <b>o arquivo de revogação da conta</b> para forçar a saÃda da Rede de Confiança.", "REVOCATION_WITH_FILE_HELP": "Para <b>revogar permanentemente</b> uma conta de membro, arraste o arquivo de revogação no quadro seguinte ou faça clique no quadro para selecionar um arquivo.", - "REVOCATION_FILENAME": "revogação-{{uid}}-{{pubkey|formatPubkey}}-{{currency}}.txt", + "REVOCATION_FILENAME": "{{currency}}-revogação-{{uid}}-{{pubkey}}.txt", "REVOCATION_WALLET": "Revogar esta identidade", "SAVE_ID": "Guardar as minhas credenciais", "STRONG_LEVEL": "Alto <span class=\"hidden-xs \">(6 perguntas min.)</span>", "TITLE": "Conta e segurança", "RECOVER_ID_HELP": "Se possui um <b>arquivo de recuperação das suas credenciais</b>, pode recuperá-las respondendo corretamente à s perguntas pessoais escolhidas por si.", "REVOCATION_WALLET_HELP": "Pedir a revogação da sua identidade acarreta a <b>saÃda da rede de confiança</b> (definitiva para o seu pseudónimo e a chave pública associada). A conta não produzirá mais o Dividendo Universal.<br/>Poderá continuar a usar carteira simples.", - "SAVE_ID_HELP": "Criação de um arquivo de recuperação, para <b>recuperar a sua contra senha</b> (e frase secreta) em caso de esquecimento. O arquivo <b>cifra-se</b> com a ajuda das perguntas pessoais escolhidas." + "SAVE_ID_HELP": "Criação de um arquivo de recuperação, para <b>recuperar a sua contra senha</b> (e frase secreta) em caso de esquecimento. O arquivo <b>cifra-se</b> com a ajuda das perguntas pessoais escolhidas.", + "SAVE_ID_FILENAME": "{{currency}}-credenciais-{{pubkey}}.txt" }, "FILE_NAME": "{{currency}}_HistoricoDaConta_{{pubkey|formatPubkey}}_{{currentTime|formatDateForFile}}.csv", "HEADERS": { @@ -889,6 +891,7 @@ "GET_BLOCK_FAILED": "Falha na recuperação do bloco", "INVALID_BLOCK_HASH": "Bloco não encontrado (hash diferente)", "DOWNLOAD_REVOCATION_FAILED": "Deve selecionar um ficheiro de texto", + "DOWNLOAD_SAVE_ID_FAILED": "Falha no download do arquivo de backup das credenciais.", "REVOCATION_FAILED": "Falha na revogação.", "SALT_OR_PASSWORD_NOT_CONFIRMED": "Frase secreta o contra senha incorretos", "RECOVER_ID_FAILED": "Falha na recuperação das credenciais", @@ -903,7 +906,8 @@ "INVALID_FILE_FORMAT": "Formato de arquivo inválido.", "SAME_TX_RECIPIENT": "O destinatário deve ser diferente do emissor.", "SELF_CERTIFICATION": "Não pode certificar a sua própria identidade.", - "TX_SANDBOX_FULL": "O nó Duniter utilizado por Cesium já não pode receber mais novas transferências, porque a fila de espera está cheia.<br/><br/>Por favor, tente mais tarde ou mude de nó (nas <b>Definições</b>)." + "TX_SANDBOX_FULL": "O nó Duniter utilizado por Cesium já não pode receber mais novas transferências, porque a fila de espera está cheia.<br/><br/>Por favor, tente mais tarde ou mude de nó (nas <b>Definições</b>).", + "DOWNLOAD_TX_HISTORY_FAILED": "Erro ao baixar o extrato da conta" }, "INFO": { "POPUP_TITLE": "Informação", @@ -920,7 +924,8 @@ "REVOCATION_SENT_WAITING_PROCESS": "A <b>revogação desta identidade</b> foi solicitada e aguarda ser processada.", "FEATURES_NOT_IMPLEMENTED": "Esta funcionalidade encontra-se em desenvolvimento.<br/><br/>Porque não <b>contribuir com Cesium</b>, para obtê-la mais rápido? ;)", "EMPTY_TX_HISTORY": "Nenhuma operação a exportar", - "LOADING_PENDING_TX": "Aguarde por favor...<br/><small>(A recuperar operações pendentes)</small>" + "LOADING_PENDING_TX": "Aguarde por favor...<br/><small>(A recuperar operações pendentes)</small>", + "FILE_DOWNLOADED": "Arquivo baixado" }, "CONFIRM": { "CAN_CONTINUE": "<b>Deseja</b> continuar?", diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index fd5f693ca669a0995b8f82be678a784c56a263a2..d5652d211c89059925c69cdb886b2b7dbebadac1 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -794,7 +794,19 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, options = options || {}; options.fromTime = options.fromTime || -1; // default: full history var pubkey = $scope.formData.pubkey; - csTx.downloadHistoryFile(pubkey, options); + + $scope.hideActionsPopover(); + + UIUtils.toast.show('COMMON.DOWNLOADING_DOTS'); + return csTx.downloadHistoryFile(pubkey, options) + .then(UIUtils.toast.hide) + .then(function() { + UIUtils.toast.show('INFO.FILE_DOWNLOADED', 1000); + }) + .catch(function(err){ + if (err && err === 'CANCELLED') return; + UIUtils.onError('ERROR.DOWNLOAD_TX_HISTORY_FAILED')(err); + }); }; // Updating wallet data @@ -979,6 +991,24 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, /* -- popover -- */ + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wallet/popover_tx_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; + var paddingIndent = 10; $scope.toUnlockUIArray = function(unlockTreeItem, leftPadding, operator) { @@ -1410,9 +1440,18 @@ function WalletSecurityModalController($scope, UIUtils, csConfig, csWallet, $tra return wallet.getCryptedId(record) .then(function(record){ - wallet.downloadSaveId(record); $scope.closeModal(); - }); + + return wallet.downloadSaveId(record) + .then(function() { + UIUtils.toast.show('INFO.FILE_DOWNLOADED', 1000); + }) + .catch(function(err){ + if (err && err === 'CANCELLED') return; + UIUtils.onError('ERROR.DOWNLOAD_SAVE_ID_FAILED')(err); + }); + }) + ; }) ; }; @@ -1445,15 +1484,15 @@ function WalletSecurityModalController($scope, UIUtils, csConfig, csWallet, $tra return wallet.downloadRevocation(); }) + .then(UIUtils.loading.hide) .then(function() { - UIUtils.loading.hide(); + UIUtils.toast.show('INFO.FILE_DOWNLOADED', 1000); }) .catch(function(err){ if (err && err === 'CANCELLED') return; UIUtils.onError('ERROR.DOWNLOAD_REVOCATION_FAILED')(err); - }) - ; + }); }; diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js index 5647e89ea42bfe68db45538cda5caa5e3786bead..efd55acc542700807c3e76bf26e52bf42e9c9980 100644 --- a/www/js/controllers/wot-controllers.js +++ b/www/js/controllers/wot-controllers.js @@ -1280,7 +1280,19 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo $scope.downloadHistoryFile = function(options) { options = options || {}; options.fromTime = options.fromTime || -1; // default: full history - csTx.downloadHistoryFile($scope.pubkey, options); + + UIUtils.loading.show(); + + UIUtils.toast.show('INFO.DOWNLOADING_DOTS'); + return csTx.downloadHistoryFile($scope.pubkey, options) + .then(UIUtils.toast.hide) + .then(function() { + UIUtils.toast.show('INFO.FILE_DOWNLOADED', 1000); + }) + .catch(function(err){ + if (err && err === 'CANCELLED') return; + UIUtils.onError('ERROR.DOWNLOAD_TX_HISTORY_FAILED')(err); + }); }; $scope.showMoreTx = function(fromTime) { @@ -1309,6 +1321,25 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo }); }; + /* -- popover -- */ + + $scope.showActionsPopover = function(event) { + UIUtils.popover.show(event, { + templateUrl: 'templates/wot/popover_tx_actions.html', + scope: $scope, + autoremove: true, + afterShow: function(popover) { + $scope.actionsPopover = popover; + } + }); + }; + + $scope.hideActionsPopover = function() { + if ($scope.actionsPopover) { + $scope.actionsPopover.hide(); + $scope.actionsPopover = null; + } + }; } diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js index 88e981c7b3824fba4355ff4df44c529fd9bfd19d..5ec007678dfd86ee279e65f20c849d7f2cea742a 100644 --- a/www/js/services/bma-services.js +++ b/www/js/services/bma-services.js @@ -233,12 +233,10 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium. } throw err; }); - } + }; return wrappedRequest; } - - function incrementGetUsageCount(path, limitRequestCount) { limitRequestCount = limitRequestCount || constants.LIMIT_REQUEST_COUNT; // Wait if too many requests on this path diff --git a/www/js/services/device-services.js b/www/js/services/device-services.js index cf88f8f8937c055f314f7db513583a0fab47d8d1..9be7c7821907bcb22341919b014bf280c421b0b1 100644 --- a/www/js/services/device-services.js +++ b/www/js/services/device-services.js @@ -2,241 +2,382 @@ var App; angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.settings.services']) - .factory('Device', function($rootScope, $translate, $ionicPopup, $q, Api, csConfig, - // removeIf(no-device) - $cordovaClipboard, $cordovaBarcodeScanner, $cordovaCamera, $cordovaNetwork, - // endRemoveIf(no-device) - ionicReady) { - 'ngInject'; - - var - CONST = { - MAX_HEIGHT: 400, - MAX_WIDTH: 400 - }, - api = new Api(this, "Device"), - exports = { - // workaround to quickly no is device or not (even before the ready() event) - enable: true - }, - cache = {}, - started = false, - startPromise, - listeners = { - online: undefined, - offline: undefined - } - ; + .factory('Device', function ($rootScope, $translate, $timeout, $ionicPopup, $q, Api, csConfig, + // removeIf(no-device) + $cordovaClipboard, $cordovaBarcodeScanner, $cordovaCamera, $cordovaNetwork, + // endRemoveIf(no-device) + ionicReady, UIUtils, Blob, FileSaver) { + 'ngInject'; + + var + CONST = { + MAX_HEIGHT: 400, + MAX_WIDTH: 400, + UTF8_BOM_CHAR: new Uint8Array([0xEF, 0xBB, 0xBF]) // UTF-8 BOM + }, + api = new Api(this, "Device"), + exports = { + // workaround to quickly no is device or not (even before the ready() event) + enable: true + }, + cache = {}, + started = false, + startPromise, + listeners = { + online: undefined, + offline: undefined + } + ; - // removeIf(device) - // workaround to quickly no is device or not (even before the ready() event) - exports.enable = false; - // endRemoveIf(device) + // removeIf(device) + // workaround to quickly no is device or not (even before the ready() event) + exports.enable = false; - function getPicture(options) { - if (!exports.camera.enable) { - return $q.reject("Camera not enable. Please call 'ionicReady()' once before use (e.g in app.js)."); - } + // endRemoveIf(device) - // Options is the sourceType by default - if (options && (typeof options === "string")) { - options = { - sourceType: options - }; - } - options = options || {}; - - // Make sure a source type has been given (if not, ask user) - if (angular.isUndefined(options.sourceType)) { - return $translate(['SYSTEM.PICTURE_CHOOSE_TYPE', 'SYSTEM.BTN_PICTURE_GALLERY', 'SYSTEM.BTN_PICTURE_CAMERA']) - .then(function(translations){ - return $ionicPopup.show({ - title: translations['SYSTEM.PICTURE_CHOOSE_TYPE'], - buttons: [ - { - text: translations['SYSTEM.BTN_PICTURE_GALLERY'], - type: 'button', - onTap: function(e) { - return navigator.camera.PictureSourceType.PHOTOLIBRARY; - } - }, - { - text: translations['SYSTEM.BTN_PICTURE_CAMERA'], - type: 'button button-positive', - onTap: function(e) { - return navigator.camera.PictureSourceType.CAMERA; - } + function getPicture(options) { + if (!exports.camera.enable) { + return $q.reject("Camera not enable. Please call 'ionicReady()' once before use (e.g in app.js)."); + } + + // Options is the sourceType by default + if (options && (typeof options === "string")) { + options = { + sourceType: options + }; + } + options = options || {}; + + // Make sure a source type has been given (if not, ask user) + if (angular.isUndefined(options.sourceType)) { + return $translate(['SYSTEM.PICTURE_CHOOSE_TYPE', 'SYSTEM.BTN_PICTURE_GALLERY', 'SYSTEM.BTN_PICTURE_CAMERA']) + .then(function (translations) { + return $ionicPopup.show({ + title: translations['SYSTEM.PICTURE_CHOOSE_TYPE'], + buttons: [ + { + text: translations['SYSTEM.BTN_PICTURE_GALLERY'], + type: 'button', + onTap: function (e) { + return navigator.camera.PictureSourceType.PHOTOLIBRARY; + } + }, + { + text: translations['SYSTEM.BTN_PICTURE_CAMERA'], + type: 'button button-positive', + onTap: function (e) { + return navigator.camera.PictureSourceType.CAMERA; } - ] - }) - .then(function(sourceType){ + } + ] + }) + .then(function (sourceType) { console.info('[camera] User select sourceType:' + sourceType); options.sourceType = sourceType; return exports.camera.getPicture(options); }); - }); - } + }); + } - options.quality = options.quality || 50; - options.destinationType = options.destinationType || navigator.camera.DestinationType.DATA_URL; - options.encodingType = options.encodingType || navigator.camera.EncodingType.PNG; - options.targetWidth = options.targetWidth || CONST.MAX_WIDTH; - options.targetHeight = options.targetHeight || CONST.MAX_HEIGHT; - return $cordovaCamera.getPicture(options); + options.quality = options.quality || 50; + options.destinationType = options.destinationType || navigator.camera.DestinationType.DATA_URL; + options.encodingType = options.encodingType || navigator.camera.EncodingType.PNG; + options.targetWidth = options.targetWidth || CONST.MAX_WIDTH; + options.targetHeight = options.targetHeight || CONST.MAX_HEIGHT; + return $cordovaCamera.getPicture(options); + } + + function scan(n) { + if (!exports.enable) { + return $q.reject("Barcode scanner not enable. Please call 'ionicReady()' once before use (e.g in app.js)."); } + var deferred = $q.defer(); + cordova.plugins.barcodeScanner.scan( + function (result) { + if (!result.cancelled) { + console.debug('[device] barcode scanner scan: ' + result.text); + deferred.resolve(result.text); // make sure to convert into String + } else { + console.debug('[device] barcode scanner scan: CANCELLED'); + deferred.resolve(); + } + }, + function (err) { + console.error('[device] Error while using barcode scanner: ' + err); + deferred.reject(err); + }, + n); + return deferred.promise; + } - function scan(n) { - if (!exports.enable) { - return $q.reject("Barcode scanner not enable. Please call 'ionicReady()' once before use (e.g in app.js)."); - } - var deferred = $q.defer(); - cordova.plugins.barcodeScanner.scan( - function(result) { - if (!result.cancelled) { - console.debug('[device] barcode scanner scan: ' + result.text); - deferred.resolve(result.text); // make sure to convert into String - } - else { - console.debug('[device] barcode scanner scan: CANCELLED'); - deferred.resolve(); - } - }, - function(err) { - console.error('[device] Error while using barcode scanner: ' + err); - deferred.reject(err); - }, - n); - return deferred.promise; + function copy(text, callback) { + if (!exports.enable) { + return $q.reject('Device disabled'); + } + var deferred = $q.defer(); + $cordovaClipboard + .copy(text) + .then(function () { + // success + if (callback) { + callback(); + } + deferred.resolve(); + }, function () { + // error + deferred.reject({message: 'ERROR.COPY_CLIPBOARD'}); + }); + return deferred.promise; + } + + exports.clipboard = {copy: copy}; + exports.camera = { + getPicture: getPicture, + scan: function (n) { + console.warn('Deprecated use of Device.camera.scan(). Use Device.barcode.scan() instead'); + return scan(n); } + }; + exports.barcode = { + enable: false, + scan: scan + }; + exports.keyboard = { + enable: false, + close: function () { + if (!exports.keyboard.enable) return; + cordova.plugins.Keyboard.close(); + } + }; + exports.network = { + connectionType: function () { + if (!exports.network.enable) return 'unknown'; + try { + return navigator.connection.type || 'unknown'; + } catch (err) { + console.error('[device] Cannot get connection type: ' + (err && err.message || err), err); + return 'unknown'; + } + }, + isOnline: function () { + try { + return navigator.connection.type !== Connection.NONE; + } catch (err) { + console.error('[device] Cannot check if online: ' + (err && err.message || err), err); + return true; + } + }, + isOffline: function () { + try { + return navigator.connection.type === Connection.NONE; + } catch (err) { + console.error('[device] Cannot check if offline: ' + (err && err.message || err), err); + return true; + } + return false; + }, + timeout: function (defaultTimeout) { + defaultTimeout = defaultTimeout || csConfig.timeout; + var timeout; + try { + var connectionType = exports.network.connectionType(); + + // If desktop: use ethernet as default connection type + if (connectionType === 'unknown' && exports.isDesktop()) { + connectionType = 'ethernet'; + } - function copy(text, callback) { - if (!exports.enable) { - return $q.reject('Device disabled'); + switch (connectionType) { + case 'ethernet': + timeout = 1000; // 1 s + break; + case 'wifi': + timeout = 2000; + break; + case 'cell': // (e.g. iOS) + case 'cell_5g': + timeout = 3000; + break; + case 'cell_4g': + timeout = 5000; + break; + case 'cell_3g': + timeout = 10000; // 10s + break; + case 'cell_2g': + timeout = 40000; // 40s + break; + case 'none': + timeout = 0; + break; + case 'unknown': + default: + timeout = defaultTimeout; + break; + } + console.debug('[device] Using timeout: {1}ms (connection type: \'{0}\')'.format(connectionType, timeout)); + + return timeout; + } catch (err) { + console.error('[device] Error while trying to get connection type: ' + (err && err.message || err)); + return defaultTimeout; } - var deferred = $q.defer(); - $cordovaClipboard - .copy(text) - .then(function () { - // success - if (callback) { - callback(); - } - deferred.resolve(); - }, function () { - // error - deferred.reject({message: 'ERROR.COPY_CLIPBOARD'}); + } + }; + + exports.downloader = { + enable: false, + download: function(request) { + return $q(function(resolve, reject) { + if (!exports.downloader.enable) return reject("Cordova Downloaded plugin is not enable!"); + if (!request) return reject("Missing request argument"); + + console.debug('[device] Downloading file from request: ' + JSON.stringify(request)); + + cordova.plugins.Downloader.download(request, function(location) { + console.info("[device] Successfully download file at '{0}'".format(location)); + resolve(location); + }, function(err) { + console.error('[device] Cannot download, from given request', request); + reject(err); }); - return deferred.promise; + }); } + }; + exports.file = { + enable: false, + started: false, + ready: function() { + if (exports.file.started) return $q.when(); + return $q(function(resolve) { + window.addEventListener('filePluginIsReady', function() { + + console.debug('[device] [file] Plugin is ready'); + + // DEBUG: dump available directory + Object.keys(cordova.file).forEach(function(key) { + console.debug('[device] [file] - cordova.file.{0}: '.format(key) + cordova.file[key]); + }); - exports.clipboard = {copy: copy}; - exports.camera = { - getPicture : getPicture, - scan: function(n){ - console.warn('Deprecated use of Device.camera.scan(). Use Device.barcode.scan() instead'); - return scan(n); - } - }; - exports.barcode = { - enable : false, - scan: scan - }; - exports.keyboard = { - enable: false, - close: function() { - if (!exports.keyboard.enable) return; - cordova.plugins.Keyboard.close(); + exports.file.started = true; + resolve(); + }, false); + }); + }, + save: function(content, options) { + + var filename = options && options.filename || 'export.txt'; + var charset = (options && options.encoding || 'utf-8').toLowerCase(); + var type = options && options.type || 'text/plain'; + var withBOM = charset === 'utf-8' && (!options || options.withBOM !== false); + var showToast = options && options.showToast || false; + + // Use Cordova file plugin + if (exports.file.enable) { + + var directory = options && options.directory || (exports.isAndroid() ? + cordova.file.externalRootDirectory + 'Download' : + cordova.file.documentsDirectory); + var fullPath = (directory.endsWith('/') ? directory : (directory + '/')) + filename; + console.debug("[device] [file] Saving file '{0}' (using Cordova)...".format(fullPath)); + + return $q(function (resolve, reject) { + + var onError = function (err) { + console.error("[device] [file] Error while creating file '{0}': {1}".format(fullPath, err ? JSON.stringify(err): 'Unknown error')); + reject(err || 'Cannot create file ' + filename); + }; + + window.resolveLocalFileSystemURL(directory, function (directoryEntry) { + directoryEntry.getFile(filename, {create: true}, function (fileEntry) { + + fileEntry.createWriter(function (fileWriter) { + fileWriter.onwriteend = function () { + console.debug("[device] [file] Successfully save file '{0}'".format(fullPath)); + resolve(fullPath); + }; + fileWriter.onerror = function (e) { + onError(); + }; + var blob = new Blob( + // Add UTF-8 BOM character (if enable) + withBOM ? [CONST.UTF8_BOM_CHAR, content] : [content], + {type: "{0};charset={1};".format(type, charset)}); + fileWriter.write(blob); + }, onError); + }, onError); + }, onError); + }) + .then(function (uri) { + if (showToast) { + UIUtils.toast.show('INFO.FILE_DOWNLOADED', 1000); + } + return uri; + }); } - }; - exports.network = { - connectionType: function() { - if (!exports.network.enable) return 'unknown'; - try { - return navigator.connection.type || 'unknown'; - } - catch(err) { - console.error('[device] Cannot get connection type: ' + (err && err.message || err), err); - return 'unknown'; - } - }, - isOnline: function() { - try { - return navigator.connection.type !== Connection.NONE; - } - catch(err) { - console.error('[device] Cannot check if online: ' + (err && err.message || err), err); - return true; - } - }, - isOffline: function() { - try { - return navigator.connection.type === Connection.NONE; + + // Fallback to browser download + else { + console.debug("[device] [file] Saving file '{0}'...".format(filename)); + + var blob = new Blob( + // Add UTF-8 BOM character (if enable) + withBOM ? [CONST.UTF8_BOM_CHAR, content] : [content], + {type: "{0};charset={1};".format(type, charset)}); + + return FileSaver.saveAs(blob, filename, true /*disable auto BOM*/); + } + }, + + uri: { + getFilename: function (uri) { + if (!uri) return uri; + var filename = uri.trim(); + + // Get last part (or all string, if no '/') + var lastSlashIndex = filename.lastIndexOf('/'); + if (lastSlashIndex !== -1 && lastSlashIndex !== uri.length - 1) { + filename = filename.substring(lastSlashIndex + 1); } - catch(err) { - console.error('[device] Cannot check if offline: ' + (err && err.message || err), err); - return true; + + // Remove query params + var queryParamIndex = filename.indexOf('?'); + if (queryParamIndex !== -1) { + filename = filename.substring(0, queryParamIndex); } - return false; + + return filename; }, - timeout: function(defaultTimeout) { - defaultTimeout = defaultTimeout || csConfig.timeout; - var timeout; - try { - var connectionType = exports.network.connectionType(); - - // If desktop: use ethernet as default connection type - if (connectionType === 'unknown' && exports.isDesktop()) { - connectionType = 'ethernet'; - } - switch (connectionType) { - case 'ethernet': - timeout = 1000; // 1 s - break; - case 'wifi': - timeout = 2000; - break; - case 'cell': // (e.g. iOS) - case 'cell_5g': - timeout = 3000; - break; - case 'cell_4g': - timeout = 5000; - break; - case 'cell_3g': - timeout = 10000; // 10s - break; - case 'cell_2g': - timeout = 40000; // 40s - break; - case 'none': - timeout = 0; - break; - case 'unknown': - default: - timeout = defaultTimeout; - break; - } - console.debug('[device] Using timeout: {1}ms (connection type: \'{0}\')'.format(connectionType, timeout)); + getDirectory: function (uri) { + if (!uri) return uri; + var directory = uri.trim(); - return timeout; - } catch(err) { - console.error('[device] Error while trying to get connection type: ' + (err && err.message || err)); - return defaultTimeout; + // Already a folder + if (directory.endsWith('/')) return directory; + + // Get part before the last slash + var lastSlashIndex = directory.lastIndexOf('/'); + if (lastSlashIndex !== -1 && lastSlashIndex !== directory.length - 1) { + return directory.substring(0, lastSlashIndex+1); } + + return directory; } - }; - - function getLastIntent() { - var deferred = $q.defer(); - window.plugins.launchmyapp.getLastIntent( - deferred.resolve, - deferred.reject); - return deferred.promise; } + }; + + function getLastIntent() { + var deferred = $q.defer(); + window.plugins.launchmyapp.getLastIntent( + deferred.resolve, + deferred.reject); + return deferred.promise; + } + // WARN: Need by cordova-plugin-customurlscheme - window.handleOpenURL = function(intent) { + window.handleOpenURL = function (intent) { if (intent) { console.info('[device] Received new intent: ', intent); cache.lastIntent = intent; // Remember, for last() @@ -245,178 +386,189 @@ angular.module('cesium.device.services', ['cesium.utils.services', 'cesium.setti }; exports.intent = { - enable: false, - last: function() { - return $q.when(cache.lastIntent); - }, - clear: function() { - cache.lastIntent = undefined; - } - }; - - // Numerical keyboard - fix #30 - exports.keyboard.digit = { - settings: { - bindModel: function(modelScope, modelPath, settings) { - settings = settings || {}; - modelScope = modelScope || $rootScope; - var getModelValue = function() { - return (modelPath||'').split('.').reduce(function(res, path) { - return res ? res[path] : undefined; - }, modelScope); - }; - var setModelValue = function(value) { - var paths = (modelPath||'').split('.'); - var property = paths.length && paths[paths.length-1]; - paths.reduce(function(res, path) { - if (path == property) { - res[property] = value; - return; - } - return res[path]; - }, modelScope); - }; + enable: false, + last: function () { + return $q.when(cache.lastIntent); + }, + clear: function () { + cache.lastIntent = undefined; + } + }; - settings.animation = settings.animation || 'pop'; - settings.action = settings.action || function(number) { - setModelValue((getModelValue() ||'') + number); - }; - if (settings.decimal) { - settings.decimalSeparator = settings.decimalSeparator || '.'; - settings.leftButton = { - html: '<span>.</span>', - action: function () { - var text = getModelValue() || ''; - // only one '.' allowed - if (text.indexOf(settings.decimalSeparator) >= 0) return; - // Auto add zero when started with '.' - if (!text.trim().length) { - text = '0'; - } - setModelValue(text + settings.decimalSeparator); - } - }; - } - settings.rightButton = settings.rightButton || { - html: '<i class="icon ion-backspace-outline"></i>', - action: function() { - var text = getModelValue(); - if (text && text.length) { - text = text.slice(0, -1); - setModelValue(text); - } + // Numerical keyboard - fix #30 + exports.keyboard.digit = { + settings: { + bindModel: function (modelScope, modelPath, settings) { + settings = settings || {}; + modelScope = modelScope || $rootScope; + var getModelValue = function () { + return (modelPath || '').split('.').reduce(function (res, path) { + return res ? res[path] : undefined; + }, modelScope); + }; + var setModelValue = function (value) { + var paths = (modelPath || '').split('.'); + var property = paths.length && paths[paths.length - 1]; + paths.reduce(function (res, path) { + if (path == property) { + res[property] = value; + return; + } + return res[path]; + }, modelScope); + }; + + settings.animation = settings.animation || 'pop'; + settings.action = settings.action || function (number) { + setModelValue((getModelValue() || '') + number); + }; + if (settings.decimal) { + settings.decimalSeparator = settings.decimalSeparator || '.'; + settings.leftButton = { + html: '<span>.</span>', + action: function () { + var text = getModelValue() || ''; + // only one '.' allowed + if (text.indexOf(settings.decimalSeparator) >= 0) return; + // Auto add zero when started with '.' + if (!text.trim().length) { + text = '0'; } - }; - return settings; - } - } - }; - - exports.isOSX = function() { - return !!navigator.userAgent.match(/Macintosh/i) || ionic.Platform.is("osx"); - }; - - exports.isIOS = function() { - return !!navigator.userAgent.match(/iPhone | iPad | iPod/i) || (!!navigator.userAgent.match(/Mobile/i) && !!navigator.userAgent.match(/Macintosh/i)) || ionic.Platform.isIOS(); - }; - - exports.isWindows = function() { - return !!navigator.userAgent.match(/Windows/i) || ionic.Platform.is("windows"); - }; - - exports.isUbuntu = function() { - return !!navigator.userAgent.match(/Ubuntu|Linux x86_64/i) || ionic.Platform.is("ubuntu"); - }; - - exports.isDesktop = function() { - if (!angular.isDefined(cache.isDesktop)) { - try { - - cache.isDesktop = !exports.enable && ( - exports.isUbuntu() || - exports.isWindows() || - exports.isOSX() || - // Should have NodeJs and NW - (!!process && !!nw && !!nw.App) - ); - } catch (err) { - // If error (e.g. 'process not defined') - cache.isDesktop = false; + setModelValue(text + settings.decimalSeparator); + } + }; } + settings.rightButton = settings.rightButton || { + html: '<i class="icon ion-backspace-outline"></i>', + action: function () { + var text = getModelValue(); + if (text && text.length) { + text = text.slice(0, -1); + setModelValue(text); + } + } + }; + return settings; } - return cache.isDesktop; - }; + } + }; - exports.isWeb = function() { - return !exports.enable && !exports.isDesktop(); - }; + exports.isAndroid = function () { + return !!navigator.userAgent.match(/Android/i) || ionic.Platform.is("android"); + }; - exports.ready = function() { - if (started) return $q.when(); - return startPromise || exports.start(); - }; + exports.isOSX = function () { + return !!navigator.userAgent.match(/Macintosh/i) || ionic.Platform.is("osx"); + }; - exports.start = function() { + exports.isIOS = function () { + return !!navigator.userAgent.match(/iPhone | iPad | iPod/i) || (!!navigator.userAgent.match(/Mobile/i) && !!navigator.userAgent.match(/Macintosh/i)) || ionic.Platform.isIOS(); + }; - startPromise = ionicReady() - .then(function() { + exports.isWindows = function () { + return !!navigator.userAgent.match(/Windows/i) || ionic.Platform.is("windows"); + }; - exports.enable = window.cordova && cordova && !!cordova.plugins || false; + exports.isUbuntu = function () { + return !!navigator.userAgent.match(/Ubuntu|Linux x86_64/i) || ionic.Platform.is("ubuntu"); + }; - if (exports.enable) { - exports.camera.enable = !!navigator.camera; - exports.keyboard.enable = cordova && cordova.plugins && !!cordova.plugins.Keyboard; - exports.barcode.enable = cordova && cordova.plugins && !!cordova.plugins.barcodeScanner && (!exports.isOSX() || exports.isIOS()); - exports.clipboard.enable = cordova && cordova.plugins && !!cordova.plugins.clipboard; - exports.intent.enable = window && !!window.plugins.launchmyapp; - exports.clipboard.enable = cordova && cordova.plugins && !!cordova.plugins.clipboard; - exports.network.enable = navigator.connection && !!navigator.connection.type; + exports.isDesktop = function () { + if (!angular.isDefined(cache.isDesktop)) { + try { + + cache.isDesktop = !exports.enable && ( + exports.isUbuntu() || + exports.isWindows() || + exports.isOSX() || + // Should have NodeJs and NW + (!!process && !!nw && !!nw.App) + ); + } catch (err) { + // If error (e.g. 'process not defined') + cache.isDesktop = false; + } + } + return cache.isDesktop; + }; - if (exports.keyboard.enable) { - angular.extend(exports.keyboard, cordova.plugins.Keyboard); - } + exports.isWeb = function () { + return !exports.enable && !exports.isDesktop(); + }; - console.debug('[device] Cordova plugins: ' + Object.keys(cordova.plugins)); - console.debug('[device] Windows plugins: ' + Object.keys(window.plugins)); - console.debug('[device] Ionic platform ready, with {camera: {0}, barcode: {1}, keyboard: {2}, clipboard: {3}, intent: {4}, network: {5}}' - .format(exports.camera.enable, exports.barcode.enable, exports.keyboard.enable, exports.clipboard.enable, exports.intent.enable, exports.network.enable)); + exports.ready = function () { + if (started) return $q.when(); + return startPromise || exports.start(); + }; - if (cordova.InAppBrowser) { - console.debug('[device] Enabling InAppBrowser'); - window.open = cordova.InAppBrowser.open; - } + exports.start = function () { + startPromise = ionicReady() + .then(function () { - // Add network listeners - if (exports.network.enable) { - document.addEventListener("offline", function() { - console.info('[device] Network is offline'); - api.network.raise.offline(); - }, false); - document.addEventListener("online", function() { - console.info('[device] Network is online'); - api.network.raise.online(); - }, false); - } + exports.enable = window.cordova && cordova && !!cordova.plugins || false; + if (exports.enable) { + + console.debug('[device] Cordova plugins: ' + Object.keys(cordova.plugins)); + console.debug('[device] Windows plugins: ' + Object.keys(window.plugins)); + + exports.camera.enable = !!navigator.camera; + exports.keyboard.enable = cordova && cordova.plugins && !!cordova.plugins.Keyboard; + exports.barcode.enable = cordova && cordova.plugins && !!cordova.plugins.barcodeScanner && (!exports.isOSX() || exports.isIOS()); + exports.clipboard.enable = cordova && cordova.plugins && !!cordova.plugins.clipboard; + exports.intent.enable = window && !!window.plugins.launchmyapp; + exports.clipboard.enable = cordova && cordova.plugins && !!cordova.plugins.clipboard; + exports.network.enable = navigator.connection && !!navigator.connection.type; + exports.file.enable = !!cordova.file && (exports.isAndroid() || exports.isIOS()); + + if (exports.keyboard.enable) { + angular.extend(exports.keyboard, cordova.plugins.Keyboard); } - else { - console.debug('[device] Ionic platform ready - no device detected.'); + + console.info('[device] Ionic platform ready, with {camera: {0}, barcode: {1}, keyboard: {2}, clipboard: {3}, intent: {4}, network: {5}, file: {6}}' + .format(exports.camera.enable, + exports.barcode.enable, + exports.keyboard.enable, + exports.clipboard.enable, + exports.intent.enable, + exports.network.enable, + exports.file.enable + )); + + if (cordova.InAppBrowser) { + console.debug('[device] Enabling InAppBrowser'); + window.open = cordova.InAppBrowser.open; } - started = true; - startPromise = null; - }); + // Add network listeners + if (exports.network.enable) { + document.addEventListener("offline", function () { + console.info('[device] Network is offline'); + api.network.raise.offline(); + }, false); + document.addEventListener("online", function () { + console.info('[device] Network is online'); + api.network.raise.online(); + }, false); + } + } else { + console.debug('[device] Ionic platform ready - no device detected.'); + } + + started = true; + startPromise = null; + }); - return startPromise; - }; + return startPromise; + }; - api.registerEvent('intent', 'new'); - api.registerEvent('network', 'offline'); - api.registerEvent('network', 'online'); + api.registerEvent('intent', 'new'); + api.registerEvent('network', 'offline'); + api.registerEvent('network', 'online'); - // Export the event api (see ngApi) - exports.api = api; + // Export the event api (see ngApi) + exports.api = api; - return exports; - }) + return exports; + }) - ; +; diff --git a/www/js/services/http-services.js b/www/js/services/http-services.js index fad7d944e44ff1f45726e3e10096bdee9ac61699..1ccd538cbacb98deca8b80fef954ac444aff409c 100644 --- a/www/js/services/http-services.js +++ b/www/js/services/http-services.js @@ -385,11 +385,11 @@ angular.module('cesium.http.services', ['cesium.cache.services']) var searchParams; if (parser.search && parser.search.startsWith('?')) { - searchParams = parser.search.substr(1).split('&') + searchParams = parser.search.substring(1).split('&') .reduce(function(res, searchParam) { if (searchParam.indexOf('=') !== -1) { - var key = searchParam.substr(0, searchParam.indexOf('=')); - var value = searchParam.substr(searchParam.indexOf('=') + 1); + var key = searchParam.substring(0, searchParam.indexOf('=')); + var value = searchParam.substring(searchParam.indexOf('=') + 1); res[key] = value; } else { diff --git a/www/js/services/tx-services.js b/www/js/services/tx-services.js index ad9aa288872c15ae4cbe641554c3c409296ec122..e68cd08538ff72bcfb96fc5e91c6abb12de69ad3 100644 --- a/www/js/services/tx-services.js +++ b/www/js/services/tx-services.js @@ -2,7 +2,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', 'cesium.settings.services', 'cesium.wot.services' ]) -.factory('csTx', function($q, $timeout, $filter, $translate, FileSaver, UIUtils, BMA, Api, +.factory('csTx', function($q, $timeout, $filter, $translate, FileSaver, UIUtils, Device, BMA, Api, csConfig, csSettings, csWot, csCurrency) { 'ngInject'; @@ -458,11 +458,9 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', tx.pubkey, formatDecimal(tx.amount/100), '"' + (tx.isUD ? translations['COMMON.UNIVERSAL_DIVIDEND'] : tx.comment) + '"' - ].join(';') + '\n'); - }, [headers.join(';') + '\n']); - - var file = new Blob(content, {type: 'text/plain; charset=utf-8'}); - FileSaver.saveAs(file, filename); + ].join(';')); + }, [headers.join(';')]).join('\n'); + return Device.file.save(content, {filename: filename}); }); }); } diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index 49b1b2ad9436e25028902ca3a21264b974ece1a4..5efc800d7035634fe2a17f28d936ce22393783eb 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -4,8 +4,8 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .factory('csWallet', function($q, $rootScope, $timeout, $translate, $filter, $ionicHistory, UIUtils, - Api, Idle, localStorage, sessionStorage, Modals, - CryptoUtils, csCrypto, BMA, csConfig, csSettings, FileSaver, Blob, csWot, csTx, csCurrency) { + Api, Idle, localStorage, sessionStorage, Modals, Device, + CryptoUtils, csCrypto, BMA, csConfig, csSettings, FileSaver, csWot, csTx, csCurrency) { 'ngInject'; var defaultBMA = BMA; @@ -1875,10 +1875,21 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, downloadSaveId = function(record){ - return getSaveIDDocument(record) - .then(function(saveId) { - var saveIdFile = new Blob([saveId], {type: 'text/plain; charset=utf-8'}); - FileSaver.saveAs(saveIdFile, '{0}-recover_ID.txt'.format(data.pubkey.substring(0,8))); + + return $q.all([ + csCurrency.get(), + getSaveIDDocument(record), + ]) + .then(function(res) { + var currency = res[0]; + var document= res[1]; + return $translate('ACCOUNT.SECURITY.SAVE_ID_FILENAME', { + currency: currency.name, + pubkey: data.pubkey + }) + .then(function(filename){ + return Device.file.save(document, {filename: filename}); + }); }); }, @@ -1914,8 +1925,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se format: format, }) .then(function(filename){ - var file = new Blob([document], {type: 'text/plain; charset=utf-8'}); - FileSaver.saveAs(file, filename); + return Device.file.save(document, {filename: filename}); }); }); @@ -2026,7 +2036,6 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se addEvent({type: 'pending', message: 'INFO.REVOCATION_SENT_WAITING_PROCESS', context: 'requirements'}, true); } }); - }, downloadRevocation = function(){ @@ -2037,14 +2046,13 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se .then(function(res) { var currency = res[0]; var revocation = res[1]; - var revocationFile = new Blob([revocation], {type: 'text/plain; charset=utf-8'}); return $translate('ACCOUNT.SECURITY.REVOCATION_FILENAME', { uid: data.uid, currency: currency.name, pubkey: data.pubkey }) - .then(function (fileName) { - FileSaver.saveAs(revocationFile, fileName); + .then(function (filename) { + return Device.file.save(revocation, {filename: filename}); }); }); }, @@ -2193,13 +2201,12 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se var content = (children||[]).reduce(function(res, wallet) { return res + [wallet.data.pubkey, wallet.data.uid, wallet.data.localName||wallet.data.name].join('\t') + '\n'; }, ''); - var file = new Blob([content], {type: 'text/plain; charset=utf-8'}); return $translate('ACCOUNT.WALLET_LIST.EXPORT_FILENAME', { pubkey: data.pubkey, currency: currency.name, }) - .then(function (fileName) { - FileSaver.saveAs(file, fileName); + .then(function(filename) { + return Device.file.save(content, {filename: filename}); }); }); }, diff --git a/www/templates/wallet/modal_security.html b/www/templates/wallet/modal_security.html index 814694fcddc73e8a11c32567aa309c6999a31a45..040691b732b22cff401b17cb38f603aaaa9aad4f 100644 --- a/www/templates/wallet/modal_security.html +++ b/www/templates/wallet/modal_security.html @@ -58,8 +58,8 @@ </div> </div> - <div class="item item-complex card stable-bg item-icon-left item-icon-right ink hidden-xs" - ng-click="selectOption('saveID')" ng-if="login && !$root.device.enable"> + <div class="item item-complex card stable-bg item-icon-left item-icon-right ink" + ng-click="selectOption('saveID')" ng-if="login"> <div class="item-content item-text-wrap"> <i class="item-image dark icon ion-person"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px;"></b> @@ -73,7 +73,7 @@ <!-- keyfile generation (hidden if device enable, because we do not known were the file is stored) --> <div class="item item-complex card stable-bg item-icon-left item-icon-right ink hidden-xs" - ng-click="selectOption('generateKeyfile')" ng-if="login && !$root.device.enable"> + ng-click="selectOption('generateKeyfile')" ng-if="login"> <div class="item-content item-text-wrap"> <i class="item-image dark icon ion-document-text"></i> <b class="ion-key icon-secondary dark" style="top: -8px; left: 42px; font-size: 12px;"></b> @@ -84,8 +84,8 @@ </div> </div> - <div class="item item-complex card stable-bg item-icon-left item-icon-right ink hidden-xs hidden-sm" - ng-click="downloadRevokeFile()" ng-if="canRevoke && !$root.device.enable"> + <div class="item item-complex card stable-bg item-icon-left item-icon-right ink" + ng-click="downloadRevokeFile()" ng-if="canRevoke"> <div class="item-content item-text-wrap"> <i class="item-image dark icon ion-person"></i> <b class="ion-ios-redo icon-secondary dark" style="top: -8px; left: 39px; font-size: 12px;"></b> diff --git a/www/templates/wallet/popover_tx_actions.html b/www/templates/wallet/popover_tx_actions.html new file mode 100644 index 0000000000000000000000000000000000000000..83900e51a51b23aefe3f93524bd5a4ac830756eb --- /dev/null +++ b/www/templates/wallet/popover_tx_actions.html @@ -0,0 +1,16 @@ +<ion-popover-view class="fit has-header popover-wallet-tx-actions"> + <ion-header-bar> + <h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1> + </ion-header-bar> + <ion-content scroll="false"> + <div class="list item-text-wrap"> + + <a class="item item-icon-left ink visible-xs visible-sm" + ng-click="downloadHistoryFile()"> + <i class="icon ion-android-download"></i> + {{'COMMON.BTN_DOWNLOAD_ACCOUNT_STATEMENT' | translate}} + </a> + + </div> + </ion-content> +</ion-popover-view> diff --git a/www/templates/wallet/view_wallet_tx.html b/www/templates/wallet/view_wallet_tx.html index 419e89d989971f0148f31e540b8364cf04db577c..4f28827d846993c6ea543c7bc0aa17916fa21912 100644 --- a/www/templates/wallet/view_wallet_tx.html +++ b/www/templates/wallet/view_wallet_tx.html @@ -8,6 +8,10 @@ <ion-nav-buttons side="secondary"> <cs-extension-point name="nav-buttons"></cs-extension-point> + + <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" + ng-click="showActionsPopover($event)"> + </button> </ion-nav-buttons> <ion-content scroll="true" class="refresher-positive-900-bg" @@ -70,7 +74,7 @@ <!-- QR code --> <ng-include src="::'templates/common/qrcode.html'"></ng-include> - <!-- Buttons bar--> + <!-- Buttons bar --> <div class="hidden-xs hidden-sm padding text-center" ng-if="!loading"> <button class="button button-stable button-small-padding icon ion-loop ink" diff --git a/www/templates/wot/popover_tx_actions.html b/www/templates/wot/popover_tx_actions.html new file mode 100644 index 0000000000000000000000000000000000000000..83900e51a51b23aefe3f93524bd5a4ac830756eb --- /dev/null +++ b/www/templates/wot/popover_tx_actions.html @@ -0,0 +1,16 @@ +<ion-popover-view class="fit has-header popover-wallet-tx-actions"> + <ion-header-bar> + <h1 class="title" translate>COMMON.POPOVER_ACTIONS_TITLE</h1> + </ion-header-bar> + <ion-content scroll="false"> + <div class="list item-text-wrap"> + + <a class="item item-icon-left ink visible-xs visible-sm" + ng-click="downloadHistoryFile()"> + <i class="icon ion-android-download"></i> + {{'COMMON.BTN_DOWNLOAD_ACCOUNT_STATEMENT' | translate}} + </a> + + </div> + </ion-content> +</ion-popover-view> diff --git a/yarn.lock b/yarn.lock index f77bfd57f0f714fe2d5ecd66ba5125dd9b0dba76..52bab6fdc0f436119107fdf1263b2c1e92825898 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3163,10 +3163,10 @@ cordova-plugin-dialogs@^2.0.2: resolved "https://registry.npmjs.org/cordova-plugin-dialogs/-/cordova-plugin-dialogs-2.0.2.tgz#ac3ce8b73bc885ff847078d5b533e7a4ed418a2f" integrity sha512-FUHI6eEVeoz2VkxbF0P56QlUQLGzXcvw3i4xuXyM9gEct6Y+FA3Xzgl2pJTZcTg5wRqLWzN08kgNoHPkom15pw== -cordova-plugin-file@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/cordova-plugin-file/-/cordova-plugin-file-6.0.2.tgz#f3911479f8357e9aacb5576674f8d95b31a1fb20" - integrity sha512-m7cughw327CjONN/qjzsTpSesLaeybksQh420/gRuSXJX5Zt9NfgsSbqqKDon6jnQ9Mm7h7imgyO2uJ34XMBtA== +cordova-plugin-file@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/cordova-plugin-file/-/cordova-plugin-file-8.0.0.tgz#e46fd696dabc3d8d79723caefa1804becd91356f" + integrity sha512-pgxCJtDjDKzyeqvrn0KnDubf9b1VLv+OyWTXjUR7T52o7oGDUkR3ubT89i/1ugHtRU6mY7XIGHD4drUByDQClw== cordova-plugin-ionic-keyboard@^2.2.0: version "2.2.0" @@ -9052,10 +9052,10 @@ node-notifier@10.0.1: uuid "^8.3.2" which "^2.0.2" -node-sass@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/node-sass/-/node-sass-8.0.0.tgz#c80d52148db0ce88610bcf1e1d112027393c13e1" - integrity sha512-jPzqCF2/e6JXw6r3VxfIqYc8tKQdkj5Z/BDATYyG6FL6b/LuYBNFGFVhus0mthcWifHm/JzBpKAd+3eXsWeK/A== +node-sass@^9.0.0: + version "9.0.0" + resolved "https://registry.npmjs.org/node-sass/-/node-sass-9.0.0.tgz#c21cd17bd9379c2d09362b3baf2cbf089bce08ed" + integrity sha512-yltEuuLrfH6M7Pq2gAj5B6Zm7m+gdZoG66wTqG6mIZV/zijq3M2OO2HswtT6oBspPyFhHDcaxWpsBm0fRNDHPg== dependencies: async-foreach "^0.1.3" chalk "^4.1.2"