refarcor create & add loading animation
This commit is contained in:
parent
00ea3e37da
commit
38fb64f7a1
|
@ -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>
|
|
@ -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 |
|
@ -7,13 +7,14 @@
|
|||
import { create, PayloadToLargeError } from '$lib/api'
|
||||
import { Crypto, Hex } from '$lib/crypto'
|
||||
import { status } from '$lib/stores/status'
|
||||
import AdvancedParameters from '$lib/ui/AdvancedParameters.svelte'
|
||||
import Button from '$lib/ui/Button.svelte'
|
||||
import FileUpload from '$lib/ui/FileUpload.svelte'
|
||||
import Loader from '$lib/ui/Loader.svelte'
|
||||
import MaxSize from '$lib/ui/MaxSize.svelte'
|
||||
import Result, { type NoteResult } from '$lib/ui/NoteResult.svelte'
|
||||
import Switch from '$lib/ui/Switch.svelte'
|
||||
import TextArea from '$lib/ui/TextArea.svelte'
|
||||
import TextInput from '$lib/ui/TextInput.svelte'
|
||||
|
||||
let note: Note = {
|
||||
contents: '',
|
||||
|
@ -27,7 +28,7 @@
|
|||
let isFile = false
|
||||
let timeExpiration = false
|
||||
let description = ''
|
||||
let loading = false
|
||||
let loading: string | null = null
|
||||
let error: string | null = null
|
||||
|
||||
$: if (!advanced) {
|
||||
|
@ -56,7 +57,7 @@
|
|||
async function submit() {
|
||||
try {
|
||||
error = null
|
||||
loading = true
|
||||
loading = $t('common.encrypting')
|
||||
|
||||
const password = Hex.encode(Crypto.getRandomBytes(32))
|
||||
const key = await Crypto.getKeyFromString(password)
|
||||
|
@ -75,6 +76,7 @@
|
|||
if (timeExpiration) data.expiration = parseInt(note.expiration as any)
|
||||
else data.views = parseInt(note.views as any)
|
||||
|
||||
loading = $t('common.uploading')
|
||||
const response = await create(data)
|
||||
result = {
|
||||
password: password,
|
||||
|
@ -90,7 +92,7 @@
|
|||
error = $t('home.errors.note_error')
|
||||
}
|
||||
} finally {
|
||||
loading = false
|
||||
loading = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -102,7 +104,7 @@
|
|||
{@html $status?.theme_text || $t('home.intro')}
|
||||
</p>
|
||||
<form on:submit|preventDefault={submit}>
|
||||
<fieldset disabled={loading}>
|
||||
<fieldset disabled={loading !== null}>
|
||||
{#if isFile}
|
||||
<FileUpload label={$t('common.file')} bind:files />
|
||||
{:else}
|
||||
|
@ -129,7 +131,7 @@
|
|||
<p>
|
||||
<br />
|
||||
{#if loading}
|
||||
{$t('common.loading')}
|
||||
{loading} <Loader />
|
||||
{:else}
|
||||
{description}
|
||||
{/if}
|
||||
|
@ -138,31 +140,7 @@
|
|||
{#if advanced}
|
||||
<div transition:blur={{ duration: 250 }}>
|
||||
<br />
|
||||
<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>
|
||||
<AdvancedParameters bind:note bind:timeExpiration />
|
||||
</div>
|
||||
{/if}
|
||||
</fieldset>
|
||||
|
@ -184,15 +162,7 @@
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
.middle-switch {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.fields {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
import { get, info } from '$lib/api'
|
||||
import { Crypto } from '$lib/crypto'
|
||||
import Button from '$lib/ui/Button.svelte'
|
||||
import Loader from '$lib/ui/Loader.svelte'
|
||||
import ShowNote, { type DecryptedNote } from '$lib/ui/ShowNote.svelte'
|
||||
|
||||
export let id: string
|
||||
|
@ -24,20 +25,20 @@
|
|||
let note: DecryptedNote | null = null
|
||||
let exists = false
|
||||
|
||||
let loading = true
|
||||
let loading: string | null = null
|
||||
let error: string | null = null
|
||||
|
||||
onMount(async () => {
|
||||
// Check if note exists
|
||||
try {
|
||||
loading = true
|
||||
loading = $t('common.loading')
|
||||
password = window.location.hash.slice(1)
|
||||
await info(id)
|
||||
exists = true
|
||||
} catch {
|
||||
exists = false
|
||||
} finally {
|
||||
loading = false
|
||||
loading = null
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -47,8 +48,9 @@
|
|||
async function show() {
|
||||
try {
|
||||
error = null
|
||||
loading = true
|
||||
loading = $t('common.downloading')
|
||||
const data = await get(id)
|
||||
loading = $t('common.decrypting')
|
||||
const key = await Crypto.getKeyFromString(password)
|
||||
switch (data.meta.type) {
|
||||
case 'text':
|
||||
|
@ -70,7 +72,7 @@
|
|||
} catch {
|
||||
error = $t('show.errors.decryption_failed')
|
||||
} finally {
|
||||
loading = false
|
||||
loading = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -97,5 +99,11 @@
|
|||
{/if}
|
||||
{/if}
|
||||
{#if loading}
|
||||
<p>{$t('common.loading')}</p>
|
||||
<p class="loader">{loading} <Loader /></p>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.loader {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue