refarcor create & add loading animation

This commit is contained in:
cupcakearmy 2022-07-19 10:26:51 +02:00
parent 00ea3e37da
commit 38fb64f7a1
No known key found for this signature in database
GPG Key ID: 3235314B4D31232F
4 changed files with 111 additions and 45 deletions

View File

@ -0,0 +1,47 @@
<script lang="ts">
import { t } from 'svelte-intl-precompile'
import type { Note } from '$lib/api'
import { status } from '$lib/stores/status'
import Switch from '$lib/ui/Switch.svelte'
import TextInput from '$lib/ui/TextInput.svelte'
export let note: Note
export let timeExpiration = false
</script>
<div class="fields">
<TextInput
type="number"
label={$t('common.views', { values: { n: 0 } })}
bind:value={note.views}
disabled={timeExpiration}
max={$status?.max_views}
validate={(v) =>
($status && v < $status?.max_views) ||
$t('home.errors.max', { values: { n: $status?.max_views ?? 0 } })}
/>
<div class="middle-switch">
<Switch label={$t('common.mode')} bind:value={timeExpiration} color={false} />
</div>
<TextInput
type="number"
label={$t('common.minutes', { values: { n: 0 } })}
bind:value={note.expiration}
disabled={!timeExpiration}
max={$status?.max_expiration}
validate={(v) =>
($status && v < $status?.max_expiration) ||
$t('home.errors.max', { values: { n: $status?.max_expiration ?? 0 } })}
/>
</div>
<style>
.middle-switch {
margin: 0 1rem;
}
.fields {
display: flex;
}
</style>

View File

@ -0,0 +1,41 @@
<svg
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 100 100"
xml:space="preserve"
>
<rect fill="none" stroke="currentColor" stroke-width="4" x="25" y="25" width="50" height="50">
<animateTransform
attributeName="transform"
dur="0.5s"
from="0 50 50"
to="180 50 50"
type="rotate"
id="strokeBox"
attributeType="XML"
begin="rectBox.end"
/>
</rect>
<rect x="27" y="27" fill="currentColor" width="46" height="50">
<animate
attributeName="height"
dur="1.3s"
attributeType="XML"
from="50"
to="0"
id="rectBox"
fill="freeze"
begin="0s;strokeBox.end"
/>
</rect>
</svg>
<style>
svg {
height: 2em;
position: relative;
top: 0.6em;
pointer-events: none;
}
</style>

After

Width:  |  Height:  |  Size: 784 B

View File

