Skip to content

Commit b55be1d

Browse files
authored
Add behavior when entering recovery words (#3471)
* Improve mobile input behavior * Hide content * lowercase automatically * Implement show all and clear all * Toggle all * Remove unnucessary setter
1 parent 5aef37f commit b55be1d

File tree

1 file changed

+70
-6
lines changed
  • src/frontend/src/routes/(new-styling)/recovery-phrase

1 file changed

+70
-6
lines changed

src/frontend/src/routes/(new-styling)/recovery-phrase/+page.svelte

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
type RecoveryWord = {
1212
value: string;
1313
isValid: boolean;
14+
showContent: boolean;
1415
};
1516
1617
const englishWordList = (wordlists.english as string[]) ?? [];
@@ -22,9 +23,12 @@
2223
Array.from({ length: 24 }, () => ({
2324
value: "",
2425
isValid: true,
26+
showContent: false,
2527
})),
2628
);
2729
30+
let showAll = $state(false);
31+
2832
// Flag to prevent double-triggering recovery on multiple blur events
2933
let recoveryInProgress = $state(false);
3034
@@ -137,7 +141,7 @@
137141
pastedWords.forEach((word, i) => {
138142
const targetIndex = currentIndex + i;
139143
if (targetIndex < words.length) {
140-
words[targetIndex].value = word.trim();
144+
words[targetIndex].value = word.trim().toLowerCase();
141145
words[targetIndex].isValid = true;
142146
}
143147
});
@@ -160,6 +164,35 @@
160164
}
161165
};
162166
167+
const toggleAll = () => {
168+
showAll = !showAll;
169+
if (!showAll) {
170+
words.forEach((word) => {
171+
word.showContent = false;
172+
});
173+
}
174+
};
175+
176+
const handleClearAll = () => {
177+
if (submitTimeoutId !== undefined) {
178+
clearTimeout(submitTimeoutId);
179+
submitTimeoutId = undefined;
180+
}
181+
182+
showAll = false;
183+
184+
words.forEach((word) => {
185+
word.value = "";
186+
word.isValid = true;
187+
word.showContent = false;
188+
});
189+
190+
const firstElement = document.getElementById("recovery-phrase-0");
191+
if (nonNullish(firstElement)) {
192+
firstElement.focus();
193+
}
194+
};
195+
163196
// Cleanup timeout on component unmount
164197
$effect(() => {
165198
return () => {
@@ -188,13 +221,36 @@
188221
{#each words as word, i}
189222
<label class="relative h-8">
190223
<!-- Text input -->
224+
<!-- "data-lpignore" Last pass ignore -->
225+
<!-- "data-1p-ignore" 1Password ignore -->
226+
<!-- "data-bwignore" Bitwarden ignore -->
227+
<!-- "data-form-type=other" Non-standard hint to password managers -->
191228
<input
192-
type="text"
229+
type={showAll || word.showContent || !word.isValid
230+
? "text"
231+
: "password"}
232+
inputmode="text"
233+
autocorrect="off"
234+
autocomplete="off"
235+
autocapitalize="off"
236+
spellcheck="false"
193237
id={`recovery-phrase-${i}`}
194-
bind:value={word.value}
238+
value={word.value}
239+
oninput={(event) => {
240+
const target = event.currentTarget as HTMLInputElement;
241+
word.value = target.value.toLowerCase();
242+
}}
195243
onkeydown={(e) => handleKeyDownInput(e, i)}
196244
onpaste={(e) => handlePaste(e, i)}
197-
onblur={() => validateWord(i)}
245+
data-lpignore="true"
246+
data-1p-ignore="true"
247+
data-bwignore="true"
248+
data-form-type="other"
249+
onfocus={() => (word.showContent = true)}
250+
onblur={() => {
251+
validateWord(i);
252+
word.showContent = false;
253+
}}
198254
aria-invalid={!word.isValid}
199255
class={`peer text-text-primary h-8 w-full rounded-full border-none pr-10 pl-10 text-base ring outline-none ring-inset focus:ring-2 ${
200256
word.isValid
@@ -231,8 +287,16 @@
231287
{/each}
232288
</div>
233289
<div class="flex flex-row gap-2">
234-
<Button class="w-full" variant="tertiary">{$t`Show all`}</Button>
235-
<Button class="w-full" variant="tertiary">{$t`Clear all`}</Button>
290+
<Button class="w-full" variant="tertiary" onclick={toggleAll}>
291+
{#if showAll}
292+
{$t`Hide all`}
293+
{:else}
294+
{$t`Show all`}
295+
{/if}
296+
</Button>
297+
<Button class="w-full" variant="tertiary" onclick={handleClearAll}>
298+
{$t`Clear all`}
299+
</Button>
236300
</div>
237301
</div>
238302
<Button size="xl" variant="secondary">{$t`Cancel`}</Button>

0 commit comments

Comments
 (0)