mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-19 19:46:42 +00:00
Manage modals with a mega modal model
This commit is contained in:
parent
dfb1916b02
commit
e43caba359
@ -19,7 +19,7 @@
|
|||||||
import * as db from "src/agent/db"
|
import * as db from "src/agent/db"
|
||||||
import user from "src/agent/user"
|
import user from "src/agent/user"
|
||||||
import {loadAppData} from "src/app/state"
|
import {loadAppData} from "src/app/state"
|
||||||
import {theme, getThemeVariables, modal, openModals} from "src/partials/state"
|
import {theme, getThemeVariables, modal} from "src/partials/state"
|
||||||
import {logUsage} from "src/app/state"
|
import {logUsage} from "src/app/state"
|
||||||
import SideNav from "src/app/SideNav.svelte"
|
import SideNav from "src/app/SideNav.svelte"
|
||||||
import Routes from "src/app/Routes.svelte"
|
import Routes from "src/app/Routes.svelte"
|
||||||
@ -54,16 +54,11 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
let scrollY
|
let scrollY
|
||||||
|
|
||||||
// Log modals
|
// Log modals, keep scroll position on body, but don't allow scrolling
|
||||||
const unsubModal = modal.stack.subscribe($stack => {
|
const unsubModal = modal.stack.subscribe($stack => {
|
||||||
if ($stack.length > 0) {
|
if ($stack.length > 0) {
|
||||||
logUsage(btoa(["modal", last($stack).type].join(":")))
|
logUsage(btoa(["modal", last($stack).type].join(":")))
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Keep scroll position on body, but don't allow scrolling
|
|
||||||
const unsubOpenModals = openModals.subscribe(n => {
|
|
||||||
if (n > 0) {
|
|
||||||
// This is not idempotent, so don't duplicate it
|
// This is not idempotent, so don't duplicate it
|
||||||
if (document.body.style.position !== "fixed") {
|
if (document.body.style.position !== "fixed") {
|
||||||
scrollY = window.scrollY
|
scrollY = window.scrollY
|
||||||
@ -71,9 +66,11 @@
|
|||||||
document.body.style.top = `-${scrollY}px`
|
document.body.style.top = `-${scrollY}px`
|
||||||
document.body.style.position = `fixed`
|
document.body.style.position = `fixed`
|
||||||
}
|
}
|
||||||
} else {
|
} else if (scrollY) {
|
||||||
document.body.setAttribute("style", "")
|
document.body.setAttribute("style", "")
|
||||||
window.scrollTo(0, scrollY)
|
window.scrollTo(0, scrollY)
|
||||||
|
|
||||||
|
scrollY = null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,7 +91,6 @@
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubModal()
|
unsubModal()
|
||||||
unsubOpenModals()
|
|
||||||
unsubHistory()
|
unsubHistory()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -31,7 +31,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each $stack as m}
|
{#each $stack as m}
|
||||||
<Modal onEscape={m.noEscape || m !== last($stack) ? null : closeModal}>
|
{#if !m.virtual}
|
||||||
|
<Modal virtual={false} onEscape={m.noEscape || m !== last($stack) ? null : closeModal}>
|
||||||
{#if m.type === "note/detail"}
|
{#if m.type === "note/detail"}
|
||||||
{#key m.note.id}
|
{#key m.note.id}
|
||||||
<NoteDetail {...m} invertColors />
|
<NoteDetail {...m} invertColors />
|
||||||
@ -79,4 +80,5 @@
|
|||||||
</Content>
|
</Content>
|
||||||
{/if}
|
{/if}
|
||||||
</Modal>
|
</Modal>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import {nip19} from "nostr-tools"
|
import {nip19} from "nostr-tools"
|
||||||
import {find, last} from "ramda"
|
import {find, last} from "ramda"
|
||||||
import {onMount} from "svelte"
|
import {onMount} from "svelte"
|
||||||
import {get} from "svelte/store"
|
|
||||||
import {quantify} from "hurdak/lib/hurdak"
|
import {quantify} from "hurdak/lib/hurdak"
|
||||||
import {findRootId, findReplyId, displayPerson} from "src/util/nostr"
|
import {findRootId, findReplyId, displayPerson} from "src/util/nostr"
|
||||||
import {formatTimestamp} from "src/util/misc"
|
import {formatTimestamp} from "src/util/misc"
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
export let feedRelay
|
export let feedRelay
|
||||||
export let notes
|
export let notes
|
||||||
|
|
||||||
$: filteredNotes = notes.filter(n => n.seen_on.includes(feedRelay.url))
|
$: filteredNotes = notes.filter(n => n.seen_on?.includes(feedRelay.url))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Content>
|
<Content>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import {pluck, find} from "ramda"
|
import {pluck, find} from "ramda"
|
||||||
import {Tags, displayPerson, displayRelay} from "src/util/nostr"
|
import {Tags, displayRelay} from "src/util/nostr"
|
||||||
import {modal, toast} from "src/partials/state"
|
import {modal, toast} from "src/partials/state"
|
||||||
import Heading from "src/partials/Heading.svelte"
|
import Heading from "src/partials/Heading.svelte"
|
||||||
|
import PersonBadge from "src/app/shared/PersonBadge.svelte"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
@ -22,10 +23,14 @@
|
|||||||
|
|
||||||
const search = q => {
|
const search = q => {
|
||||||
if (q.startsWith("#")) {
|
if (q.startsWith("#")) {
|
||||||
return $searchTopics(q).map(({name}) => ["t", name])
|
return $searchTopics(q)
|
||||||
|
.slice(0, 5)
|
||||||
|
.map(({name}) => ["t", name])
|
||||||
}
|
}
|
||||||
|
|
||||||
return $searchPeople(q).map(({pubkey}) => ["p", pubkey])
|
return $searchPeople(q)
|
||||||
|
.slice(0, 5)
|
||||||
|
.map(({pubkey}) => ["p", pubkey])
|
||||||
}
|
}
|
||||||
|
|
||||||
const _searchRelays = q => pluck("url", $searchRelays(q)).map(url => ["r", url])
|
const _searchRelays = q => pluck("url", $searchRelays(q)).map(url => ["r", url])
|
||||||
@ -63,9 +68,11 @@
|
|||||||
<MultiSelect {search} bind:value={values.params}>
|
<MultiSelect {search} bind:value={values.params}>
|
||||||
<div slot="item" let:item>
|
<div slot="item" let:item>
|
||||||
{#if item[0] === "p"}
|
{#if item[0] === "p"}
|
||||||
{displayPerson(getPersonWithFallback(item[1]))}
|
<div class="-my-1">
|
||||||
|
<PersonBadge inert person={getPersonWithFallback(item[1])} />
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
#{item[1]}
|
<strong>#{item[1]}</strong>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</MultiSelect>
|
</MultiSelect>
|
||||||
|
@ -1,18 +1,26 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import {randomId} from "hurdak/lib/hurdak"
|
||||||
import {onMount, onDestroy} from "svelte"
|
import {onMount, onDestroy} from "svelte"
|
||||||
import {fly, fade} from "svelte/transition"
|
import {fly, fade} from "svelte/transition"
|
||||||
import {openModals} from "src/partials/state"
|
import {modal} from "src/partials/state"
|
||||||
|
|
||||||
|
export let virtual = true
|
||||||
export let onEscape = null
|
export let onEscape = null
|
||||||
|
|
||||||
let root, content
|
let root, content
|
||||||
|
|
||||||
|
const id = randomId()
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
openModals.update(n => n + 1)
|
if (virtual) {
|
||||||
|
modal.push({id, virtual: true})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
openModals.update(n => n - 1)
|
if (virtual) {
|
||||||
|
modal.remove(id)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<div class="mt-2 flex flex-col rounded border border-solid border-gray-6" in:fly={{y: 20}}>
|
<div class="mt-2 flex flex-col rounded border border-solid border-gray-6" in:fly={{y: 20}}>
|
||||||
{#each data as item, i}
|
{#each data as item, i}
|
||||||
<button
|
<button
|
||||||
class="cursor-pointer border-l-2 border-solid border-black py-2 px-4 text-left text-white"
|
class="cursor-pointer border-l-2 border-solid border-black py-2 px-4 text-left text-gray-1 hover:border-accent hover:bg-gray-7"
|
||||||
class:bg-gray-8={index !== i}
|
class:bg-gray-8={index !== i}
|
||||||
class:bg-gray-7={index === i}
|
class:bg-gray-7={index === i}
|
||||||
class:border-accent={index === i}
|
class:border-accent={index === i}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {prop, fromPairs} from "ramda"
|
import {prop, whereEq, reject, last, fromPairs} from "ramda"
|
||||||
import {uuid, switcher} from "hurdak/lib/hurdak"
|
import {uuid, switcher} from "hurdak/lib/hurdak"
|
||||||
import type {Writable} from "svelte/store"
|
import type {Writable} from "svelte/store"
|
||||||
import {navigate} from "svelte-routing"
|
import {navigate} from "svelte-routing"
|
||||||
@ -44,15 +44,10 @@ toast.show = (type, message, timeout = 5) => {
|
|||||||
|
|
||||||
// Modals
|
// Modals
|
||||||
|
|
||||||
export const openModals = writable(0)
|
|
||||||
|
|
||||||
export const modal = {
|
export const modal = {
|
||||||
stack: new WritableList([]) as WritableList<any>,
|
stack: new WritableList([]) as WritableList<any>,
|
||||||
getCurrent() {
|
getCurrent() {
|
||||||
const $stack = get(modal.stack)
|
return last(get(modal.stack))
|
||||||
const $openModals = get(openModals)
|
|
||||||
|
|
||||||
return $stack[$openModals - 1]
|
|
||||||
},
|
},
|
||||||
sync($stack, opts = {}) {
|
sync($stack, opts = {}) {
|
||||||
const hash = $stack.length > 0 ? `#m=${$stack.length}` : ""
|
const hash = $stack.length > 0 ? `#m=${$stack.length}` : ""
|
||||||
@ -63,6 +58,9 @@ export const modal = {
|
|||||||
|
|
||||||
return $stack
|
return $stack
|
||||||
},
|
},
|
||||||
|
remove(id) {
|
||||||
|
modal.stack.update($stack => modal.sync(reject(whereEq({id}), $stack)))
|
||||||
|
},
|
||||||
push(data) {
|
push(data) {
|
||||||
modal.stack.update($stack => modal.sync($stack.concat(data)))
|
modal.stack.update($stack => modal.sync($stack.concat(data)))
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user