From dfa9c9961599753d5c55412ffe941a9faf384254 Mon Sep 17 00:00:00 2001 From: Niko PLP Date: Sun, 14 Jul 2024 00:34:53 +0300 Subject: [PATCH] fixes and improvements of QR scanning --- nextgraph/src/local_broker.rs | 2 +- ng-app/src/lib/Login.svelte | 2 +- .../src/lib/components/PasswordInput.svelte | 1 + ng-app/src/locales/en.json | 30 +- ng-app/src/routes/ScanQR.svelte | 5 +- ng-app/src/routes/WalletInfo.svelte | 276 +++++++++++------- ng-app/src/routes/WalletLogin.svelte | 7 +- ng-app/src/routes/WalletLoginQr.svelte | 173 ++++++----- ng-app/src/store.ts | 26 ++ ng-app/src/styles.css | 197 +++++++------ ng-net/src/actors/ext/mod.rs | 1 - 11 files changed, 405 insertions(+), 315 deletions(-) diff --git a/nextgraph/src/local_broker.rs b/nextgraph/src/local_broker.rs index 0ab4558..dac2265 100644 --- a/nextgraph/src/local_broker.rs +++ b/nextgraph/src/local_broker.rs @@ -44,7 +44,7 @@ use ng_verifier::types::*; use ng_verifier::verifier::Verifier; use ng_wallet::bip39::encode_mnemonic; -use ng_wallet::emojis::{display_pazzle, display_pazzle_one, encode_pazzle}; +use ng_wallet::emojis::{display_pazzle, encode_pazzle}; use ng_wallet::{ create_wallet_first_step_v0, create_wallet_second_step_v0, display_mnemonic, types::*, }; diff --git a/ng-app/src/lib/Login.svelte b/ng-app/src/lib/Login.svelte index b9c086a..9afdc07 100644 --- a/ng-app/src/lib/Login.svelte +++ b/ng-app/src/lib/Login.svelte @@ -89,7 +89,7 @@ unlockWith = "pazzle"; scrollToTop(); } - function start_with_mnemonic() { + async function start_with_mnemonic() { loaded = false; step = "mnemonic"; unlockWith = "mnemonic"; diff --git a/ng-app/src/lib/components/PasswordInput.svelte b/ng-app/src/lib/components/PasswordInput.svelte index e744d08..6ed9c88 100644 --- a/ng-app/src/lib/components/PasswordInput.svelte +++ b/ng-app/src/lib/components/PasswordInput.svelte @@ -46,6 +46,7 @@ {placeholder} {id} {type} + autofocus on:input={handleInput} class={`${className} pr-12 text-md block`} autocomplete={auto_complete} diff --git a/ng-app/src/locales/en.json b/ng-app/src/locales/en.json index ae3cd3c..fb94260 100644 --- a/ng-app/src/locales/en.json +++ b/ng-app/src/locales/en.json @@ -28,18 +28,21 @@ "remove_wallet_modal.title": "Remove wallet?", "remove_wallet_modal.confirm": "Are you sure you want to remove this wallet from your device?", "create_text_code": "Generate TextCode to export", - "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.", - "scan_qr.scan_btn": "Scan QR Code ", + "scan_qr.title": "Export by scanning a QR-Code", + "scan_qr.no_camera": "If to the contrary, the other device does not have a camera, ", + "scan_qr.other_has_camera": "If the other device where you want to import the Wallet, has a camera, then you can just click on the Back button and select Generate QR to export", + "scan_qr.notes": "You will now scan the QR-Code that appears on the screen of the other device (the one you want to transfer your wallet to).", + "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 transferred to the new device.", "gen_qr.title": "Export by generating QR-Code", - "gen_qr.notes": "Use the following QR-Code to scan with the device that you want to transfer your wallet to.", + "gen_qr.notes": "In order to transfer your wallet to another device, you will now display a QR-Code here on this device, and you will then scan it with the other device where you want to transfer your wallet to.", + "gen_qr.no_camera": "If the device where you want to import the Wallet, does not have a camera, then you will have to choose another method.", "gen_qr.img_title": "Your Export QR Code to Scan", "gen_qr.img_alt": "Your Export QR Code to Scan", - "gen_qr.gen_button": "Show QR Code", + "gen_qr.gen_button": "Display QR-Code", "gen_text_code.title": "Export with TextCode", "gen_text_code.gen_btn": "Generate TextCode", "gen_text_code.label": "Your TextCode:" @@ -256,8 +259,11 @@ "scan.description": "To import your wallet from another device, generate an export-QR-Code there. On the other device, go to
User Panel > Wallet > Export by scanning QR-Code to export.", "scan.button": "Scan QR-Code", "scan.modal.title": "Scan Wallet QR-Code", - "gen.description": "To import your wallet from another device, you have to generate an import-QR-Code here on this device, and then scan it with your other device. On the other device, go to
User Panel > Wallet > Export by generating QR-Code, to export.", - "gen.generated": "Scan this QR-Code from the the other device.", + "gen.button": "Generate QR-Code", + "gen.description": "To import your wallet from another device, you have to generate a QR-Code here on this device, and then scan it with your other device (the one where your wallet is located for now).
If your other device does not have a camera, then you have to use another method for importing your wallet here.", + "offline_advice": "If you do not have internet on this device, you can use the \"Import a Wallet file\" method instead.", + "gen.letsgo": "Ready? On your other device, you first have to be logged-in (wallet is opened) and then you go to
User Panel > Wallet > Scan QR to export.
Then on this present device, click below on the
Generate QR-Code button.", + "gen.generated": "Scan this QR-Code from the other device.
You have 5 minutes to do so.", "success_btn": "Continue to Login" }, "wallet_login_textcode": { @@ -371,11 +377,13 @@ "donate_nextgraph": "Donate to NextGraph" }, "wallet_sync": { - "offline_warning": "You cannot transfer your wallet when offline.
Please make sure, you are connected first.", - "textcode.usage_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 the \"Import with QRCode\" option instead, 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.", - "server_transfer_notice": "Both devices need to be online.
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.", + "offline_warning": "You cannot transfer your wallet when offline.
Please make sure you are connected to the internet first.", + "textcode.usage_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 the \"Import with QRCode\" option instead, as it is safer and simpler. 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.", + "server_transfer_notice": "Both devices need to be online.
During this wallet transfer, your wallet will be temporarily and securely stored on our servers for up to 5 minutes, using two levels of encryption.
We at NextGraph will never be able to read your wallet, your PIN, your pazzle nor your mnemonic.", "importing": "Importing wallet", - "error": "An error occurred while synchronizing your wallet:
{error}" + "error": "An error occurred while synchronizing your wallet:
{error}", + "no_camera": "Unfortunately, your device does not have a camera.
You cannot scan any QR-Code.
In order to export your wallet to another device, you will have to use another method.", + "no_camera_alternatives": "You have 2 other options: \"Import a Wallet file\" (transfer it using a USB key by example, useful if you are offline) or \"Import a TextCode\" (which is a text you will have to transfer with another messaging app)." }, "emojis": { "category": { diff --git a/ng-app/src/routes/ScanQR.svelte b/ng-app/src/routes/ScanQR.svelte index 57b1a77..e083a36 100644 --- a/ng-app/src/routes/ScanQR.svelte +++ b/ng-app/src/routes/ScanQR.svelte @@ -59,9 +59,12 @@ // Add scanner to Screen. webScanner.render((decoded_text, decoded_result) => { + console.log(decoded_result); // Handle scan result on_qr_scanned(decoded_text); - }, undefined); + }, (error) => { + console.error(error); + }); // Auto-Request camera permissions (there's no native way, unfortunately...) setTimeout(() => { diff --git a/ng-app/src/routes/WalletInfo.svelte b/ng-app/src/routes/WalletInfo.svelte index b36bc30..7c11fcc 100644 --- a/ng-app/src/routes/WalletInfo.svelte +++ b/ng-app/src/routes/WalletInfo.svelte @@ -41,6 +41,7 @@ display_error, online, scanned_qr_code, + check_has_camera, } from "../store"; import { default as ng } from "../api"; @@ -63,6 +64,8 @@ let scanner_state: "before_start" | "scanned" | "success" = "before_start"; + let has_camera = false; + async function scrollToTop() { await tick(); container.scrollIntoView(); @@ -78,6 +81,7 @@ scanned_qr_code.set(""); } await scrollToTop(); + has_camera = await check_has_camera(); }); function open_scan_menu() { @@ -98,7 +102,7 @@ generation_state = "loading"; generated_qr = await ng.wallet_export_get_qrcode( $active_session.session_id, - Math.ceil(container.clientWidth * 0.9) + container.clientWidth ); generation_state = "generated"; } @@ -184,13 +188,13 @@ -
-
- - - {#if sub_menu === null} +
+ + {#if sub_menu === null} + +
  • {$t("pages.wallet_info.title")}

    @@ -211,7 +215,7 @@ {$t("buttons.back")}
  • - +
  • - +
  • - {:else if sub_menu === "scan_qr"} - + + + {:else if sub_menu === "scan_qr"} + + +
  • {$t("pages.wallet_info.scan_qr.title")} @@ -412,109 +422,159 @@ /> {$t("buttons.back")}

  • - - {#if scanner_state === "before_start"} - + {#if !has_camera}
  • - {@html $t("pages.wallet_info.scan_qr.notes")} -
    - {@html $t("wallet_sync.server_transfer_notice")} + + {@html $t("wallet_sync.no_camera")} + + + {@html $t("pages.wallet_info.scan_qr.other_has_camera")} + + + {@html $t("pages.wallet_info.scan_qr.no_camera")} + {@html $t("wallet_sync.no_camera_alternatives")} +
  • - - - {#if !$online} + {:else} + {#if scanner_state === "before_start"} +
  • - - {@html $t("wallet_sync.offline_warning")} - + {@html $t("pages.wallet_info.scan_qr.notes")} +

    + {@html $t("wallet_sync.server_transfer_notice")}
  • - {/if} - - {:else if scanner_state === "scanned"} -
  • - -
    - {@html $t("pages.wallet_info.scan_qr.syncing")}... -
    -
    - {scanned_qr_code} -
    -
  • - {:else if scanner_state === "success"} -
  • -
    - -
    -
    - {@html $t("pages.wallet_info.scan_qr.scan_successful")} -
    -
  • + + {#if !$online} +
  • + + {@html $t("wallet_sync.offline_warning")} + +
  • + {/if} +
  • + +
  • + {:else if scanner_state === "scanned"} +
  • + +
    + {@html $t("pages.wallet_info.scan_qr.syncing")}... +
    +
    + {scanned_qr_code} +
    +
  • + {:else if scanner_state === "success"} +
  • +
    + +
    +
    + {@html $t("pages.wallet_info.scan_qr.scan_successful")} +
    +
  • + {/if} {/if}
    - - {:else if sub_menu === "generate_qr"} - -
  • -

    - {$t("pages.wallet_info.gen_qr.title")} -

    -
  • +
    +
    + + {:else if sub_menu === "generate_qr"} + {#if generation_state !== "generated"} +
    +
    +

    + {$t("pages.wallet_info.gen_qr.title")} +

    +
    - - + + + + + +
    + {@html $t("pages.wallet_info.gen_qr.notes")} +

    + {@html $t("pages.wallet_info.gen_qr.no_camera")} + {@html $t("wallet_sync.no_camera_alternatives")} +

    + {@html $t("wallet_sync.server_transfer_notice")} +
    - -
  • - {@html $t("pages.wallet_info.gen_qr.notes")} -
    - {@html $t("wallet_sync.server_transfer_notice")} -
  • + + {#if !$online} +
    + + {@html $t("wallet_sync.offline_warning")} + +
    + {/if} - - {#if !$online} -
  • - - {@html $t("wallet_sync.offline_warning")} - -
  • - {/if} + {#if generation_state === "before_start"} +
    +
    +
    +
    + {:else if generation_state === "loading"} + + {/if} - {#if generation_state === "before_start"} - - {$t("pages.wallet_info.gen_qr.gen_button")} - - {:else if generation_state === "loading"} - - {:else} - -
    - {@html generated_qr} -
    - {/if} - - {:else if sub_menu === "text_code"} +
    + {:else} +
    +

    + {$t("pages.wallet_info.gen_qr.title")} +

    +
    + {@html $t("pages.wallet_login_qr.gen.generated")} +
    + + +
    + {@html generated_qr} +
    + + +
    + {/if} + {:else if sub_menu === "text_code"} + +
  • @@ -566,16 +626,16 @@ {:else} - + {$t("pages.wallet_info.gen_text_code.label")}
    {/if}

  • - {/if} -
    -
    + + + {/if}
    {#if error}
    @@ -588,7 +648,7 @@

    {/if} -
    +