From a67f9cbc9f609aa56e445fe8f422ba3be14e9345 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 21 Oct 2022 21:18:10 -0700 Subject: pin code input --- src/routes/[username]/settings/+page.server.js | 4 +- src/routes/[username]/settings/+page.svelte | 28 +++++-- src/routes/[username]/settings/_account.svelte | 18 +++- src/routes/[username]/settings/_security.svelte | 104 +++++++++++++++++++----- 4 files changed, 123 insertions(+), 31 deletions(-) (limited to 'src/routes') diff --git a/src/routes/[username]/settings/+page.server.js b/src/routes/[username]/settings/+page.server.js index 7053a939..deb4356e 100644 --- a/src/routes/[username]/settings/+page.server.js +++ b/src/routes/[username]/settings/+page.server.js @@ -3,9 +3,11 @@ import { auth, get, post } from '$lib/utils'; export const actions = { default: async ({ cookies, request }) => { + let form = Object.fromEntries(await request.formData()) + let user = { ...(await get('/me', auth(cookies))), - ...Object.fromEntries(await request.formData()) + ...form }; try { diff --git a/src/routes/[username]/settings/+page.svelte b/src/routes/[username]/settings/+page.svelte index c1ac20d0..a584fc56 100644 --- a/src/routes/[username]/settings/+page.svelte +++ b/src/routes/[username]/settings/+page.svelte @@ -4,7 +4,7 @@ import Pos from './_pos.svelte'; import Security from './_security.svelte'; - import { Icon } from '$comp'; + import { Icon, Spinner } from '$comp'; import { t } from '$lib/translations'; import { failure, success } from '$lib/utils'; import { avatarUpload, bannerUpload } from '$lib/store'; @@ -26,19 +26,29 @@ $: ({ comp } = tabs.find((t) => t.name === tab)); - let save = async () => { + let loading, submit; + let save = async (msg) => { + loading = true; + if (typeof msg !== 'string') msg = 'Settings saved'; + + console.log("SAVING ONCE") + try { if ($avatarUpload) { await upload($avatarUpload.file, $avatarUpload.type, $avatarUpload.progress, token); } + if ($bannerUpload) { await upload($bannerUpload.file, $bannerUpload.type, $bannerUpload.progress, token); } - success('Settings saved'); + + success(msg); } catch (e) { console.log(e); failure('Something went wrong'); } + + loading = false; }; @@ -58,16 +68,22 @@ {/each} - +
diff --git a/src/routes/[username]/settings/_account.svelte b/src/routes/[username]/settings/_account.svelte index 10756c7a..d7ab9f5e 100644 --- a/src/routes/[username]/settings/_account.svelte +++ b/src/routes/[username]/settings/_account.svelte @@ -17,6 +17,7 @@ $: banner = files.banner.src; $: $tempProfileFiles = { profile: files.profile.src, banner: files.banner.src }; + let togglePassword = () => (revealPassword = !revealPassword); let colorThemes = [ { theme: 1, color1: 'from-[#F5F7FA]', color2: 'to-[#C3CFE2]' }, { theme: 2, color1: 'from-[#FDFCFB]', color2: 'to-[#E2D1C3]' }, @@ -88,7 +89,8 @@ {/if} select('profile')} + on:keydown={() => select('profile')} + >Select select('banner')} + on:keydown={() => select('banner')} alt="Banner" /> {:else if user.banner} @@ -197,12 +205,14 @@ src={`/api/public/${user.username}-banner.webp`} class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80" on:click={() => select('banner')} + on:keydown={() => select('banner')} alt="Banner" /> {:else}
select('banner')} + on:keydown={() => select('banner')} alt="Banner" /> {/if} @@ -211,7 +221,8 @@ select('banner')} + on:keydown={() => select('banner')}>Select handleThemeClick(colors)} + on:keydown={() => handleThemeClick(colors)} /> {/each}
--> diff --git a/src/routes/[username]/settings/_security.svelte b/src/routes/[username]/settings/_security.svelte index 2a490aa4..a74517aa 100644 --- a/src/routes/[username]/settings/_security.svelte +++ b/src/routes/[username]/settings/_security.svelte @@ -5,25 +5,75 @@ import { Pincode, PincodeInput } from 'svelte-pincode'; import { post, success, failure } from '$lib/utils'; - export let user; + export let user, submit; let settingPin, setting2fa, disabling2fa; - let code = []; - let pin = ''; let token = ''; - let tokenInput, pinInput; + let pinCode = []; + let verifyCode = []; + let tokenInput, pinInput, verifyInput; + let verifying = false; + let startVerifying = () => { + verifying = true; + }; + + $: pin = pinCode.join(''); + + let locked; + $: verifyCode.join('').length > 5 && checkPin(); + let checkPin = async () => { + if (locked) return; + locked = true; + + let verify = verifyCode.join(''); + + pinCode = ['', '', '', '', '', '']; + verifyCode = ['', '', '', '', '', '']; + settingPin = false; + + try { + if (pin.length > 5 && pin === verify) { + user.pin = pin; + submit.click(); + } else { + failure('Pin mismatch, try again'); + settingPin = true; + pinInput.focusFirstInput(); + } + } catch (e) { + failure('Problem setting PIN'); + } + + verifying = false; + + await new Promise((r) => setTimeout(r, 500)); + locked = false; + }; + + $: if (verifying) verifyInput && tick().then(verifyInput.focusFirstInput); $: if (settingPin) pinInput && tick().then(pinInput.focusFirstInput); - $: if (setting2fa || disabling2fa) tokenInput && tick().then(tokenInput.focusFirstInput); + $: if (setting2fa || disabling2fa) tokenInput && tick().then(tokenInput?.focusFirstInput); let reset = () => { token = ''; - code = []; return true; }; - let togglePin = () => (settingPin = !settingPin); + let togglePin = async () => { + if (user.pin) { + try { + user.pin = null; + submit.click(); + } catch (e) { + failure('Failed to disable pin'); + } + } else { + settingPin = true; + } + }; + let toggleEnabling = () => reset() && (setting2fa = !setting2fa); let toggleDisabling = () => reset() && (disabling2fa = !disabling2fa); @@ -58,31 +108,43 @@ $: otpUri = `otpauth://totp/coinos:${user.username}?secret=${user.otpsecret}&period=30&digits=6&algorithm=SHA1&issuer=coinos`; - +