You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.9 KiB
141 lines
3.9 KiB
<script lang="ts"> |
|
import { sessionManager } from '../../services/auth/session-manager.js'; |
|
import { signAndPublish } from '../../services/nostr/auth-handler.js'; |
|
import { relayManager } from '../../services/nostr/relay-manager.js'; |
|
import type { NostrEvent } from '../../types/nostr.js'; |
|
|
|
interface Props { |
|
parentEvent: NostrEvent; // The event to reply to |
|
onPublished?: () => void; |
|
onCancel?: () => void; |
|
} |
|
|
|
let { parentEvent, onPublished, onCancel }: Props = $props(); |
|
|
|
let content = $state(''); |
|
let publishing = $state(false); |
|
let includeClientTag = $state(true); |
|
|
|
async function publish() { |
|
if (!sessionManager.isLoggedIn()) { |
|
alert('Please log in to reply'); |
|
return; |
|
} |
|
|
|
if (!content.trim()) { |
|
alert('Reply cannot be empty'); |
|
return; |
|
} |
|
|
|
publishing = true; |
|
|
|
try { |
|
const tags: string[][] = []; |
|
|
|
// Add NIP-10 threading tags for reply |
|
const rootTag = parentEvent.tags.find((t) => t[0] === 'root'); |
|
const rootId = rootTag?.[1] || parentEvent.id; |
|
|
|
tags.push(['e', parentEvent.id, '', 'reply']); |
|
tags.push(['p', parentEvent.pubkey]); |
|
tags.push(['root', rootId]); |
|
|
|
if (includeClientTag) { |
|
tags.push(['client', 'Aitherboard']); |
|
} |
|
|
|
const event: Omit<NostrEvent, 'id' | 'sig'> = { |
|
kind: 1, |
|
pubkey: sessionManager.getCurrentPubkey()!, |
|
created_at: Math.floor(Date.now() / 1000), |
|
tags, |
|
content: content.trim() |
|
}; |
|
|
|
// Get target inbox if replying |
|
let targetInbox: string[] | undefined; |
|
try { |
|
const { fetchRelayLists } = await import('../../services/user-data.js'); |
|
const { inbox } = await fetchRelayLists(parentEvent.pubkey); |
|
targetInbox = inbox; |
|
} catch { |
|
// Ignore errors, just use default relays |
|
} |
|
|
|
const relays = relayManager.getFeedPublishRelays(targetInbox); |
|
const result = await signAndPublish(event, relays); |
|
|
|
if (result.success.length > 0) { |
|
content = ''; |
|
onPublished?.(); |
|
} else { |
|
alert('Failed to publish reply'); |
|
} |
|
} catch (error) { |
|
console.error('Error publishing reply:', error); |
|
alert('Error publishing reply'); |
|
} finally { |
|
publishing = false; |
|
} |
|
} |
|
</script> |
|
|
|
<div class="reply-to-Feed-form"> |
|
<div class="reply-context mb-2 p-2 bg-fog-highlight dark:bg-fog-dark-highlight rounded text-sm"> |
|
<span class="font-semibold">Replying to:</span> {parentEvent.content.slice(0, 100)}... |
|
</div> |
|
|
|
<textarea |
|
bind:value={content} |
|
placeholder="Write a reply..." |
|
class="w-full p-3 border border-fog-border dark:border-fog-dark-border rounded bg-fog-post dark:bg-fog-dark-post text-fog-text dark:text-fog-dark-text" |
|
rows="6" |
|
disabled={publishing} |
|
></textarea> |
|
|
|
<div class="flex items-center justify-between mt-2"> |
|
<label class="flex items-center gap-2 text-sm text-fog-text dark:text-fog-dark-text"> |
|
<input |
|
type="checkbox" |
|
bind:checked={includeClientTag} |
|
class="rounded" |
|
/> |
|
Include client tag |
|
</label> |
|
|
|
<div class="flex gap-2"> |
|
{#if onCancel} |
|
<button |
|
onclick={onCancel} |
|
class="px-4 py-2 text-sm border border-fog-border dark:border-fog-dark-border rounded hover:bg-fog-highlight dark:hover:bg-fog-dark-highlight" |
|
disabled={publishing} |
|
> |
|
Cancel |
|
</button> |
|
{/if} |
|
<button |
|
onclick={publish} |
|
class="px-4 py-2 text-sm bg-fog-accent dark:bg-fog-dark-accent text-white rounded hover:opacity-90 disabled:opacity-50" |
|
disabled={publishing || !content.trim()} |
|
> |
|
{publishing ? 'Publishing...' : 'Reply'} |
|
</button> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<style> |
|
.reply-to-Feed-form { |
|
margin-bottom: 1rem; |
|
} |
|
|
|
textarea { |
|
resize: vertical; |
|
min-height: 120px; |
|
} |
|
|
|
textarea:focus { |
|
outline: none; |
|
border-color: var(--fog-accent, #64748b); |
|
} |
|
</style>
|
|
|