Add modal for note detail

This commit is contained in:
Jonathan Staab 2022-11-25 08:54:38 -08:00
parent 9a929ce78d
commit fef1aa6ce3
7 changed files with 56 additions and 8 deletions

View File

@ -4,10 +4,15 @@
import {onMount} from "svelte" import {onMount} from "svelte"
import {writable} from "svelte/store" import {writable} from "svelte/store"
import {fly} from "svelte/transition" import {fly, fade} from "svelte/transition"
import {cubicInOut} from "svelte/easing"
import {Router, Route, links, navigate} from "svelte-routing" import {Router, Route, links, navigate} from "svelte-routing"
import {globalHistory} from "svelte-routing/src/history"
import {hasParent} from 'src/util/html'
import {store as toast} from "src/state/toast" import {store as toast} from "src/state/toast"
import {modal} from "src/state/app"
import {user} from 'src/state/user' import {user} from 'src/state/user'
import NoteDetail from "src/partials/NoteDetail.svelte"
import NotFound from "src/routes/NotFound.svelte" import NotFound from "src/routes/NotFound.svelte"
import Notes from "src/routes/Notes.svelte" import Notes from "src/routes/Notes.svelte"
import Login from "src/routes/Login.svelte" import Login from "src/routes/Login.svelte"
@ -31,11 +36,16 @@
export let url = "" export let url = ""
onMount(() => { onMount(() => {
// Close menu on click outside
document.querySelector("html").addEventListener("click", e => { document.querySelector("html").addEventListener("click", e => {
if (e.target !== menuIcon) { if (e.target !== menuIcon) {
menuIsOpen.set(false) menuIsOpen.set(false)
} }
}) })
globalHistory.listen(() => {
modal.set(null)
})
}) })
// Give the animation a moment to finish // Give the animation a moment to finish
@ -47,6 +57,8 @@
} }
</script> </script>
<svelte:body on:keydown={e => e.key === 'Escape' && modal.set(null)} />
<Router {url}> <Router {url}>
<div use:links class="h-full"> <div use:links class="h-full">
<div class="pt-16 text-white h-full"> <div class="pt-16 text-white h-full">
@ -127,6 +139,22 @@
<h1 class="staatliches text-3xl">Coracle</h1> <h1 class="staatliches text-3xl">Coracle</h1>
</div> </div>
{#if $modal}
<div class="fixed inset-0">
<div
class="absolute inset-0 opacity-75 bg-black cursor-pointer"
transition:fade
on:click={e => modal.set(null)} />
<div class="absolute inset-0 mt-20 sm:mt-32 modal-content" transition:fly={{y: 1000, opacity: 1}}>
<dialog open class="bg-dark border-t border-solid border-medium h-full w-full">
{#if $modal.note}
<NoteDetail note={$modal.note} />
{/if}
</dialog>
</div>
</div>
{/if}
{#if $toast} {#if $toast}
<div <div
class="fixed bottom-0 left-0 right-0 pointer-events-none" class="fixed bottom-0 left-0 right-0 pointer-events-none"

View File

@ -1,17 +1,19 @@
<script> <script>
import cx from 'classnames'
import {fly} from 'svelte/transition' import {fly} from 'svelte/transition'
import {navigate} from 'svelte-routing' import {navigate} from 'svelte-routing'
import {ellipsize} from 'hurdak/src/core' import {ellipsize} from 'hurdak/src/core'
import {hasParent} from 'src/util/html' import {hasParent} from 'src/util/html'
import {accounts} from "src/state/app" import {accounts, modal} from "src/state/app"
import {formatTimestamp} from 'src/util/misc' import {formatTimestamp} from 'src/util/misc'
import UserBadge from "src/partials/UserBadge.svelte" import UserBadge from "src/partials/UserBadge.svelte"
export let note export let note
export let interactive = false
const onClick = e => { const onClick = e => {
if (!['I'].includes(e.target.tagName) && !hasParent('a', e.target)) { if (!['I'].includes(e.target.tagName) && !hasParent('a', e.target)) {
navigate(`/notes/${note.id}`) modal.set({note})
} }
} }
</script> </script>
@ -19,7 +21,10 @@
<li <li
in:fly={{y: 20}} in:fly={{y: 20}}
on:click={onClick} on:click={onClick}
class="py-2 px-3 chat-message flex flex-col gap-2 hover:bg-dark border border-solid border-black hover:border-medium transition-all cursor-pointer"> class={cx("py-2 px-3 flex flex-col gap-2 text-white", {
"hover:bg-dark transition-all cursor-pointer": interactive,
"border border-solid border-black hover:border-medium": interactive,
})}>
<div class="flex gap-4 items-center justify-between"> <div class="flex gap-4 items-center justify-between">
<UserBadge user={$accounts[note.pubkey]} /> <UserBadge user={$accounts[note.pubkey]} />
<p class="text-sm text-light">{formatTimestamp(note.created_at)}</p> <p class="text-sm text-light">{formatTimestamp(note.created_at)}</p>

View File

@ -0,0 +1,13 @@
<script>
import {onMount} from 'svelte'
import {ensureAccount} from 'src/state/app'
import Note from 'src/partials/Note.svelte'
export let note
onMount(() => {
ensureAccount(note.account)
})
</script>
<Note note={note} />

View File

@ -34,7 +34,7 @@
<ul class="py-8 flex flex-col gap-4 max-w-xl m-auto"> <ul class="py-8 flex flex-col gap-4 max-w-xl m-auto">
{#each reverse(notes) as n} {#each reverse(notes) as n}
<Note note={n} /> <Note interactive note={n} />
{/each} {/each}
</ul> </ul>

View File

@ -54,7 +54,7 @@
<div class="h-px bg-medium" in:fly={{y: 20, delay: 200}} /> <div class="h-px bg-medium" in:fly={{y: 20, delay: 200}} />
<div class="flex flex-col gap-4" in:fly={{y: 20, delay: 400}}> <div class="flex flex-col gap-4" in:fly={{y: 20, delay: 400}}>
{#each reverse(notes) as note} {#each reverse(notes) as note}
<Note note={note} /> <Note interactive note={note} />
{/each} {/each}
</div> </div>
</div> </div>

View File

@ -4,6 +4,8 @@ import {getLocalJson, setLocalJson, now, timedelta} from "src/util/misc"
import {user} from 'src/state/user' import {user} from 'src/state/user'
import {nostr} from 'src/state/nostr' import {nostr} from 'src/state/nostr'
export const modal = writable(null)
export const rooms = writable(getLocalJson("coracle/rooms") || {}) export const rooms = writable(getLocalJson("coracle/rooms") || {})
rooms.subscribe($rooms => { rooms.subscribe($rooms => {

View File

@ -46,8 +46,8 @@ export const stripExifData = async file => {
} }
export const hasParent = (tag, e) => { export const hasParent = (tag, e) => {
while (e.parentNode) { while (e) {
if (e.parentNode.tagName === tag.toUpperCase()) { if (e.tagName === tag.toUpperCase()) {
return true return true
} }