mirror of
https://github.com/aljazceru/hypergolic.git
synced 2025-12-17 21:44:21 +01:00
Merge pull request #102 from bob2402/help-thread
problem: no help thread
This commit is contained in:
37
src/components/HelpThreadNoteTree.svelte
Normal file
37
src/components/HelpThreadNoteTree.svelte
Normal 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>
|
||||||
69
src/lib/event_helpers/help_thread.ts
Normal file
69
src/lib/event_helpers/help_thread.ts
Normal 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
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user