mirror of
https://github.com/hoornet/vega.git
synced 2026-05-07 04:39:12 -07:00
Bump to v0.4.0 — Phase 3: image lightbox, bookmarks, discover, language filter, UI polish
This commit is contained in:
61
src/stores/bookmark.ts
Normal file
61
src/stores/bookmark.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { create } from "zustand";
|
||||
import { fetchBookmarkList, publishBookmarkList } from "../lib/nostr";
|
||||
|
||||
const STORAGE_KEY = "wrystr_bookmarks";
|
||||
|
||||
function loadLocal(): string[] {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "[]");
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function saveLocal(ids: string[]) {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(ids));
|
||||
}
|
||||
|
||||
interface BookmarkState {
|
||||
bookmarkedIds: string[];
|
||||
fetchBookmarks: (pubkey: string) => Promise<void>;
|
||||
addBookmark: (eventId: string) => Promise<void>;
|
||||
removeBookmark: (eventId: string) => Promise<void>;
|
||||
isBookmarked: (eventId: string) => boolean;
|
||||
}
|
||||
|
||||
export const useBookmarkStore = create<BookmarkState>((set, get) => ({
|
||||
bookmarkedIds: loadLocal(),
|
||||
|
||||
fetchBookmarks: async (pubkey: string) => {
|
||||
try {
|
||||
const ids = await fetchBookmarkList(pubkey);
|
||||
if (ids.length === 0) return;
|
||||
const local = get().bookmarkedIds;
|
||||
const merged = Array.from(new Set([...ids, ...local]));
|
||||
set({ bookmarkedIds: merged });
|
||||
saveLocal(merged);
|
||||
} catch {
|
||||
// Non-critical — local bookmarks still work
|
||||
}
|
||||
},
|
||||
|
||||
addBookmark: async (eventId: string) => {
|
||||
const { bookmarkedIds } = get();
|
||||
if (bookmarkedIds.includes(eventId)) return;
|
||||
const updated = [...bookmarkedIds, eventId];
|
||||
set({ bookmarkedIds: updated });
|
||||
saveLocal(updated);
|
||||
publishBookmarkList(updated).catch(() => {});
|
||||
},
|
||||
|
||||
removeBookmark: async (eventId: string) => {
|
||||
const updated = get().bookmarkedIds.filter((id) => id !== eventId);
|
||||
set({ bookmarkedIds: updated });
|
||||
saveLocal(updated);
|
||||
publishBookmarkList(updated).catch(() => {});
|
||||
},
|
||||
|
||||
isBookmarked: (eventId: string) => {
|
||||
return get().bookmarkedIds.includes(eventId);
|
||||
},
|
||||
}));
|
||||
@@ -2,7 +2,7 @@ import { create } from "zustand";
|
||||
|
||||
import { NDKEvent } from "@nostr-dev-kit/ndk";
|
||||
|
||||
type View = "feed" | "search" | "relays" | "settings" | "profile" | "thread" | "article-editor" | "article" | "about" | "zaps" | "dm" | "notifications";
|
||||
type View = "feed" | "search" | "relays" | "settings" | "profile" | "thread" | "article-editor" | "article" | "about" | "zaps" | "dm" | "notifications" | "bookmarks";
|
||||
type FeedTab = "global" | "following";
|
||||
|
||||
interface UIState {
|
||||
@@ -16,6 +16,7 @@ interface UIState {
|
||||
pendingDMPubkey: string | null;
|
||||
pendingArticleNaddr: string | null;
|
||||
showHelp: boolean;
|
||||
feedLanguageFilter: string | null;
|
||||
setView: (view: View) => void;
|
||||
setFeedTab: (tab: FeedTab) => void;
|
||||
openProfile: (pubkey: string) => void;
|
||||
@@ -24,6 +25,7 @@ interface UIState {
|
||||
openDM: (pubkey: string) => void;
|
||||
openArticle: (naddr: string) => void;
|
||||
goBack: () => void;
|
||||
setFeedLanguageFilter: (filter: string | null) => void;
|
||||
toggleSidebar: () => void;
|
||||
toggleHelp: () => void;
|
||||
}
|
||||
@@ -41,6 +43,7 @@ export const useUIStore = create<UIState>((set, _get) => ({
|
||||
pendingDMPubkey: null,
|
||||
pendingArticleNaddr: null,
|
||||
showHelp: false,
|
||||
feedLanguageFilter: null,
|
||||
setView: (currentView) => set({ currentView }),
|
||||
setFeedTab: (feedTab) => set({ feedTab }),
|
||||
openProfile: (pubkey) => set((s) => ({ currentView: "profile", selectedPubkey: pubkey, previousView: s.currentView as View })),
|
||||
@@ -53,6 +56,7 @@ export const useUIStore = create<UIState>((set, _get) => ({
|
||||
currentView: s.previousView !== s.currentView ? s.previousView : "feed",
|
||||
selectedNote: null,
|
||||
})),
|
||||
setFeedLanguageFilter: (feedLanguageFilter) => set({ feedLanguageFilter }),
|
||||
toggleSidebar: () => set((s) => {
|
||||
const next = !s.sidebarCollapsed;
|
||||
localStorage.setItem(SIDEBAR_KEY, String(next));
|
||||
|
||||
Reference in New Issue
Block a user