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.
 
 
 
 
 

209 lines
5.5 KiB

<script lang="ts">
import { getBookmarkedEvents } from '../../services/user-actions.js';
import { nostrClient } from '../../services/nostr/nostr-client.js';
import { relayManager } from '../../services/nostr/relay-manager.js';
import { sessionManager } from '../../services/auth/session-manager.js';
import FeedPost from '../../modules/feed/FeedPost.svelte';
import { onMount } from 'svelte';
import type { NostrEvent } from '../../types/nostr.js';
import { KIND } from '../../types/kind-lookup.js';
import { goto } from '$app/navigation';
interface Props {
isOpen: boolean;
onClose: () => void;
}
let { isOpen, onClose }: Props = $props();
let bookmarkedEvents = $state<NostrEvent[]>([]);
let loading = $state(true);
function navigateToEvent(event: NostrEvent) {
goto(`/event/${event.id}`);
}
$effect(() => {
if (isOpen) {
loadBookmarks();
}
});
async function loadBookmarks() {
loading = true;
try {
// Get bookmarks from published kind 10003 event (from cache/relays)
const allBookmarkedIds = await getBookmarkedEvents();
console.log('[BookmarksPanel] Total bookmarked IDs to fetch:', allBookmarkedIds.size, Array.from(allBookmarkedIds));
if (allBookmarkedIds.size === 0) {
bookmarkedEvents = [];
loading = false;
return;
}
const profileRelays = relayManager.getProfileReadRelays();
const events = await nostrClient.fetchEvents(
[{ ids: Array.from(allBookmarkedIds), limit: 100 }],
profileRelays,
{ useCache: true, cacheResults: true, timeout: 10000 }
);
console.log('[BookmarksPanel] Fetched', events.length, 'events out of', allBookmarkedIds.size, 'bookmarked IDs');
// Log which IDs were not found
const foundIds = new Set(events.map(e => e.id));
const missingIds = Array.from(allBookmarkedIds).filter(id => !foundIds.has(id));
if (missingIds.length > 0) {
console.warn('[BookmarksPanel] Could not find events for these bookmarked IDs:', missingIds);
}
// Sort by created_at descending
bookmarkedEvents = events.sort((a, b) => b.created_at - a.created_at);
} catch (error) {
console.error('Error loading bookmarks:', error);
bookmarkedEvents = [];
} finally {
loading = false;
}
}
</script>
{#if isOpen}
<div
class="bookmarks-panel-overlay"
onclick={(e) => {
// Only close if clicking directly on the overlay, not on the panel
if (e.target === e.currentTarget) {
onClose();
}
}}
onkeydown={(e) => {
if (e.key === 'Escape') {
onClose();
}
}}
role="dialog"
aria-modal="true"
aria-label="Bookmarks panel"
tabindex="-1"
>
<div
class="bookmarks-panel"
>
<div class="bookmarks-panel-header">
<h2 class="bookmarks-panel-title">Bookmarks</h2>
<button class="bookmarks-panel-close" onclick={onClose} aria-label="Close bookmarks">
</button>
</div>
<div class="bookmarks-panel-content">
{#if loading}
<p class="text-fog-text-light dark:text-fog-dark-text-light">Loading bookmarks...</p>
{:else if bookmarkedEvents.length === 0}
<p class="text-fog-text-light dark:text-fog-dark-text-light">No bookmarks yet.</p>
{:else}
<div class="bookmarks-list">
{#each bookmarkedEvents as event (event.id)}
<FeedPost post={event} onOpenEvent={navigateToEvent} />
{/each}
</div>
{/if}
</div>
</div>
</div>
{/if}
<style>
.bookmarks-panel-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
align-items: stretch;
}
.bookmarks-panel {
width: 400px;
max-width: 90vw;
background: var(--fog-post, #ffffff);
border-right: 1px solid var(--fog-border, #e5e7eb);
display: flex;
flex-direction: column;
overflow: hidden;
}
:global(.dark) .bookmarks-panel {
background: var(--fog-dark-post, #1f2937);
border-right-color: var(--fog-dark-border, #374151);
}
.bookmarks-panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
border-bottom: 1px solid var(--fog-border, #e5e7eb);
}
:global(.dark) .bookmarks-panel-header {
border-bottom-color: var(--fog-dark-border, #374151);
}
.bookmarks-panel-title {
margin: 0;
font-size: 1.25rem;
font-weight: 600;
color: var(--fog-text, #1f2937);
}
:global(.dark) .bookmarks-panel-title {
color: var(--fog-dark-text, #f9fafb);
}
.bookmarks-panel-close {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: var(--fog-text-light, #6b7280);
padding: 0;
width: 2rem;
height: 2rem;
display: flex;
align-items: center;
justify-content: center;
border-radius: 0.25rem;
transition: background 0.2s;
}
:global(.dark) .bookmarks-panel-close {
color: var(--fog-dark-text-light, #9ca3af);
}
.bookmarks-panel-close:hover {
background: var(--fog-highlight, #f3f4f6);
}
:global(.dark) .bookmarks-panel-close:hover {
background: var(--fog-dark-highlight, #374151);
}
.bookmarks-panel-content {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
.bookmarks-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
</style>