Add welcome modal with data persistence permission prompt
This commit is contained in:
		
							parent
							
								
									70f3f31370
								
							
						
					
					
						commit
						ea345e6e61
					
				|  | @ -1,11 +1,14 @@ | |||
| <script lang="ts"> | ||||
| 	import Button from './button.svelte'; | ||||
| 	import FaXmark from '$icon/fa-xmark.svelte'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 
 | ||||
| 	export let open: boolean; | ||||
| 	export let title: string; | ||||
| 	export let size: 'sm' | 'md' | 'lg' = 'md'; | ||||
| 
 | ||||
| 	const dispatch = createEventDispatcher(); | ||||
| 
 | ||||
| 	const maxWidths = { | ||||
| 		sm: '400px', | ||||
| 		md: '700px', | ||||
|  | @ -20,6 +23,7 @@ | |||
| 
 | ||||
| 	function close() { | ||||
| 		open = false; | ||||
| 		dispatch('close'); | ||||
| 	} | ||||
| 
 | ||||
| 	function escape(event: KeyboardEvent) { | ||||
|  | @ -47,7 +51,7 @@ | |||
| 	.app-modal { | ||||
| 		article { | ||||
| 			max-width: var(--max-width, none); | ||||
| 			flex: 1 0 auto; | ||||
| 			flex: 1 0 0; | ||||
| 		} | ||||
| 
 | ||||
| 		header { | ||||
|  |  | |||
|  | @ -0,0 +1,33 @@ | |||
| <script lang="ts"> | ||||
| 	import { onMount } from 'svelte'; | ||||
| 	import Modal from './modal.svelte'; | ||||
| 	import Button from './button.svelte'; | ||||
| 	import { persistence } from '$lib/stores'; | ||||
| 
 | ||||
| 	let open = false; | ||||
| 
 | ||||
| 	onMount(() => { | ||||
| 		if (!persistence.prompted) { | ||||
| 			open = true; | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	function close() { | ||||
| 		persistence.prompt(); | ||||
| 		open = false; | ||||
| 	} | ||||
| </script> | ||||
| 
 | ||||
| <Modal title="Welcome!" size="sm" bind:open on:close={close}> | ||||
| 	<p> | ||||
| 		Capture your thoughts for later by writing a quick note. Add tags to categorize it and organize | ||||
| 		your notes. | ||||
| 	</p> | ||||
| 	<p> | ||||
| 		This app keeps all of its data on your device. Your notes are private, never sent to an external | ||||
| 		server. | ||||
| 	</p> | ||||
| 	<footer> | ||||
| 		<Button on:click={close}>Get Started</Button> | ||||
| 	</footer> | ||||
| </Modal> | ||||
|  | @ -3,10 +3,12 @@ import { NotesStore } from './notes'; | |||
| import { ThemeStore, type Theme } from './theme'; | ||||
| import { TagsStore } from './tags'; | ||||
| import { SettingsStore } from './settings'; | ||||
| import { PersistenceStore } from './persistence'; | ||||
| 
 | ||||
| export const tags = new TagsStore(); | ||||
| export const notes = new NotesStore(tags); | ||||
| 
 | ||||
| export const persistence = new PersistenceStore(); | ||||
| export const settings = new SettingsStore(); | ||||
| 
 | ||||
| export const theme = new ThemeStore(); | ||||
|  |  | |||
|  | @ -0,0 +1,39 @@ | |||
| import { writable, type Readable } from 'svelte/store'; | ||||
| 
 | ||||
| export class PersistenceStore implements Readable<boolean | null> { | ||||
| 	private persistence = writable<boolean | null>(null); | ||||
| 
 | ||||
| 	get prompted() { | ||||
| 		return !!localStorage.promptedForPersistence; | ||||
| 	} | ||||
| 	private set prompted(value: boolean) { | ||||
| 		localStorage.promptedForPersistence = value; | ||||
| 	} | ||||
| 
 | ||||
| 	constructor() { | ||||
| 		this.check(); | ||||
| 	} | ||||
| 
 | ||||
| 	subscribe = this.persistence.subscribe; | ||||
| 
 | ||||
| 	async check() { | ||||
| 		if (navigator.storage && navigator.storage.persisted) { | ||||
| 			let persisted: boolean | null = await navigator.storage.persisted(); | ||||
| 
 | ||||
| 			if (persisted !== true) { | ||||
| 				persisted = this.prompted ? false : null; | ||||
| 			} | ||||
| 
 | ||||
| 			this.persistence.set(persisted); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	async prompt() { | ||||
| 		this.prompted = true; | ||||
| 
 | ||||
| 		if (navigator.storage && navigator.storage.persist) { | ||||
| 			const persisted = await navigator.storage.persist(); | ||||
| 			this.persistence.set(persisted); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -5,6 +5,7 @@ | |||
| 	import NoteListPlaceholder from '$lib/components/notes/note-list-placeholder.svelte'; | ||||
| 	import NoteList from '$lib/components/notes/note-list.svelte'; | ||||
| 	import SettingsModal from '$lib/components/settings/settings-modal.svelte'; | ||||
| 	import WelcomeModal from '$lib/components/welcome-modal.svelte'; | ||||
| 	import { notes, tags } from '$lib/stores'; | ||||
| 
 | ||||
| 	const notesCount = notes.count; | ||||
|  | @ -24,6 +25,7 @@ | |||
| 		<NoteAddButton /> | ||||
| 	</section> | ||||
| </main> | ||||
| <WelcomeModal /> | ||||
| <SettingsModal /> | ||||
| 
 | ||||
| <style lang="scss"> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue