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 { 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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue