diff --git a/ng-app/src/App.svelte b/ng-app/src/App.svelte index 3efb223..948fe8d 100644 --- a/ng-app/src/App.svelte +++ b/ng-app/src/App.svelte @@ -38,11 +38,15 @@ import ng from "./api"; import AccountInfo from "./routes/AccountInfo.svelte"; + import WalletLoginQr from "./routes/WalletLoginQr.svelte"; + import WalletLoginTextCode from "./routes/WalletLoginTextCode.svelte"; const routes = new Map(); routes.set("/", Home); routes.set("/test", Test); routes.set("/wallet/login", WalletLogin); + routes.set("/wallet/login-qr", WalletLoginQr); + routes.set("/wallet/login-text-code", WalletLoginTextCode); routes.set("/wallet/create", WalletCreate); routes.set("/i/:invitation", Invitation); routes.set("/user", User); @@ -286,5 +290,3 @@ {:else} {/if} - - diff --git a/ng-app/src/locales/en.json b/ng-app/src/locales/en.json index cd27336..5fd53c4 100644 --- a/ng-app/src/locales/en.json +++ b/ng-app/src/locales/en.json @@ -30,17 +30,17 @@ "remove_wallet_modal.confirm": "Are you sure you want to remove this wallet from your device?", "offline_warning": "You cannot export your Wallet with QR-Code while being offline.
Please connect to the internet and to your broker first.", "scan_qr.title": "Export by scanning QR-Code", - "scan_qr.notes": "Scan the QR-Code on the device that you want to transfer your wallet to.
For the wallet transfer, you agree that your double-encrypted wallet is stored on our servers for no more than 5 minutes.", + "scan_qr.notes": "Scan the QR-Code on the device that you want to transfer your wallet to.
During this wallet import, your wallet will be temporarily and securely stored on our servers for up to 5 minutes, using two levels of encryption.", "scan_qr.scan_btn": "Scan QR Code ", "scan_qr.scanner.title": "Scan your QR Code", "scan_qr.scanner.loading": "Loading scanner", "scan_qr.syncing": "Synchronizing wallet", "scan_qr.scan_successful": "Success!
Your wallet has been synchronized to the new device.", "gen_qr.title": "Export with generated QR-Code", - "gen_qr.notes": "Use the following QR-Code to scan with the device that you want to transfer your wallet to.
For the wallet transfer, you agree for your double-encrypted wallet to be stored on our servers for no more than 5 minutes.", + "gen_qr.notes": "Use the following QR-Code to scan with the device that you want to transfer your wallet to.
During this wallet import, your wallet will be temporarily and securely stored on our servers for up to 5 minutes, using two levels of encryption.", "gen_qr.img_title": "Your Export QR Code to Scan", "gen_qr.img_alt": "Your Export QR Code to Scan", - "gen_qr.gen_button": "Generate QR Code" + "gen_qr.gen_button": "Display QR Code" }, "settings": { "title": "Settings" @@ -244,6 +244,25 @@ "import_link": "Enter a Wallet Link", "new_wallet": "Create a new Wallet", "logged_in": "You are logged in.
please wait while the app is loading" + }, + "wallet_login_qr": { + "title": "Import Wallet with QR-Code", + "offline_warning": "Cannot connect to the wallet synchronization service. Are you offline?", + "scan.description": "To import your wallet from another device, generate a wallet QR-Code there. On the other device, go to
User Panel > Wallet > Generate QR to export.
Both devices need to be online.
For the wallet transfer, your wallet will be temporarily and securely stored on our servers for up to 5 minutes, using double encryption.", + "scan.button": "Scan QR-Code", + "scan.syncing": "Importing wallet", + "scan.error": "An error occurred transferring wallet: {error}", + "scan.modal.title": "Scan Wallet QR-Code", + "scan.success": "Your wallet has been imported!", + "gen.button": "Generate", + "gen.description": "To import your wallet from another device, you have to display a QR-Code here on this device, and then scan it with your other device. On the other device, go to
User Panel > Wallet > Scan QR to export.
Both devices need to be online.
For the wallet transfer, your wallet will be temporarily and securely stored on our servers for up to 5 minutes, using double encryption. If your other device does not have a camera, then you should use the \"Enter a TextCode\" option on the previous screen.", + "gen.generated": "Scan this QR-Code from the the other device.", + "gen.success": "Your wallet has been imported!", + "success_btn": "Continue to Login" + }, + "wallet_login_textcode": { + "title": "Import Wallet from TextCode", + "warning": "You have to exchange this TextCode with the other device by any means available to you (email, other messenger apps, etc...). It is highly recommended to use a tool that is end-to-end encrypted. If you can, you should use instead the \"Import with QRCode\" option, as it is safer. If your devices are not connected to the internet, then you can use the \"Import a Wallet File\" option. In this case, you will transfer the wallet file with a USB key, from one device to the other, or for mobile, by connecting your mobile with the USB cable, to the computer, and then transferring the file with the File Transfer utility on Android, or AirDrop/Finder/iTunes on an iPhone/mac/PC. We do not recommend uploading your wallet file to any cloud service." } }, "buttons": { diff --git a/ng-app/src/routes/WalletCreate.svelte b/ng-app/src/routes/WalletCreate.svelte index f2628d5..0384494 100644 --- a/ng-app/src/routes/WalletCreate.svelte +++ b/ng-app/src/routes/WalletCreate.svelte @@ -1622,7 +1622,6 @@
- diff --git a/ng-app/src/routes/WalletInfo.svelte b/ng-app/src/routes/WalletInfo.svelte index cdf2816..e5bf2a5 100644 --- a/ng-app/src/routes/WalletInfo.svelte +++ b/ng-app/src/routes/WalletInfo.svelte @@ -136,9 +136,15 @@ html5QrcodeScanner = new WebQRScanner( "scanner-div", { fps: 10, qrbox: { width: 300, height: 300 }, formatsToSupport: [0] }, - /* verbose= */ false + false ); html5QrcodeScanner.render(onScanSuccess, undefined); + + // Auto-Request camera permissions (there's no native way, unfortunately...) + setTimeout(() => { + // Auto-start by clicking button + document.getElementById("html5-qrcode-button-camera-permission")?.click(); + }, 100); } function close_scanner() { diff --git a/ng-app/src/routes/WalletLogin.svelte b/ng-app/src/routes/WalletLogin.svelte index 545191b..5af265d 100644 --- a/ng-app/src/routes/WalletLogin.svelte +++ b/ng-app/src/routes/WalletLogin.svelte @@ -18,7 +18,7 @@ + + +
+
+ +
+

{$t("pages.wallet_login_qr.title")}

+
+ + + {#if login_method === undefined} + +
+ {:else if false} + + +
+ + {@html $t("pages.wallet_login_qr.offline_warning")} + +
+ {:else if login_method === "scan"} + + {#if scan_state === "before_start"} + +
+ {@html $t("pages.wallet_login_qr.scan.description")} +
+ {:else if scan_state === "scanning"} + + {:else if scan_state === "has_scanned"} + +
+ +
+
+ {$t("pages.wallet_login_qr.scan.syncing")} +
+ {:else if scan_state === "success"} +
+ +
+
+ {@html $t("pages.wallet_login_qr.scan.success")} +
+ {:else} + + {$t("pages.wallet_login_qr.scan.error", { + values: { error: $t("errors." + scan_state) }, + })} + {/if} + {:else if login_method === "gen"} + + {#if gen_state == "before_start"} + +
+ {@html $t("pages.wallet_login_qr.gen.description")} +
+ {:else if gen_state === "generating"} +
+ +
+ {:else if gen_state === "generated"} + +
+ {@html $t("pages.wallet_login_qr.gen.generated")} +
+ + +
+ {#if generated_qr === "dummy"} +
+ +
+ {:else} + pages.wallet_info.gen_qr_alt + {/if} +
+ {:else if gen_state === "success"} +
+ +
+
+ {@html $t("pages.wallet_login_qr.gen.success")} +
+ {:else} + + {$t("pages.wallet_login_qr.gen.error")} + {/if} + {/if} + +
+
+ {#if login_method === "scan" && scan_state === "before_start"} + + + {:else if login_method === "gen" && gen_state === "before_start"} + + + {:else if scan_state === "success" || gen_state === "success"} + + + + {/if} + + + {#if scan_state !== "success" && gen_state !== "success"} + + {/if} +
+
+
+ + +
+ {$t("pages.wallet_login_qr.scan.modal.loading")}... +
+
+
+
diff --git a/ng-app/src/routes/WalletLoginTextCode.svelte b/ng-app/src/routes/WalletLoginTextCode.svelte new file mode 100644 index 0000000..c5bb81a --- /dev/null +++ b/ng-app/src/routes/WalletLoginTextCode.svelte @@ -0,0 +1,310 @@ + + + +
+
+ +
+

{$t("pages.wallet_login_qr.title")}

+
+ + + {#if login_method === undefined} + +
+ {:else if false} + + +
+ + {@html $t("pages.wallet_login_qr.offline_warning")} + +
+ {:else if login_method === "scan"} + + {#if scan_state === "before_start"} + +
+ {@html $t("pages.wallet_login_qr.scan.description")} +
+ {:else if scan_state === "scanning"} + + {:else if scan_state === "has_scanned"} + +
+ +
+
+ {$t("pages.wallet_login_qr.scan.syncing")} +
+ {:else if scan_state === "success"} +
+ +
+
+ {@html $t("pages.wallet_login_qr.scan.success")} +
+ {:else} + + {$t("pages.wallet_login_qr.scan.error", { + values: { error: $t("errors." + scan_state) }, + })} + {/if} + {:else if login_method === "gen"} + + {#if gen_state == "before_start"} + +
+ {@html $t("pages.wallet_login_qr.gen.description")} +
+ {:else if gen_state === "generating"} +
+ +
+ {:else if gen_state === "generated"} + +
+ {@html $t("pages.wallet_login_qr.gen.generated")} +
+ + +
+ {#if generated_qr === "dummy"} +
+ +
+ {:else} + pages.wallet_info.gen_qr_alt + {/if} +
+ {:else if gen_state === "success"} +
+ +
+
+ {@html $t("pages.wallet_login_qr.gen.success")} +
+ {:else} + + {$t("pages.wallet_login_qr.gen.error")} + {/if} + {/if} + +
+
+ {#if login_method === "scan" && scan_state === "before_start"} + + + {:else if login_method === "gen" && gen_state === "before_start"} + + + {:else if scan_state === "success" || gen_state === "success"} + + + + {/if} + + + {#if scan_state !== "success" && gen_state !== "success"} + + {/if} +
+
+
+ + +
+ {$t("pages.wallet_login_qr.scan.modal.loading")}... +
+
+
+
diff --git a/ng-app/src/styles.css b/ng-app/src/styles.css index f0bc380..0e4992f 100644 --- a/ng-app/src/styles.css +++ b/ng-app/src/styles.css @@ -9,6 +9,15 @@ // according to those terms. */ +/** To format paths, like Settings > Wallet > Generate Wallet QR */ +.path { + font-family: monospace; + background-color: rgba(73, 114, 165, 0.1); +} + +/* TODO: hide qr scanner and info button */ + + .logo { padding: 1.5em; will-change: filter;