Support nevent path

This commit is contained in:
Jonathan Staab 2023-01-12 09:15:37 -08:00
parent e0bb3ca32c
commit 2f818a561e
9 changed files with 132 additions and 50 deletions

View File

@ -74,6 +74,7 @@ If you like Coracle and want to support its development, you can donate sats via
- [ ] Load feeds from network rather than user relays? This could make global feed more useful: global for _my_ relays
- [ ] Release to android with https://svelte-native.technology/docs
- [ ] Compress is taking too long and messing up the ui, maybe use dexie for people?
- [ ] Move people to nprofile via bech32 entity (or redirect from there)
## 0.2.6

View File

@ -15,7 +15,8 @@
import {modal, toast, settings, alerts} from "src/app"
import {routes} from "src/app/ui"
import Anchor from 'src/partials/Anchor.svelte'
import NoteDetail from "src/views/NoteDetail.svelte"
import Modal from 'src/partials/Modal.svelte'
import NoteDetailModal from "src/views/NoteDetail.svelte"
import PersonSettings from "src/views/PersonSettings.svelte"
import NotFound from "src/routes/NotFound.svelte"
import Search from "src/routes/Search.svelte"
@ -30,6 +31,7 @@
import AddRelay from "src/routes/AddRelay.svelte"
import Person from "src/routes/Person.svelte"
import NoteCreate from "src/routes/NoteCreate.svelte"
import Bech32Entity from "src/routes/Bech32Entity.svelte"
export let url = ""
@ -39,6 +41,11 @@
const searchIsOpen = writable(false)
const toggleSearch = () => searchIsOpen.update(x => !x)
const closeModal = () => {
modal.set(null)
menuIsOpen.set(false)
}
let menuIcon
let scrollY
let suspendedSubs = []
@ -78,14 +85,6 @@
})
</script>
<svelte:body
on:keydown={e => {
if (e.key === 'Escape') {
modal.set(null)
menuIsOpen.set(false)
}
}} />
<Router {url}>
<div use:links class="h-full">
<div class="pt-16 text-white h-full">
@ -104,6 +103,11 @@
<Route path="/settings" component={Settings} />
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
<Route path="/:entity" let:params>
{#key params.entity}
<Bech32Entity {...params} />
{/key}
</Route>
<Route path="*" component={NotFound} />
</div>
@ -197,25 +201,17 @@
{/if}
{#if $modal}
<div class="fixed inset-0 z-10">
<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 overflow-auto">
{#if $modal.note}
{#key $modal.note.id}
<NoteDetail {...$modal} />
{/key}
{:else if $modal.form === 'relay'}
<AddRelay />
{:else if $modal.form === 'person/settings'}
<PersonSettings />
{/if}
</dialog>
</div>
</div>
<Modal onEscape={closeModal}>
{#if $modal.note}
{#key $modal.note.id}
<NoteDetailModal {...$modal} />
{/key}
{:else if $modal.form === 'relay'}
<AddRelay />
{:else if $modal.form === 'person/settings'}
<PersonSettings />
{/if}
</Modal>
{/if}
{#if $toast}

View File

@ -46,6 +46,10 @@ export const getRelays = pubkey => {
}
export const getEventRelays = event => {
if (event.seen_on) {
return [event.seen_on]
}
return uniq(getRelays(event.pubkey).concat(Tags.from(event).relays()))
}

View File

@ -1,11 +1,12 @@
import {without} from 'ramda'
import {updateIn, mergeRight} from 'hurdak/lib/hurdak'
import {get} from 'svelte/store'
import {getPerson, getRelays, people, keys, db} from 'src/agent'
import {getPerson, getRelays, people, load, keys, db} from 'src/agent'
import {toast, modal, settings} from 'src/app/ui'
import cmd from 'src/app/cmd'
import alerts from 'src/app/alerts'
import loaders from 'src/app/loaders'
import query from 'src/app/query'
export {toast, modal, settings, alerts}
@ -49,3 +50,19 @@ export const removeRelay = async url => {
await cmd.setRelays(without([url], relays))
}
export const loadNote = async (relays, id) => {
const [found] = await load(relays, {ids: [id]})
if (!found) {
return null
}
const context = await loaders.loadContext(relays, found)
const note = query.annotate(found, context, {showEntire: true, depth: 3})
// Log this for debugging purposes
console.log('loadNote', note)
return note
}

24
src/partials/Modal.svelte Normal file
View File

@ -0,0 +1,24 @@
<script>
import {fly, fade} from "svelte/transition"
export let onEscape
</script>
<svelte:body
on:keydown={e => {
if (e.key === 'Escape') {
onEscape()
}
}} />
<div class="fixed inset-0 z-10">
<div
class="absolute inset-0 opacity-75 bg-black cursor-pointer"
transition:fade
on:click={onEscape} />
<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 overflow-auto">
<slot />
</dialog>
</div>
</div>

View File

@ -1,6 +1,7 @@
<script>
import cx from 'classnames'
import extractUrls from 'extract-urls'
import {nip19} from 'nostr-tools'
import {whereEq, reject, propEq, find} from 'ramda'
import {slide} from 'svelte/transition'
import {navigate} from 'svelte-routing'
@ -27,6 +28,7 @@
const links = $settings.showLinkPreviews ? extractUrls(note.content) || [] : null
const interactive = !anchorId || anchorId !== note.id
const relays = getEventRelays(note)
let likes, flags, like, flag
@ -40,15 +42,14 @@
const onClick = e => {
if (!['I'].includes(e.target.tagName) && !hasParent('a', e.target)) {
modal.set({note, relays: getEventRelays(note)})
modal.set({note, relays})
}
}
const goToParent = async () => {
modal.set({
note: {id: findReply(note)[1]},
relays: getEventRelays(note),
})
const parent = {id: findReply(note)[1]}
modal.set({note: parent, relays})
}
const react = async content => {
@ -114,7 +115,12 @@
<Card on:click={onClick} {interactive} {invertColors}>
<div class="flex gap-4 items-center justify-between">
<Badge person={getPerson(note.pubkey, true)} />
<p class="text-sm text-light">{formatTimestamp(note.created_at)}</p>
<Anchor
href={"/" + nip19.neventEncode({id: note.id, relays})}
class="text-sm text-light"
type="unstyled">
{formatTimestamp(note.created_at)}
</Anchor>
</div>
<div class="ml-6 flex flex-col gap-2">
{#if findReply(note) && showParent}

View File

@ -0,0 +1,15 @@
<script>
import {nip19} from 'nostr-tools'
import NoteDetail from 'src/routes/NoteDetail.svelte'
export let entity
const {type, data} = nip19.decode(entity)
</script>
<div class="py-4 max-w-xl m-auto">
{#if type === "nevent"}
<NoteDetail {...data} />
{/if}
</div>

View File

@ -0,0 +1,29 @@
<script>
import {fly} from 'svelte/transition'
import {loadNote} from 'src/app'
import Note from 'src/partials/Note.svelte'
import Spinner from 'src/partials/Spinner.svelte'
export let id
export let relays
let note = {id}
console.log(id, relays)
loadNote(relays, id).then(found => {
note = found
})
</script>
{#if !note}
<div class="p-4 text-center text-white" in:fly={{y: 20}}>
Sorry, we weren't able to find this note.
</div>
{:else if note.pubkey}
<div in:fly={{y: 20}}>
<Note invertColors anchorId={note.id} note={note} depth={2} />
</div>
{:else}
<Spinner />
{/if}

View File

@ -1,9 +1,6 @@
<script>
import {first} from 'hurdak/lib/hurdak'
import {fly} from 'svelte/transition'
import {load} from 'src/agent'
import loaders from 'src/app/loaders'
import query from 'src/app/query'
import {loadNote} from 'src/app'
import Note from 'src/partials/Note.svelte'
import Spinner from 'src/partials/Spinner.svelte'
@ -11,18 +8,11 @@
export let relays
if (!note.pubkey) {
load(relays, {ids: [note.id]}).then(async events => {
const found = first(events)
if (found) {
const context = await loaders.loadContext(relays, found)
note = query.annotate(found, context, {showEntire: true, depth: 3})
}
// Log this for debugging purposes
console.log('NoteDetail', note)
loadNote(relays, note.id).then(found => {
note = found
})
} else {
console.log('NoteDetail', note)
}
</script>