Maybe get dialogs behaving properly

This commit is contained in:
Jon Staab
2024-10-15 15:52:30 -07:00
parent 4decb2f4d9
commit 9c300d40f6
22 changed files with 169 additions and 189 deletions
+7 -7
View File
@@ -1,17 +1,17 @@
<script lang="ts">
import {pubkey} from '@welshman/app'
import {pubkey} from "@welshman/app"
import Landing from "@app/components/Landing.svelte"
import Toast from "@app/components/Toast.svelte"
import PrimaryNav from "@app/components/PrimaryNav.svelte"
</script>
<div class="flex h-screen overflow-hidden">
<PrimaryNav>
{#if $pubkey}
{#if $pubkey}
<PrimaryNav>
<slot />
{:else}
<Landing />
{/if}
</PrimaryNav>
</PrimaryNav>
{:else}
<Landing />
{/if}
</div>
<Toast />
+7 -5
View File
@@ -14,7 +14,6 @@
import type {PublishStatusData} from "@welshman/app"
import {REACTION, ZAP_RESPONSE, displayRelayUrl} from "@welshman/util"
import {repository} from "@welshman/app"
import {slideAndFade} from '@lib/transition'
import Icon from "@lib/components/Icon.svelte"
import Avatar from "@lib/components/Avatar.svelte"
import Button from "@lib/components/Button.svelte"
@@ -41,7 +40,10 @@
const rootHints = [rootTag?.[2]].filter(Boolean) as string[]
const rootEvent = rootId ? deriveEvent(rootId, rootHints) : readable(null)
const [colorName, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length]
const ps = throttled(300, derived(publishStatusData, $m => Object.values($m[event.id] || {})))
const ps = throttled(
300,
derived(publishStatusData, $m => Object.values($m[event.id] || {})),
)
const showInfo = () => pushModal(EventInfo, {event})
@@ -94,7 +96,7 @@
</p>
</div>
{/if}
<div class="flex gap-2 w-full">
<div class="flex w-full gap-2">
{#if showPubkey}
<Avatar src={$profile?.picture} class="border border-solid border-base-content" size={10} />
{:else}
@@ -128,7 +130,7 @@
</div>
{#if $reactions.length > 0 || $zaps.length > 0}
<div class="ml-12 text-xs">
{#each groupBy(e => e.content, uniqBy(e => e.pubkey + e.content, $reactions)).entries() as [content, events]}
{#each groupBy( e => e.content, uniqBy(e => e.pubkey + e.content, $reactions), ).entries() as [content, events]}
{@const isOwn = events.some(e => e.pubkey === $pubkey)}
{@const onClick = () => onReactionClick(content, events)}
<button
@@ -147,7 +149,7 @@
</div>
{/if}
<button
class="join absolute top-1 right-1 border border-solid border-neutral text-xs opacity-0 transition-all group-hover:opacity-100"
class="join absolute right-1 top-1 border border-solid border-neutral text-xs opacity-0 transition-all group-hover:opacity-100"
on:click|stopPropagation>
<ChannelMessageEmojiButton {url} {room} {event} />
<Button class="btn join-item btn-xs" on:click={showInfo}>
+1 -1
View File
@@ -43,7 +43,7 @@
}
</script>
<div class="fixed flex max-h-screen w-full flex-col gap-2">
<div class="col-2">
<div class="overflow-auto pt-3">
<ChannelMessage {url} {room} {event} showPubkey />
{#each sortBy(e => e.created_at, $replies) as reply (reply.id)}
+8 -5
View File
@@ -35,7 +35,10 @@
const reactions = deriveEvents(repository, {filters: [{kinds: [REACTION], "#e": [event.id]}]})
const zaps = deriveEvents(repository, {filters: [{kinds: [ZAP_RESPONSE], "#e": [event.id]}]})
const [_, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length]
const ps = throttled(300, derived(publishStatusData, $m => Object.values($m[event.wrap!.id] || {})))
const ps = throttled(
300,
derived(publishStatusData, $m => Object.values($m[event.wrap!.id] || {})),
)
const showProfile = () => pushDrawer(ProfileDetail, {pubkey: event.pubkey})
@@ -67,7 +70,7 @@
</script>
<div
class="chat flex gap-1 items-center group justify-end"
class="group chat flex items-center justify-end gap-1"
class:chat-start={event.pubkey !== $pubkey}
class:flex-row-reverse={event.pubkey !== $pubkey}
class:chat-end={event.pubkey === $pubkey}>
@@ -85,13 +88,13 @@
popoverIsVisible = false
},
}}>
<Button class="group-hover:opacity-100 opacity-0 transition-all" on:click={togglePopover}>
<Button class="opacity-0 transition-all group-hover:opacity-100" on:click={togglePopover}>
<Icon icon="menu-dots" size={4} />
</Button>
</Tippy>
<div class="flex flex-col">
<div class="chat-bubble mx-1 max-w-sm">
<div class="flex items-start gap-2 w-full">
<div class="flex w-full items-start gap-2">
{#if showPubkey}
<Button on:click={showProfile}>
<Avatar
@@ -129,7 +132,7 @@
</div>
</div>
{#if $reactions.length > 0 || $zaps.length > 0}
<div class="-mt-4 text-xs z-feature relative flex justify-end">
<div class="relative z-feature -mt-4 flex justify-end text-xs">
{#each groupBy( e => e.content, uniqBy(e => e.pubkey + e.content, $reactions), ).entries() as [content, events]}
{@const isOwn = events.some(e => e.pubkey === $pubkey)}
{@const onClick = () => onReactionClick(content, events)}
+4 -4
View File
@@ -1,9 +1,9 @@
<script lang="ts">
import Icon from '@lib/components/Icon.svelte'
import Button from '@lib/components/Button.svelte'
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import ChatMessageEmojiButton from "@app/components/ChatMessageEmojiButton.svelte"
import EventInfo from '@app/components/EventInfo.svelte'
import {pushModal} from '@app/modal'
import EventInfo from "@app/components/EventInfo.svelte"
import {pushModal} from "@app/modal"
export let event
export let pubkeys
+1 -2
View File
@@ -14,7 +14,6 @@
import DateTimeInput from "@lib/components/DateTimeInput.svelte"
import {getPubkeyHints} from "@app/commands"
import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor"
import {clearModal} from "@app/modal"
import {pushToast} from "@app/toast"
export let url
@@ -54,7 +53,7 @@
})
publishThunk({event, relays: [url]})
clearModal()
history.back()
}
let editor: Readable<Editor>
+2 -4
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import Button from '@lib/components/Button.svelte'
import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
export let event
@@ -8,9 +8,7 @@
<div class="column gap-4">
<ModalHeader>
<div slot="title">Event Details</div>
<div slot="info">
The full details of this event are shown below.
</div>
<div slot="info">The full details of this event are shown below.</div>
</ModalHeader>
<pre class="overflow-auto"><code>{JSON.stringify(event, null, 2)}</code></pre>
<Button class="btn btn-primary" on:click={() => history.back()}>Got it</Button>
+22 -19
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Dialog from "@lib/components/Dialog.svelte"
import CardButton from "@lib/components/CardButton.svelte"
import LogIn from "@app/components/LogIn.svelte"
import SignUp from "@app/components/SignUp.svelte"
@@ -11,23 +12,25 @@
const signUp = () => pushModal(SignUp)
</script>
<div class="column gap-4">
<div class="py-2">
<h1 class="heading">Welcome to Flotilla!</h1>
<p class="text-center">The chat app built for sovereign communities.</p>
<Dialog>
<div class="column gap-4">
<div class="py-2">
<h1 class="heading">Welcome to Flotilla!</h1>
<p class="text-center">The chat app built for sovereign communities.</p>
</div>
<Button on:click={logIn}>
<CardButton>
<div slot="icon"><Icon icon="login-2" size={7} /></div>
<div slot="title">Log in</div>
<div slot="info">If you've been here before, you know the drill.</div>
</CardButton>
</Button>
<Button on:click={signUp}>
<CardButton>
<div slot="icon"><Icon icon="add-circle" size={7} /></div>
<div slot="title">Create an account</div>
<div slot="info">Just a few questions and you'll be on your way.</div>
</CardButton>
</Button>
</div>
<Button on:click={logIn}>
<CardButton>
<div slot="icon"><Icon icon="login-2" size={7} /></div>
<div slot="title">Log in</div>
<div slot="info">If you've been here before, you know the drill.</div>
</CardButton>
</Button>
<Button on:click={signUp}>
<CardButton>
<div slot="icon"><Icon icon="add-circle" size={7} /></div>
<div slot="title">Create an account</div>
<div slot="info">Just a few questions and you'll be on your way.</div>
</CardButton>
</Button>
</div>
</Dialog>
+2 -2
View File
@@ -9,7 +9,7 @@
import SignUp from "@app/components/SignUp.svelte"
import InfoNostr from "@app/components/InfoNostr.svelte"
import LogInInfoRemoteSigner from "@app/components/LogInInfoRemoteSigner.svelte"
import {pushModal, clearModal} from "@app/modal"
import {pushModal, clearModals} from "@app/modal"
import {pushToast} from "@app/toast"
import {loadUserData} from "@app/commands"
@@ -31,7 +31,7 @@
await loadUserData(session.pubkey, {relays})
pushToast({message: "Successfully logged in!"})
clearModal()
clearModals()
}
const loginWithNip46 = withLoading(async () => {
+23 -45
View File
@@ -1,56 +1,34 @@
<script lang="ts">
import {onMount} from 'svelte'
import type {SvelteComponent} from "svelte"
import {page} from "$app/stores"
import {fly} from "@lib/transition"
import Drawer from "@lib/components/Drawer.svelte"
import {modals} from "@app/modal"
import Toast from "@app/components/Toast.svelte"
import Dialog from "@lib/components/Dialog.svelte"
import {modals, clearModals} from "@app/modal"
let prev: any
let mounted = false
let dialog: HTMLDialogElement
let drawer: SvelteComponent
$: hash = $page.url.hash.slice(1)
$: modal = modals.get(hash)
$: prev = modal || prev
$: {
if (mounted) {
if (modal?.options?.drawer) {
drawer.open()
} else if (modal) {
dialog.showModal()
} else {
drawer.close()
dialog.close()
}
const onKeyDown = (e: any) => {
if (e.code === "Escape" && e.target === document.body) {
clearModals()
}
}
onMount(() => {
mounted = true
})
let modal: any
$: hash = $page.url.hash.slice(1)
$: hashIsValid = Boolean($modals[hash])
$: modal = $modals[hash] || modal
</script>
<dialog bind:this={dialog} class="modal modal-bottom !z-modal sm:modal-middle">
{#if modal && !modal.options?.drawer}
{#key hash}
<div class="bg-alt modal-box overflow-visible overflow-y-auto" transition:fly={{duration: 100}}>
<svelte:component this={modal.component} {...modal.props} />
</div>
{/key}
<Toast />
{/if}
<form method="dialog" class="modal-backdrop">
<button />
</form>
</dialog>
<Drawer bind:this={drawer}>
{#if modal && modal.options?.drawer}
{#key hash}
<svelte:window on:keydown={onKeyDown} />
{#if hashIsValid && modal?.options?.drawer}
<Drawer onClose={clearModals}>
{#key modal.id}
<svelte:component this={modal.component} {...modal.props} />
{/key}
{/if}
</Drawer>
</Drawer>
{:else if hashIsValid && modal}
<Dialog onClose={clearModals}>
{#key modal.id}
<svelte:component this={modal.component} {...modal.props} />
{/key}
</Dialog>
{/if}
+2 -2
View File
@@ -54,9 +54,9 @@
{@const following = getPubkeyTagValues(getListTags($userFollows)).includes(pubkey)}
<div class="divider" />
<button type="button" class="chat chat-start cursor-default" on:click|stopPropagation>
<div class="bg-alt chat-bubble text-left col-4">
<div class="bg-alt col-4 chat-bubble text-left">
<Content hideMedia={!following} {event} />
<Link external href={entityLink(nevent)} class="row-2 justify-end group whitespace-nowrap">
<Link external href={entityLink(nevent)} class="row-2 group justify-end whitespace-nowrap">
<Icon icon="link-round" size={3} />
<p class="text-xs">{formatTimestamp(event.created_at)}</p>
</Link>
+2 -2
View File
@@ -7,7 +7,7 @@
import Spinner from "@lib/components/Spinner.svelte"
import LogIn from "@app/components/LogIn.svelte"
import InfoNostr from "@app/components/LogIn.svelte"
import {pushModal, clearModal} from "@app/modal"
import {pushModal, clearModals} from "@app/modal"
import {pushToast} from "@app/toast"
const login = () => pushModal(LogIn)
@@ -38,7 +38,7 @@
if (await loginBroker.connect("", nip46Perms)) {
addSession({method: "nip46", pubkey, secret, handler})
pushToast({message: "Successfully logged in!"})
clearModal()
clearModals()
} else {
pushToast({
theme: "error",
+2 -2
View File
@@ -5,7 +5,7 @@
import Icon from "@lib/components/Icon.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import {clearModal} from "@app/modal"
import {clearModals} from "@app/modal"
import {addSpaceMembership} from "@app/commands"
export let url
@@ -15,7 +15,7 @@
const tryJoin = async () => {
await addSpaceMembership(url)
clearModal()
clearModals()
}
const join = async () => {
+1 -2
View File
@@ -11,7 +11,6 @@
import ModalFooter from "@lib/components/ModalFooter.svelte"
import {getPubkeyHints} from "@app/commands"
import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor"
import {clearModal} from "@app/modal"
export let url
@@ -25,7 +24,7 @@
const event = createEvent(NOTE, {content: $editor.getText(), tags: getEditorTags($editor)})
publishThunk({event, relays: [url]})
clearModal()
history.back()
}
let editor: Readable<Editor>