Browse Source

bug-fixes

clone events
master
Silberengel 1 month ago
parent
commit
0e5bbf5393
  1. 94
      src/lib/components/EventMenu.svelte
  2. 6
      src/lib/components/content/EmojiPicker.svelte
  3. 7
      src/lib/components/content/GifPicker.svelte
  4. 7
      src/lib/components/content/PollCard.svelte
  5. 7
      src/lib/components/modals/EventJsonModal.svelte
  6. 8
      src/lib/components/modals/RelatedEventsModal.svelte
  7. 21
      src/lib/components/profile/ProfileMenu.svelte
  8. 26
      src/lib/modules/discussions/DiscussionVoteButtons.svelte
  9. 20
      src/lib/modules/reactions/FeedReactionButtons.svelte
  10. 6
      src/lib/services/nostr/config.ts
  11. 43
      src/lib/services/user-actions.ts
  12. 23
      src/routes/write/+page.svelte

94
src/lib/components/EventMenu.svelte

@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
import { KIND } from '../types/kind-lookup.js';
import { goto } from '$app/navigation';
import Icon from './ui/Icon.svelte';
import { getEventLink } from '../services/event-links.js';
interface Props {
event: NostrEvent;
@ -243,16 +244,47 @@ @@ -243,16 +244,47 @@
closeMenu();
}
function viewEvent() {
closeMenu();
goto(getEventLink(event));
}
function cloneEvent() {
// Store event data in sessionStorage for the write page to pick up
const cloneData = {
kind: event.kind,
content: event.content,
tags: event.tags,
isClone: true
};
sessionStorage.setItem('aitherboard_cloneEvent', JSON.stringify(cloneData));
closeMenu();
goto('/write');
}
async function broadcastEvent() {
broadcasting = true;
closeMenu();
try {
// Get all available relays for broadcasting
const relays = relayManager.getPublishRelays(
[...relayManager.getThreadReadRelays(), ...relayManager.getFeedReadRelays()],
true
);
// Get ALL available relays for maximum broadcasting
// Start with all available relays (includes default, profile, and user inbox relays)
let allRelays = relayManager.getAllAvailableRelays();
// Add thread publish relays (includes thread-specific relays)
allRelays = [...allRelays, ...relayManager.getThreadPublishRelays()];
// Add file metadata publish relays (includes GIF relays)
allRelays = [...allRelays, ...relayManager.getFileMetadataPublishRelays()];
// Add feed response relays
allRelays = [...allRelays, ...relayManager.getFeedResponseReadRelays()];
// Use getPublishRelays to ensure user outbox and local write relays are included
// This will also normalize, deduplicate, filter read-only relays, and filter blocked relays
const relays = relayManager.getPublishRelays(allRelays, true);
console.log(`[Broadcast] Broadcasting to ${relays.length} relays:`, relays);
const results = await nostrClient.publish(event, { relays });
publicationResults = results;
@ -284,14 +316,18 @@ @@ -284,14 +316,18 @@
}
async function pinNote() {
await togglePin(event.id);
const results = await togglePin(event.id);
publicationResults = results;
publicationModalOpen = true;
// Force state update
stateUpdateTrigger++;
closeMenu();
}
async function bookmarkNote() {
await toggleBookmark(event.id);
const results = await toggleBookmark(event.id);
publicationResults = results;
publicationModalOpen = true;
// Force state update by re-checking bookmark status
const newBookmarked = await isBookmarked(event.id);
bookmarkedState = newBookmarked;
@ -390,6 +426,19 @@ @@ -390,6 +426,19 @@
class="menu-dropdown"
style="top: {menuPosition.top}px; right: {menuPosition.right}px;"
>
<!-- View actions -->
<button class="menu-item" onclick={viewEvent}>
<Icon name="eye" size={16} />
<span>View this note</span>
</button>
<button class="menu-item" onclick={viewJson}>
<Icon name="code" size={16} />
<span>View JSON</span>
</button>
<div class="menu-divider"></div>
<!-- Copy actions -->
<button class="menu-item" onclick={copyUserId}>
<Icon name="copy" size={16} />
<span>Copy user ID</span>
@ -404,28 +453,36 @@ @@ -404,28 +453,36 @@
<span class="copied-indicator"></span>
{/if}
</button>
<button class="menu-item" onclick={viewJson}>
<Icon name="code" size={16} />
<span>View JSON</span>
<div class="menu-divider"></div>
<!-- Share actions -->
<button class="menu-item" onclick={shareWithaitherboard}>
<Icon name="share" size={16} />
<span>Share with aitherboard</span>
{#if copied === 'share'}
<span class="copied-indicator"></span>
{/if}
</button>
<!-- User-specific actions (logged in only) -->
{#if isLoggedIn}
<div class="menu-divider"></div>
<button class="menu-item" onclick={viewRelatedEvents}>
<Icon name="search" size={16} />
<span>View your related events</span>
</button>
{/if}
<button class="menu-item" onclick={cloneEvent}>
<Icon name="edit" size={16} />
<span>Edit/Clone this event</span>
</button>
<button class="menu-item" onclick={broadcastEvent} disabled={broadcasting}>
<Icon name="radio" size={16} />
<span>{broadcasting ? 'Broadcasting...' : 'Broadcast event'}</span>
</button>
<button class="menu-item" onclick={shareWithaitherboard}>
<Icon name="share" size={16} />
<span>Share with aitherboard</span>
{#if copied === 'share'}
<span class="copied-indicator"></span>
{/if}
</button>
<!-- Interaction actions (logged in only) -->
{#if isLoggedIn && onReply}
<div class="menu-divider"></div>
<button class="menu-item menu-item-reply" onclick={() => { onReply(); closeMenu(); }}>
@ -434,7 +491,9 @@ @@ -434,7 +491,9 @@
</button>
{/if}
{#if isLoggedIn && showContentActions}
{#if !onReply}
<div class="menu-divider"></div>
{/if}
<button class="menu-item" onclick={pinNote} class:active={pinnedState}>
<Icon name="plus" size={16} />
<span>Pin note</span>
@ -458,6 +517,7 @@ @@ -458,6 +517,7 @@
</button>
{/if}
<!-- Delete action (logged in and own event only) -->
{#if isLoggedIn && isOwnEvent}
<div class="menu-divider"></div>
<button class="menu-item menu-item-danger" onclick={confirmDelete} disabled={deleting}>

6
src/lib/components/content/EmojiPicker.svelte

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
import { KIND } from '../../types/kind-lookup.js';
import type { NostrEvent } from '../../types/nostr.js';
import { cacheEvent } from '../../services/cache/event-cache.js';
import PublicationStatusModal from '../modals/PublicationStatusModal.svelte';
interface Props {
open: boolean;
@ -29,6 +30,8 @@ @@ -29,6 +30,8 @@
let fileInput: HTMLInputElement | null = $state(null);
let shortcodeInput: HTMLInputElement | null = $state(null);
let showUploadForm = $state(false);
let publicationModalOpen = $state(false);
let publicationResults = $state<{ success: string[]; failed: Array<{ relay: string; error: string }> } | null>(null);
// Check if user is logged in
let isLoggedIn = $derived(sessionManager.isLoggedIn());
@ -305,6 +308,8 @@ @@ -305,6 +308,8 @@
// Publish the event
const result = await signAndPublish(event, relays);
publicationResults = result;
publicationModalOpen = true;
if (result.success.length > 0) {
console.log(`[EmojiPicker] Published emoji set event for ${file.name} (shortcode: :${finalShortcode}:) to ${result.success.length} relay(s)`);
@ -450,6 +455,7 @@ @@ -450,6 +455,7 @@
{/snippet}
</EmojiDrawer>
<PublicationStatusModal bind:open={publicationModalOpen} bind:results={publicationResults} />
<style>
.emoji-picker-wrapper {

7
src/lib/components/content/GifPicker.svelte

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
import { KIND } from '../../types/kind-lookup.js';
import type { NostrEvent } from '../../types/nostr.js';
import { cacheEvent } from '../../services/cache/event-cache.js';
import PublicationStatusModal from '../modals/PublicationStatusModal.svelte';
interface Props {
open: boolean;
@ -40,6 +41,8 @@ @@ -40,6 +41,8 @@
image: '',
content: ''
});
let publicationModalOpen = $state(false);
let publicationResults = $state<{ success: string[]; failed: Array<{ relay: string; error: string }> } | null>(null);
// Check if user is logged in
let isLoggedIn = $derived(sessionManager.isLoggedIn());
@ -365,6 +368,8 @@ @@ -365,6 +368,8 @@
// Publish the event
const result = await signAndPublish(event, relays);
publicationResults = result;
publicationModalOpen = true;
if (result.success.length > 0) {
console.log(`[GifPicker] Published file metadata event for ${file.name} to ${result.success.length} relay(s)`);
@ -619,6 +624,8 @@ @@ -619,6 +624,8 @@
</div>
{/if}
<PublicationStatusModal bind:open={publicationModalOpen} bind:results={publicationResults} />
<style>
.drawer-backdrop {
position: fixed;

7
src/lib/components/content/PollCard.svelte

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
import { onMount } from 'svelte';
import type { NostrEvent } from '../../types/nostr.js';
import { KIND } from '../../types/kind-lookup.js';
import PublicationStatusModal from '../modals/PublicationStatusModal.svelte';
interface Props {
pollEvent: NostrEvent; // The poll event (kind 1068)
@ -33,6 +34,8 @@ @@ -33,6 +34,8 @@
let submittingVote = $state(false);
let userVote = $state<string[]>([]); // Option IDs the current user has voted for
let hasVoted = $state(false);
let publicationModalOpen = $state(false);
let publicationResults = $state<{ success: string[]; failed: Array<{ relay: string; error: string }> } | null>(null);
// Parse poll event
function parsePoll() {
@ -208,6 +211,8 @@ @@ -208,6 +211,8 @@
created_at: Math.floor(Date.now() / 1000),
pubkey: session.pubkey
}, relayUrls.length > 0 ? relayUrls : undefined);
publicationResults = result;
publicationModalOpen = true;
if (result.success.length > 0) {
// Reload votes after successful publish
@ -315,6 +320,8 @@ @@ -315,6 +320,8 @@
</div>
</div>
<PublicationStatusModal bind:open={publicationModalOpen} bind:results={publicationResults} />
<style>
.poll-card {
margin: 1rem 0;

7
src/lib/components/modals/EventJsonModal.svelte

@ -28,12 +28,6 @@ @@ -28,12 +28,6 @@
}
}
function selectAll() {
const textarea = document.querySelector('.json-textarea') as HTMLTextAreaElement;
if (textarea) {
textarea.select();
}
}
</script>
{#if open && event}
@ -69,7 +63,6 @@ @@ -69,7 +63,6 @@
class="json-textarea"
readonly
value={jsonText}
onclick={selectAll}
></textarea>
</div>

8
src/lib/components/modals/RelatedEventsModal.svelte

@ -108,13 +108,6 @@ @@ -108,13 +108,6 @@
}
}
function selectAll() {
const textarea = document.querySelector('.json-textarea') as HTMLTextAreaElement;
if (textarea) {
textarea.select();
}
}
// Load related events when modal opens
$effect(() => {
if (open && event && currentPubkey) {
@ -179,7 +172,6 @@ @@ -179,7 +172,6 @@
class="json-textarea"
readonly
value={jsonText}
onclick={selectAll}
></textarea>
{/if}
</div>

21
src/lib/components/profile/ProfileMenu.svelte

@ -269,6 +269,20 @@ @@ -269,6 +269,20 @@
closeMenu();
}
function cloneEvent() {
if (!profileEvent) return;
// Store event data in sessionStorage for the write page to pick up
const cloneData = {
kind: profileEvent.kind,
content: profileEvent.content,
tags: profileEvent.tags,
isClone: true
};
sessionStorage.setItem('aitherboard_cloneEvent', JSON.stringify(cloneData));
closeMenu();
goto('/write');
}
function seeBookmarks() {
if (onOpenBookmarks) {
onOpenBookmarks();
@ -349,6 +363,13 @@ @@ -349,6 +363,13 @@
<span class="menu-item-text">View Json</span>
</button>
{#if isLoggedIn && profileEvent}
<button class="menu-item" onclick={cloneEvent} role="menuitem">
<span class="menu-item-icon"></span>
<span class="menu-item-text">Edit/Clone this event</span>
</button>
{/if}
<div class="menu-divider"></div>
<button class="menu-item" onclick={shareWithAitherboard} role="menuitem">

26
src/lib/modules/discussions/DiscussionVoteButtons.svelte

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
import { KIND } from '../../types/kind-lookup.js';
import VoteCount from '../../components/content/VoteCount.svelte';
import { getCachedReactionsForEvents } from '../../services/cache/event-cache.js';
import PublicationStatusModal from '../../components/modals/PublicationStatusModal.svelte';
interface Props {
event: NostrEvent;
@ -28,6 +29,8 @@ @@ -28,6 +29,8 @@
let processingUpdate = $state(false);
let updateDebounceTimer: ReturnType<typeof setTimeout> | null = null;
let initialLoadComplete = $state(false); // Track when initial load is done
let publicationModalOpen = $state(false);
let publicationResults = $state<{ success: string[]; failed: Array<{ relay: string; error: string }> } | null>(null);
// Count upvotes and downvotes
let upvotes = $derived.by(() => {
@ -419,8 +422,10 @@ @@ -419,8 +422,10 @@
content: ''
};
const config = nostrClient.getConfig();
await signAndPublish(deletionEvent, [...config.defaultRelays]);
const relays = relayManager.getReactionPublishRelays();
const results = await signAndPublish(deletionEvent, relays);
publicationResults = results;
publicationModalOpen = true;
// Remove from map immediately so counts update
allReactionsMap.delete(reactionIdToDelete);
@ -454,8 +459,10 @@ @@ -454,8 +459,10 @@
content: ''
};
const config = nostrClient.getConfig();
await signAndPublish(deletionEvent, [...config.defaultRelays]);
const relays = relayManager.getReactionPublishRelays();
const results = await signAndPublish(deletionEvent, relays);
publicationResults = results;
publicationModalOpen = true;
// Remove from map immediately so counts update
// Reassign map to trigger reactivity in Svelte 5
@ -486,13 +493,14 @@ @@ -486,13 +493,14 @@
content
};
const config = nostrClient.getConfig();
// Sign the event first to get the ID
const signedEvent = await sessionManager.signEvent(reactionEvent);
// Publish the signed event
await nostrClient.publish(signedEvent, { relays: [...config.defaultRelays] });
// Publish the signed event using reaction publish relays (filters read-only relays)
const relays = relayManager.getReactionPublishRelays();
const results = await nostrClient.publish(signedEvent, { relays });
publicationResults = results;
publicationModalOpen = true;
// Update local state immediately for instant UI feedback
userReaction = content;
@ -536,6 +544,8 @@ @@ -536,6 +544,8 @@
/>
</div>
<PublicationStatusModal bind:open={publicationModalOpen} bind:results={publicationResults} />
<style>
.discussion-vote-buttons {
margin-top: 0.5rem;

20
src/lib/modules/reactions/FeedReactionButtons.svelte

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
import { shouldIncludeClientTag } from '../../services/client-tag-preference.js';
import Icon from '../../components/ui/Icon.svelte';
import { getCachedReactionsForEvents } from '../../services/cache/event-cache.js';
import PublicationStatusModal from '../../components/modals/PublicationStatusModal.svelte';
interface Props {
event: NostrEvent;
@ -37,6 +38,8 @@ @@ -37,6 +38,8 @@
let isMounted = $state(false);
let processingUpdate = $state(false);
let updateDebounceTimer: ReturnType<typeof setTimeout> | null = null;
let publicationModalOpen = $state(false);
let publicationResults = $state<{ success: string[]; failed: Array<{ relay: string; error: string }> } | null>(null);
onMount(() => {
// Set lastEventId immediately to prevent $effect from running during mount
@ -404,8 +407,10 @@ @@ -404,8 +407,10 @@
content: ''
};
const config = nostrClient.getConfig();
await signAndPublish(deletionEvent, [...config.defaultRelays]);
const relays = relayManager.getReactionPublishRelays();
const results = await signAndPublish(deletionEvent, relays);
publicationResults = results;
publicationModalOpen = true;
// Update local state
userReaction = null;
@ -463,13 +468,14 @@ @@ -463,13 +468,14 @@
content
};
const config = nostrClient.getConfig();
// Sign the event first to get the ID
const signedEvent = await sessionManager.signEvent(reactionEvent);
// Publish the signed event
await nostrClient.publish(signedEvent, { relays: [...config.defaultRelays] });
// Publish the signed event using reaction publish relays (filters read-only relays)
const relays = relayManager.getReactionPublishRelays();
const results = await nostrClient.publish(signedEvent, { relays });
publicationResults = results;
publicationModalOpen = true;
// Update local state with the new reaction
userReaction = content;
@ -657,6 +663,8 @@ @@ -657,6 +663,8 @@
{/each}
</div>
<PublicationStatusModal bind:open={publicationModalOpen} bind:results={publicationResults} />
<style>
.Feed-reaction-buttons {
margin-top: 0.5rem;

6
src/lib/services/nostr/config.ts

@ -29,6 +29,10 @@ const GIF_RELAYS = [ @@ -29,6 +29,10 @@ const GIF_RELAYS = [
"wss://thecitadel.nostr1.com"
];
const READ_ONLY_RELAYS = [
'wss://aggr.nostr.land' // Read-only aggregator
];
const RELAY_TIMEOUT = 10000;
// Fetch limits
@ -53,6 +57,7 @@ export interface NostrConfig { @@ -53,6 +57,7 @@ export interface NostrConfig {
threadPublishRelays: string[];
relayTimeout: number;
gifRelays: string[];
readOnlyRelays: string[];
// Fetch limits
feedLimit: number;
singleEventLimit: number;
@ -92,6 +97,7 @@ export function getConfig(): NostrConfig { @@ -92,6 +97,7 @@ export function getConfig(): NostrConfig {
threadPublishRelays: THREAD_PUBLISH_RELAYS,
relayTimeout: RELAY_TIMEOUT,
gifRelays: GIF_RELAYS,
readOnlyRelays: READ_ONLY_RELAYS,
// Fetch limits
feedLimit: parseIntEnv(import.meta.env.VITE_FEED_LIMIT, FEED_LIMIT, 1),
singleEventLimit: SINGLE_EVENT_LIMIT,

43
src/lib/services/user-actions.ts

@ -159,8 +159,9 @@ export function isHighlighted(eventId: string): boolean { @@ -159,8 +159,9 @@ export function isHighlighted(eventId: string): boolean {
/**
* Toggle pin status of an event
* Publishes kind 10001 list event (pins are stored in cache and on relays only)
* Returns publication results
*/
export async function togglePin(eventId: string): Promise<boolean> {
export async function togglePin(eventId: string): Promise<{ success: string[]; failed: Array<{ relay: string; error: string }> }> {
try {
const session = sessionManager.getSession();
if (!session) {
@ -179,27 +180,26 @@ export async function togglePin(eventId: string): Promise<boolean> { @@ -179,27 +180,26 @@ export async function togglePin(eventId: string): Promise<boolean> {
}
// Publish updated pin list event
await publishPinList(Array.from(currentPins));
const result = await publishPinList(Array.from(currentPins));
// Invalidate cache so next read gets fresh data
invalidatePinCache();
return !isCurrentlyPinned;
return result;
} catch (error) {
console.error('Failed to toggle pin:', error);
// Return current state on error
const currentPins = await getPinnedEvents();
return currentPins.has(eventId);
return { success: [], failed: [{ relay: 'unknown', error: error instanceof Error ? error.message : String(error) }] };
}
}
/**
* Publish pin list event (kind 10001)
* Returns publication results
*/
async function publishPinList(eventIds: string[]): Promise<void> {
async function publishPinList(eventIds: string[]): Promise<{ success: string[]; failed: Array<{ relay: string; error: string }> }> {
try {
const session = sessionManager.getSession();
if (!session) return;
if (!session) return { success: [], failed: [] };
// Deduplicate input eventIds first
const deduplicatedEventIds = Array.from(new Set(eventIds));
@ -236,7 +236,7 @@ async function publishPinList(eventIds: string[]): Promise<void> { @@ -236,7 +236,7 @@ async function publishPinList(eventIds: string[]): Promise<void> {
const removedEventIds = [...existingEventIds].filter(id => !deduplicatedEventIds.includes(id));
if (newEventIds.length === 0 && removedEventIds.length === 0 && existingLists.length > 0) {
return; // No changes, cancel operation
return { success: [], failed: [] }; // No changes, cancel operation
}
// Build final tags: preserve all a-tags, add/update e-tags
@ -293,17 +293,19 @@ async function publishPinList(eventIds: string[]): Promise<void> { @@ -293,17 +293,19 @@ async function publishPinList(eventIds: string[]): Promise<void> {
// Publish to write relays
const writeRelays = relayManager.getPublishRelays(relays, true);
await signAndPublish(listEvent, writeRelays);
return await signAndPublish(listEvent, writeRelays);
} catch (error) {
console.error('Failed to publish pin list:', error);
return { success: [], failed: [{ relay: 'unknown', error: error instanceof Error ? error.message : String(error) }] };
}
}
/**
* Toggle bookmark status of an event
* Publishes kind 10003 list event (bookmarks are stored in cache and on relays only)
* Returns publication results
*/
export async function toggleBookmark(eventId: string): Promise<boolean> {
export async function toggleBookmark(eventId: string): Promise<{ success: string[]; failed: Array<{ relay: string; error: string }> }> {
try {
const session = sessionManager.getSession();
if (!session) {
@ -322,27 +324,26 @@ export async function toggleBookmark(eventId: string): Promise<boolean> { @@ -322,27 +324,26 @@ export async function toggleBookmark(eventId: string): Promise<boolean> {
}
// Publish updated bookmark list event
await publishBookmarkList(Array.from(currentBookmarks));
const result = await publishBookmarkList(Array.from(currentBookmarks));
// Invalidate cache so next read gets fresh data
invalidateBookmarkCache();
return !isCurrentlyBookmarked;
return result;
} catch (error) {
console.error('Failed to toggle bookmark:', error);
// Return current state on error
const currentBookmarks = await getBookmarkedEvents();
return currentBookmarks.has(eventId);
return { success: [], failed: [{ relay: 'unknown', error: error instanceof Error ? error.message : String(error) }] };
}
}
/**
* Publish bookmark list event (kind 10003)
* Returns publication results
*/
async function publishBookmarkList(eventIds: string[]): Promise<void> {
async function publishBookmarkList(eventIds: string[]): Promise<{ success: string[]; failed: Array<{ relay: string; error: string }> }> {
try {
const session = sessionManager.getSession();
if (!session) return;
if (!session) return { success: [], failed: [] };
// Deduplicate input eventIds first
const deduplicatedEventIds = Array.from(new Set(eventIds));
@ -379,7 +380,7 @@ async function publishBookmarkList(eventIds: string[]): Promise<void> { @@ -379,7 +380,7 @@ async function publishBookmarkList(eventIds: string[]): Promise<void> {
const removedEventIds = [...existingEventIds].filter(id => !deduplicatedEventIds.includes(id));
if (newEventIds.length === 0 && removedEventIds.length === 0 && existingLists.length > 0) {
return; // No changes, cancel operation
return { success: [], failed: [] }; // No changes, cancel operation
}
// Build final tags: preserve all a-tags, add/update e-tags
@ -436,9 +437,11 @@ async function publishBookmarkList(eventIds: string[]): Promise<void> { @@ -436,9 +437,11 @@ async function publishBookmarkList(eventIds: string[]): Promise<void> {
// Publish to write relays
const writeRelays = relayManager.getPublishRelays(relays, true);
await signAndPublish(listEvent, writeRelays);
const result = await signAndPublish(listEvent, writeRelays);
return result;
} catch (error) {
console.error('Failed to publish bookmark list:', error);
return { success: [], failed: [{ relay: 'unknown', error: error instanceof Error ? error.message : String(error) }] };
}
}

23
src/routes/write/+page.svelte

@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
});
let initialContent = $state<string | null>(null);
let initialTags = $state<string[][] | null>(null);
let isCloneMode = $state(false);
// Subscribe to session changes to reactively update login status
let currentSession = $state(sessionManager.session.value);
@ -46,7 +47,22 @@ @@ -46,7 +47,22 @@
}
}
// Check for highlight data in sessionStorage
// Check for clone/edit event data in sessionStorage (takes priority)
const cloneDataStr = sessionStorage.getItem('aitherboard_cloneEvent');
if (cloneDataStr) {
try {
const cloneData = JSON.parse(cloneDataStr);
initialKind = cloneData.kind || null;
initialContent = cloneData.content || null;
initialTags = cloneData.tags || null;
isCloneMode = cloneData.isClone === true;
// Clear sessionStorage after reading
sessionStorage.removeItem('aitherboard_cloneEvent');
} catch (error) {
console.error('Error parsing clone event data:', error);
}
} else {
// Check for highlight data in sessionStorage (fallback)
const highlightDataStr = sessionStorage.getItem('aitherboard_highlightData');
if (highlightDataStr) {
try {
@ -59,6 +75,7 @@ @@ -59,6 +75,7 @@
console.error('Error parsing highlight data:', error);
}
}
}
});
</script>
@ -66,7 +83,9 @@ @@ -66,7 +83,9 @@
<main class="container mx-auto px-4 py-8">
<div class="write-page">
<h1 class="font-bold mb-6 text-fog-text dark:text-fog-dark-text font-mono" style="font-size: 1.5em;">/Write</h1>
<h1 class="font-bold mb-6 text-fog-text dark:text-fog-dark-text font-mono" style="font-size: 1.5em;">
{isCloneMode ? '/Write: Edit or Clone an event' : '/Write'}
</h1>
{#if !isLoggedIn}
<div class="login-prompt">

Loading…
Cancel
Save