From 7609d85878d2485b97c22162e3e4ef1bfc9c8ef9 Mon Sep 17 00:00:00 2001
From: Laurin Weger <Laurin-W@users.noreply.github.com>
Date: Tue, 2 Jul 2024 15:41:39 +0200
Subject: [PATCH] add password hide option

---
 ng-app/src/lib/Login.svelte                   | 76 +++++++++++--------
 .../src/lib/components/PasswordInput.svelte   | 61 +++++++++++++++
 2 files changed, 104 insertions(+), 33 deletions(-)
 create mode 100644 ng-app/src/lib/components/PasswordInput.svelte

diff --git a/ng-app/src/lib/Login.svelte b/ng-app/src/lib/Login.svelte
index 5eb20223..d8615636 100644
--- a/ng-app/src/lib/Login.svelte
+++ b/ng-app/src/lib/Login.svelte
@@ -28,6 +28,7 @@
     Key,
     CheckCircle,
   } from "svelte-heros-v2";
+  import PasswordInput from "./components/PasswordInput.svelte";
   //import Worker from "../worker.js?worker&inline";
   export let wallet;
   export let for_import = false;
@@ -88,10 +89,12 @@
 
   let pazzlePage = 0;
 
+  /** The selected emojis by category (one for each pazzle page). First will be the selected of first pazzle page. */
   let selection = [].fill(null, 0, pazzle_length);
 
   let pin_code = [];
 
+  /** The selected order from the order page. */
   let ordered = [];
 
   let shuffle_pin;
