Add initialization error toasts (#24)
* Add error, success, info, and warning styles * Add Toast component * Add initialization error toast * Add device store and toast placement * Set device on window resize events Co-authored-by: Brian Ginsburg <gins@brianginsburg.com> Co-authored-by: Jess Martin <jessmartin@gmail.com>
This commit is contained in:
parent
046c80be44
commit
2d25466f93
|
|
@ -8,7 +8,7 @@
|
|||
"name": "svelte-elemetary-template",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"webnative": "0.33.0-alpha-3"
|
||||
"webnative": "0.33.0-alpha-4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-static": "1.0.0-next.36",
|
||||
|
|
@ -4679,9 +4679,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webnative": {
|
||||
"version": "0.33.0-alpha-3",
|
||||
"resolved": "https://registry.npmjs.org/webnative/-/webnative-0.33.0-alpha-3.tgz",
|
||||
"integrity": "sha512-fx7ZNk1eKdt88RHG90fKg99xhBKsPIizOEgggr0HYrbM9G9O4vXGabt48QQF6K9pTuZmrrSW/RyqR/bxCHRc6A==",
|
||||
"version": "0.33.0-alpha-4",
|
||||
"resolved": "https://registry.npmjs.org/webnative/-/webnative-0.33.0-alpha-4.tgz",
|
||||
"integrity": "sha512-P7TH9uwh31IS8PjHaRD74wQRjmVu1qiHnMwkjr2x0FiUixUwbrkvumL4qergeCIKQj//ZrrnkCZhebJ1efaylQ==",
|
||||
"dependencies": {
|
||||
"@ipld/dag-cbor": "^7.0.0",
|
||||
"@ipld/dag-pb": "^2.1.15",
|
||||
|
|
@ -8069,9 +8069,9 @@
|
|||
"peer": true
|
||||
},
|
||||
"webnative": {
|
||||
"version": "0.33.0-alpha-3",
|
||||
"resolved": "https://registry.npmjs.org/webnative/-/webnative-0.33.0-alpha-3.tgz",
|
||||
"integrity": "sha512-fx7ZNk1eKdt88RHG90fKg99xhBKsPIizOEgggr0HYrbM9G9O4vXGabt48QQF6K9pTuZmrrSW/RyqR/bxCHRc6A==",
|
||||
"version": "0.33.0-alpha-4",
|
||||
"resolved": "https://registry.npmjs.org/webnative/-/webnative-0.33.0-alpha-4.tgz",
|
||||
"integrity": "sha512-P7TH9uwh31IS8PjHaRD74wQRjmVu1qiHnMwkjr2x0FiUixUwbrkvumL4qergeCIKQj//ZrrnkCZhebJ1efaylQ==",
|
||||
"requires": {
|
||||
"@ipld/dag-cbor": "^7.0.0",
|
||||
"@ipld/dag-pb": "^2.1.15",
|
||||
|
|
|
|||
|
|
@ -50,6 +50,6 @@
|
|||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"webnative": "0.33.0-alpha-3"
|
||||
"webnative": "0.33.0-alpha-4"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,12 +88,12 @@
|
|||
/>
|
||||
{/if}
|
||||
{#if !(username.length === 0) && usernameAvailable && usernameValid && !checkingUsername}
|
||||
<span class="w-4 h-4 block absolute top-4 right-4">
|
||||
<span class="w-4 h-4 block absolute top-5 right-4">
|
||||
<CheckIcon />
|
||||
</span>
|
||||
{/if}
|
||||
{#if !(username.length === 0) && !checkingUsername && !(usernameAvailable && usernameValid)}
|
||||
<span class="w-4 h-4 block absolute top-4 right-4">
|
||||
<span class="w-4 h-4 block absolute top-5 right-4">
|
||||
<XIcon />
|
||||
</span>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<svg
|
||||
width="28px"
|
||||
height="28px"
|
||||
viewBox="0 0 28 28"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g fill="none" fill-rule="nonzero">
|
||||
<path
|
||||
d="M4.03033009,13.4696699 C3.73743687,13.1767767 3.26256313,13.1767767 2.96966991,13.4696699 C2.6767767,13.7625631 2.6767767,14.2374369 2.96966991,14.5303301 L9.96966991,21.5303301 C10.2625631,21.8232233 10.7374369,21.8232233 11.0303301,21.5303301 L25.0303301,7.53033009 C25.3232233,7.23743687 25.3232233,6.76256313 25.0303301,6.46966991 C24.7374369,6.1767767 24.2625631,6.1767767 23.9696699,6.46966991 L10.5,19.9393398 L4.03033009,13.4696699 Z"
|
||||
fill="#14532d"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 788 B |
|
|
@ -0,0 +1,14 @@
|
|||
<svg
|
||||
width="15px"
|
||||
height="15px"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M6.7929 7.49998L1.14645 1.85353L1.85356 1.14642L7.50001 6.79287L13.1465 1.14642L13.8536 1.85353L8.20711 7.49998L13.8536 13.1464L13.1465 13.8535L7.50001 8.20708L1.85356 13.8535L1.14645 13.1464L6.7929 7.49998Z"
|
||||
fill="#7f1d1d"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 414 B |
|
|
@ -0,0 +1,36 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { quintOut } from 'svelte/easing'
|
||||
import { fade } from 'svelte/transition'
|
||||
|
||||
import CheckThinIcon from '$components/icons/CheckThinIcon.svelte'
|
||||
import XThinIcon from '$components/icons/XThinIcon.svelte'
|
||||
|
||||
export let kind: 'success' | 'error'
|
||||
export let message: string
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const clearNotification = () => {
|
||||
dispatch('clear')
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="toast"
|
||||
on:click={clearNotification}
|
||||
out:fade={{ duration: 800, easing: quintOut }}
|
||||
>
|
||||
<div
|
||||
class="alert {kind === 'success' ? 'alert-success' : 'alert-error'} text-sm"
|
||||
>
|
||||
<div>
|
||||
{#if kind === 'success'}
|
||||
<CheckThinIcon />
|
||||
{:else if kind === 'error'}
|
||||
<XThinIcon />
|
||||
{/if}
|
||||
<span class="pl-1">{message}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export type Device = {
|
||||
isMobile: boolean
|
||||
}
|
||||
|
|
@ -2,5 +2,17 @@ export type Session = {
|
|||
username: string
|
||||
authed: boolean
|
||||
loading: boolean
|
||||
error?: 'Insecure Context' | 'Unsupported Browser'
|
||||
}
|
||||
error?: SessionError
|
||||
}
|
||||
|
||||
type SessionError = 'Insecure Context' | 'Unsupported Browser'
|
||||
|
||||
export const errorToMessage = (error: SessionError): string => {
|
||||
switch (error) {
|
||||
case 'Insecure Context':
|
||||
return 'This application requires a secure context (HTTPS)'
|
||||
|
||||
case 'Unsupported Browser':
|
||||
return 'Your browser does not support this application'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,63 @@
|
|||
<script lang="ts">
|
||||
import { get } from 'svelte/store'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
import '../global.css'
|
||||
import { initialize } from '$lib/common/webnative'
|
||||
import { sessionStore, theme } from '../stores'
|
||||
import { deviceStore, sessionStore, theme } from '../stores'
|
||||
import { storeTheme } from '$lib/theme'
|
||||
import { errorToMessage, type Session } from '$lib/session'
|
||||
import Toast from '$components/notifications/Toast.svelte'
|
||||
import Header from '$components/Header.svelte'
|
||||
|
||||
let session: Session = null
|
||||
|
||||
theme.subscribe(val => {
|
||||
storeTheme(val)
|
||||
})
|
||||
|
||||
sessionStore.subscribe(val => {
|
||||
session = val
|
||||
})
|
||||
|
||||
onMount(() => { setDevice() })
|
||||
|
||||
const setDevice = () => {
|
||||
if (window.innerWidth <= 768) {
|
||||
deviceStore.set({ isMobile: true })
|
||||
} else {
|
||||
deviceStore.set({ isMobile: false })
|
||||
}
|
||||
}
|
||||
|
||||
const init = async () => {
|
||||
await initialize()
|
||||
|
||||
// TODO: Remove this debugging statement
|
||||
const session = get(sessionStore)
|
||||
console.log('session at init', session)
|
||||
}
|
||||
|
||||
const clearNotification = () => {
|
||||
sessionStore.update(session => ({
|
||||
...session,
|
||||
error: null
|
||||
}))
|
||||
}
|
||||
|
||||
init()
|
||||
</script>
|
||||
|
||||
<svelte:window on:resize={setDevice} />
|
||||
|
||||
<div data-theme={$theme}>
|
||||
<Header />
|
||||
|
||||
{#if session.error}
|
||||
<Toast
|
||||
kind="error"
|
||||
message={errorToMessage(session.error)}
|
||||
on:clear={clearNotification}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import type { Writable } from 'svelte/store'
|
|||
import type FileSystem from 'webnative/fs/index'
|
||||
|
||||
import { loadTheme } from '$lib/theme'
|
||||
import type { Device } from '$lib/device'
|
||||
import type { Session } from '$lib/session'
|
||||
import type { Theme } from '$lib/theme'
|
||||
|
||||
|
|
@ -14,4 +15,6 @@ export const sessionStore: Writable<Session> = writable({
|
|||
loading: true
|
||||
})
|
||||
|
||||
export const filesystemStore: Writable<FileSystem | null> = writable(null)
|
||||
export const filesystemStore: Writable<FileSystem | null> = writable(null)
|
||||
|
||||
export const deviceStore: Writable<Device> = writable({ isMobile: true })
|
||||
|
|
@ -11,6 +11,10 @@ module.exports = {
|
|||
secondary: "#30aadd",
|
||||
accent: "#00ffc6",
|
||||
neutral: "#282828",
|
||||
info: "#bfdbfe",
|
||||
success: "#bbf7d0",
|
||||
warning: "#fdba74",
|
||||
error: "#fecaca",
|
||||
"base-content": "#ffffff",
|
||||
"base-100": "#111111",
|
||||
"--rounded-box": "16px",
|
||||
|
|
@ -24,6 +28,10 @@ module.exports = {
|
|||
secondary: "#30aadd",
|
||||
accent: "#00ffc6",
|
||||
neutral: "#e5e5e5",
|
||||
info: "#bfdbfe",
|
||||
success: "#bbf7d0",
|
||||
warning: "#fdba74",
|
||||
error: "#fecaca",
|
||||
"base-content": "#000000",
|
||||
"base-100": "#ffffff",
|
||||
"--rounded-box": "16px",
|
||||
|
|
|
|||
Loading…
Reference in New Issue