problem: no help thread

resolve https://github.com/nostrocket/hypergolic/issues/90
This commit is contained in:
Bob
2024-08-18 21:39:20 +08:00
parent 9558d0d182
commit 1653a74da2
3 changed files with 201 additions and 1 deletions

View File

@@ -0,0 +1,37 @@
<script lang="ts">
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
import { Separator } from '$lib/components/ui/separator/index.js';
import { unixToRelativeTime } from '@/helpers';
import { ndk } from '@/ndk';
import type { TreeNote } from '@/event_helpers/help_thread';
export let notes: TreeNote[];
export let isRoot: boolean = false;
</script>
<ol class="w-full">
{#each notes as note, index (note.id)}
{#if isRoot && index > 0}
<Separator />
{/if}
<li class="flex flex-col p-5">
<div class="flex items-center gap-2">
<Avatar
ndk={$ndk}
pubkey={note.pubkey}
class="h-5 w-5 flex-none rounded-full object-cover"
/>
<Name ndk={$ndk} pubkey={note.pubkey} class="inline-block truncate" />
</div>
<div class="overflow-hidden break-words" style="overflow-wrap: anywhere;">{note.content}</div>
<div class="text-gray-500">
{note.created_at ? unixToRelativeTime(note.created_at * 1000) : 'Loading'}
</div>
{#if note.children.length > 0}
<div class="ml-4">
<svelte:self notes={note.children} isRoot={false} />
</div>
{/if}
</li>
{/each}
</ol>

View File

@@ -0,0 +1,69 @@
import { prepareNostrEvent } from '@/helpers';
import { NDKKind, type NDKEvent } from '@nostr-dev-kit/ndk';
import type NDKSvelte from '@nostr-dev-kit/ndk-svelte';
export const HELP_THREAD_ROOT_EVENT_ID =
'f05059e5d33716c38a10b392538a592de91014b6e9610c91e5f50543f2fdb4fd';
const HELP_THREAD_ROOT_AUTHOR_PUBKEY =
'887f827161338ef4d3e83482498664ad7454caf9bda7d080c3b32821f1394708';
export interface TreeNote {
id: string;
pubkey: string;
content: string;
created_at: number;
reply?: string;
root: string;
children: TreeNote[];
}
export function buildNoteTree(notes: NDKEvent[]): TreeNote[] {
const noteMap = new Map<string, TreeNote>();
notes.forEach((note) => {
const rootTag = note.getMatchingTags('e', 'root')[0]?.[1];
const replyTag = note.getMatchingTags('e', 'reply')[0]?.[1];
noteMap.set(note.id, {
id: note.id,
pubkey: note.author.pubkey,
content: note.content,
created_at: note.created_at!,
root: rootTag,
reply: replyTag,
children: []
});
});
notes.forEach((note) => {
const replyTag = note.getMatchingTags('e', 'reply')[0]?.[1];
if (replyTag) {
const parent = noteMap.get(replyTag);
const self = noteMap.get(note.id);
if (parent && self) {
parent.children.push(self);
}
}
});
const result = Array.from(noteMap.values()).filter(
(note) =>
!note.reply ||
(note.reply === HELP_THREAD_ROOT_EVENT_ID && note.root === HELP_THREAD_ROOT_EVENT_ID)
);
return result;
}
export function prepareQuestionNoteEvent(args: { ndk: NDKSvelte; content: string }) {
const tags = [
['p', HELP_THREAD_ROOT_AUTHOR_PUBKEY],
['e', HELP_THREAD_ROOT_EVENT_ID, 'wss://relay.nostrocket.org', 'reply'],
['e', HELP_THREAD_ROOT_EVENT_ID, 'wss://relay.nostrocket.org', 'root']
];
return prepareNostrEvent({
...args,
kind: NDKKind.Text,
tags
});
}

View File

@@ -1 +1,95 @@
Wouldn't it be cool to have a nostr help thread here? <script lang="ts">
import * as Card from '$lib/components/ui/card/index.js';
import { ndk } from '@/ndk';
import { NDKKind } from '@nostr-dev-kit/ndk';
import { onDestroy } from 'svelte';
import { derived } from 'svelte/store';
import Heading from '../../components/Heading.svelte';
import HelpThreadNoteTree from '../../components/HelpThreadNoteTree.svelte';
import Button from '@/components/ui/button/button.svelte';
import { Label } from '$lib/components/ui/label/index.js';
import { Textarea } from '$lib/components/ui/textarea/index.js';
import { devmode, currentUser } from '@/stores/session';
import {
buildNoteTree,
HELP_THREAD_ROOT_EVENT_ID,
prepareQuestionNoteEvent
} from '@/event_helpers/help_thread';
import type NDKSvelte from '@nostr-dev-kit/ndk-svelte';
let notes = $ndk.storeSubscribe({
kinds: [1 as NDKKind],
'#e': [HELP_THREAD_ROOT_EVENT_ID]
});
let treeNotes = derived(notes, ($_notes) => {
return buildNoteTree($_notes);
});
let content: string;
function publish(ndk: NDKSvelte) {
if (!ndk.signer) {
throw new Error('no ndk signer found');
}
let author = $currentUser;
if (!author) {
throw new Error('no current user');
}
const e = prepareQuestionNoteEvent({
ndk,
content
});
e.publish().then((x) => {
console.log(x);
});
}
onDestroy(() => {
notes.unsubscribe();
});
</script>
<div class="my-4 flex flex-col gap-2">
{#if $devmode}
<div>
<Button
on:click={() => {
console.log('notes', $notes);
console.log('treeNotes', $treeNotes);
}}
variant="outline"
>
Print to Console
</Button>
</div>
{/if}
<Heading title="Help" />
<div>
If the answers to the questions below do not address your issue, you can send your question here
</div>
<form class="relative overflow-hidden">
<Label for="message" class="sr-only">Question</Label>
<Textarea
id="message"
placeholder="Type your question here..."
class="w-full resize-none shadow-none"
bind:value={content}
/>
<div class="flex items-center pt-2">
<Button
type="submit"
size="sm"
class="ml-auto gap-1.5"
on:click={() => {
publish($ndk);
}}
>
Publish
</Button>
</div>
</form>
<Card.Root>
<HelpThreadNoteTree notes={$treeNotes} isRoot />
</Card.Root>
</div>