@@ -244,7 +247,7 @@
   async function select_order(val) {
     ordered.push(val);
     val.sel = ordered.length;
-    console.debug("ordered", ordered);
+
     selection = selection;
     if (ordered.length == pazzle_length - 1) {
       let last = selection.find((emoji) => !emoji.sel);
@@ -257,7 +260,9 @@
   }
 
   function go_back() {
-    if (step === "pazzle") {
+    if (step === "mnemonic") {
+      init();
+    } else if (step === "pazzle") {
       // Go to previous pazzle or init page, if on first pazzle.
       if (pazzlePage === 0) {
         init();
@@ -274,7 +279,9 @@
         selection = selection;
       }
     } else if (step === "pin") {
-      if (pin_code.length === 0) {
+      if (unlockWith === "mnemonic") {
+        start_with_mnemonic();
+      } else if (pin_code.length === 0) {
         // Unselect the last two elements.
         const to_unselect = ordered.slice(-2);
         to_unselect.forEach((val) => {
@@ -443,43 +450,21 @@
       class:max-w-[600px]={!mobile}
     >
       <div class="mt-auto flex flex-col justify-center">
-        {#if step == "pazzle"}
-          <p class="max-w-xl md:mx-auto lg:max-w-2xl">
-            <span class="text-xl">
-              <!-- TODO: Internationalization-->
-              Select your emoji of category: {emoji_cat[
-                shuffle.category_indices[pazzlePage]
-              ]}</span
-            >
-          </p>
-          {#each [0, 1, 2, 3, 4] as row}
-            <div class="columns-3 gap-0">
-              {#each emojis2[pazzlePage]?.slice(0 + row * 3, 3 + row * 3) || [] as emoji, i (pazzlePage + "-" + row + "-" + i)}
-                <div
-                  role="button"
-                  tabindex="0"
-                  class="w-full aspect-square emoji focus:outline-none focus:bg-gray-300"
-                  on:click={() => select(row * 3 + i)}
-                  on:keypress={() => select(row * 3 + i)}
-                >
-                  <svelte:component this={emoji.svg?.default} />
-                </div>
-              {/each}
-            </div>
-          {/each}
-        {:else if step == "mnemonic"}
+        <!-- Unlock Screens -->
+
+        {#if step == "mnemonic"}
           <form on:submit|preventDefault={start_pin}>
             <label
               for="mnemonic-input"
               class="block mb-2 text-xl text-gray-900 dark:text-white"
               >Your 12 word mnemonic</label
             >
-            <input
-              type="password"
+            <PasswordInput
               id="mnemonic-input"
               placeholder="Enter your 12 word mnemonic here separated by spaces"
               bind:value={mnemonic}
-              class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
+              className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
+              auto_complete="mnemonic"
             />
             <div class="flex">
               <button
@@ -494,6 +479,30 @@
               >
             </div>
           </form>
+        {:else if step == "pazzle"}
+          <p class="max-w-xl md:mx-auto lg:max-w-2xl">
+            <span class="text-xl">
+              <!-- TODO: Internationalization-->
+              Select your emoji of category: {emoji_cat[
+                shuffle.category_indices[pazzlePage]
+              ]}</span
+            >
+          </p>
+          {#each [0, 1, 2, 3, 4] as row}
+            <div class="columns-3 gap-0">
+              {#each emojis2[pazzlePage]?.slice(0 + row * 3, 3 + row * 3) || [] as emoji, i (pazzlePage + "-" + row + "-" + i)}
+                <div
+                  role="button"
+                  tabindex="0"
+                  class="w-full aspect-square emoji focus:outline-none focus:bg-gray-300"
+                  on:click={() => select(row * 3 + i)}
+                  on:keypress={() => select(row * 3 + i)}
+                >
+                  <svelte:component this={emoji.svg?.default} />
+                </div>
+              {/each}
+            </div>
+          {/each}
         {:else if step == "order"}
           <p class="max-w-xl md:mx-auto lg:max-w-2xl mb-2">
             <span class="text-xl">Click your emojis in the correct order</span>
@@ -538,8 +547,9 @@
               >{#each pin_code as pin_key}*{/each}</span
             >
           </p>
+
           {#each [0, 1, 2] as row}
-            <div class="columns-3 gap-2">
+            <div class="columns-3 flex">
               {#each shuffle_pin.slice(0 + row * 3, 3 + row * 3) as num}
                 <button
                   tabindex="0"
@@ -552,7 +562,7 @@
               {/each}
             </div>
           {/each}
-          <div class="columns-3 gap-2">
+          <div class="columns-3 flex">
             <div class="m-1 w-full aspect-square" />
             <button
               tabindex="0"
diff --git a/ng-app/src/lib/components/PasswordInput.svelte b/ng-app/src/lib/components/PasswordInput.svelte
new file mode 100644
index 00000000..e2d88b25
--- /dev/null
+++ b/ng-app/src/lib/components/PasswordInput.svelte
@@ -0,0 +1,61 @@
+<script lang="ts">
+  export let value: string | undefined = undefined;
+  export let placeholder: string | undefined = undefined;
+  export let className: string | undefined = undefined;
+  export let id: string | undefined = undefined;
+  export let auto_complete: string | undefined = undefined;
+
+  export let show: boolean = false;
+
+  let type: "password" | "text" = "password";
+  $: type = show ? "text" : "password";
+
+  function handleInput(event: Event) {
+    const target = event.target as HTMLInputElement;
+    value = target.value;
+  }
+</script>
+
+<div class="relative">
+  <input
+    {value}
+    {placeholder}
+    {id}
+    {type}
+    on:input={handleInput}
+    class={`${className} text-md block`}
+    autocomplete={auto_complete}
+  />
+
+  <div
+    class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5"
+  >
+    <svg
+      fill="none"
+      on:click={() => (show = !show)}
+      class={`${show ? "block" : "hidden"} h-6 text-gray-700`}
+      xmlns="http://www.w3.org/2000/svg"
+      viewbox="0 0 576 512"
+    >
+      <path
+        fill="currentColor"
+        d="M572.52 241.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400a144 144 0 1 1 144-144 143.93 143.93 0 0 1-144 144zm0-240a95.31 95.31 0 0 0-25.31 3.79 47.85 47.85 0 0 1-66.9 66.9A95.78 95.78 0 1 0 288 160z"
+      >
+      </path>
+    </svg>
+
+    <svg
+      fill="none"
+      class={`${!show ? "block" : "hidden"} h-6 text-gray-700`}
+      on:click={() => (show = !show)}
+      xmlns="http://www.w3.org/2000/svg"
+      viewbox="0 0 640 512"
+    >
+      <path
+        fill="currentColor"
+        d="M320 400c-75.85 0-137.25-58.71-142.9-133.11L72.2 185.82c-13.79 17.3-26.48 35.59-36.72 55.59a32.35 32.35 0 0 0 0 29.19C89.71 376.41 197.07 448 320 448c26.91 0 52.87-4 77.89-10.46L346 397.39a144.13 144.13 0 0 1-26 2.61zm313.82 58.1l-110.55-85.44a331.25 331.25 0 0 0 81.25-102.07 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64a308.15 308.15 0 0 0-147.32 37.7L45.46 3.37A16 16 0 0 0 23 6.18L3.37 31.45A16 16 0 0 0 6.18 53.9l588.36 454.73a16 16 0 0 0 22.46-2.81l19.64-25.27a16 16 0 0 0-2.82-22.45zm-183.72-142l-39.3-30.38A94.75 94.75 0 0 0 416 256a94.76 94.76 0 0 0-121.31-92.21A47.65 47.65 0 0 1 304 192a46.64 46.64 0 0 1-1.54 10l-73.61-56.89A142.31 142.31 0 0 1 320 112a143.92 143.92 0 0 1 144 144c0 21.63-5.29 41.79-13.9 60.11z"
+      >
+      </path>
+    </svg>
+  </div>
+</div>