@ -7,13 +7,14 @@
import { create, PayloadToLargeError } from '$lib/api' import { create, PayloadToLargeError } from '$lib/api'
import { Crypto, Hex } from '$lib/crypto' import { Crypto, Hex } from '$lib/crypto'
import { status } from '$lib/stores/status' import { status } from '$lib/stores/status'
import AdvancedParameters from '$lib/ui/AdvancedParameters.svelte'
import Button from '$lib/ui/Button.svelte' import Button from '$lib/ui/Button.svelte'
import FileUpload from '$lib/ui/FileUpload.svelte' import FileUpload from '$lib/ui/FileUpload.svelte'
import Loader from '$lib/ui/Loader.svelte'
import MaxSize from '$lib/ui/MaxSize.svelte' import MaxSize from '$lib/ui/MaxSize.svelte'
import Result, { type NoteResult } from '$lib/ui/NoteResult.svelte' import Result, { type NoteResult } from '$lib/ui/NoteResult.svelte'
import Switch from '$lib/ui/Switch.svelte' import Switch from '$lib/ui/Switch.svelte'
import TextArea from '$lib/ui/TextArea.svelte' import TextArea from '$lib/ui/TextArea.svelte'
import TextInput from '$lib/ui/TextInput.svelte'
let note: Note = { let note: Note = {
contents: '', contents: '',
@ -27,7 +28,7 @@
let isFile = false let isFile = false
let timeExpiration = false let timeExpiration = false
let description = '' let description = ''
let loading = false let loading: string | null = null
let error: string | null = null let error: string | null = null
$: if (!advanced) { $: if (!advanced) {
@ -56,7 +57,7 @@
async function submit() { async function submit() {
try { try {
error = null error = null
loading = true loading = $t('common.encrypting')
const password = Hex.encode(Crypto.getRandomBytes(32)) const password = Hex.encode(Crypto.getRandomBytes(32))
const key = await Crypto.getKeyFromString(password) const key = await Crypto.getKeyFromString(password)
@ -75,6 +76,7 @@
if (timeExpiration) data.expiration = parseInt(note.expiration as any) if (timeExpiration) data.expiration = parseInt(note.expiration as any)
else data.views = parseInt(note.views as any) else data.views = parseInt(note.views as any)
loading = $t('common.uploading')
const response = await create(data) const response = await create(data)
result = { result = {
password: password, password: password,
@ -90,7 +92,7 @@
error = $t('home.errors.note_error') error = $t('home.errors.note_error')
} }
} finally { } finally {
loading = false loading = null
} }
} }
</script> </script>
@ -102,7 +104,7 @@
{@html $status?.theme_text || $t('home.intro')} {@html $status?.theme_text || $t('home.intro')}
</p> </p>
<form on:submit|preventDefault={submit}> <form on:submit|preventDefault={submit}>
<fieldset disabled={loading}> <fieldset disabled={loading !== null}>
{#if isFile} {#if isFile}
<FileUpload label={$t('common.file')} bind:files /> <FileUpload label={$t('common.file')} bind:files />
{:else} {:else}
@ -129,7 +131,7 @@
<p> <p>
<br /> <br />
{#if loading} {#if loading}
{$t('common.loading')} {loading} <Loader />
{:else} {:else}
{description} {description}
{/if} {/if}
@ -138,31 +140,7 @@
{#if advanced} {#if advanced}
<div transition:blur={{ duration: 250 }}> <div transition:blur={{ duration: 250 }}>
<br /> <br />
<div class="fields"> <AdvancedParameters bind:note bind:timeExpiration />
<TextInput
type="number"
label={$t('common.views', { values: { n: 0 } })}
bind:value={note.views}
disabled={timeExpiration}
max={$status?.max_views}
validate={(v) =>
($status && v < $status?.max_views) ||
$t('home.errors.max', { values: { n: $status?.max_views ?? 0 } })}
/>
<div class="middle-switch">
<Switch label={$t('common.mode')} bind:value={timeExpiration} color={false} />
</div>
<TextInput
type="number"
label={$t('common.minutes', { values: { n: 0 } })}
bind:value={note.expiration}
disabled={!timeExpiration}
max={$status?.max_expiration}
validate={(v) =>
($status && v < $status?.max_expiration) ||
$t('home.errors.max', { values: { n: $status?.max_expiration ?? 0 } })}
/>
</div>
</div> </div>
{/if} {/if}
</fieldset> </fieldset>
@ -184,15 +162,7 @@
flex: 1; flex: 1;
} }
.middle-switch {
margin: 0 1rem;
}
.error-text { .error-text {
margin-top: 0.5rem; margin-top: 0.5rem;
} }
.fields {
display: flex;
}
</style> </style>

View File

@ -16,6 +16,7 @@
import { get, info } from '$lib/api' import { get, info } from '$lib/api'
import { Crypto } from '$lib/crypto' import { Crypto } from '$lib/crypto'
import Button from '$lib/ui/Button.svelte' import Button from '$lib/ui/Button.svelte'
import Loader from '$lib/ui/Loader.svelte'
import ShowNote, { type DecryptedNote } from '$lib/ui/ShowNote.svelte' import ShowNote, { type DecryptedNote } from '$lib/ui/ShowNote.svelte'
export let id: string export let id: string
@ -24,20 +25,20 @@
let note: DecryptedNote | null = null let note: DecryptedNote | null = null
let exists = false let exists = false
let loading = true let loading: string | null = null
let error: string | null = null let error: string | null = null
onMount(async () => { onMount(async () => {
// Check if note exists // Check if note exists
try { try {
loading = true loading = $t('common.loading')
password = window.location.hash.slice(1) password = window.location.hash.slice(1)
await info(id) await info(id)
exists = true exists = true
} catch { } catch {
exists = false exists = false
} finally { } finally {
loading = false loading = null
} }
}) })
@ -47,8 +48,9 @@
async function show() { async function show() {
try { try {
error = null error = null
loading = true loading = $t('common.downloading')
const data = await get(id) const data = await get(id)
loading = $t('common.decrypting')
const key = await Crypto.getKeyFromString(password) const key = await Crypto.getKeyFromString(password)
switch (data.meta.type) { switch (data.meta.type) {
case 'text': case 'text':
@ -70,7 +72,7 @@
} catch { } catch {
error = $t('show.errors.decryption_failed') error = $t('show.errors.decryption_failed')
} finally { } finally {
loading = false loading = null
} }
} }
</script> </script>
@ -97,5 +99,11 @@
{/if} {/if}
{/if} {/if}
{#if loading} {#if loading}
<p>{$t('common.loading')}</p> <p class="loader">{loading} <Loader /></p>
{/if} {/if}
<style>
.loader {
text-align: center;
}
</style>