libraryStores.js raw

   1  import { writable } from 'svelte/store';
   2  
   3  // ==================== Library Navigation ====================
   4  
   5  // Which library sub-view is active: "my-library" | "bookmarks" | "editor" | "reader"
   6  export const activeLibraryView = writable("my-library");
   7  
   8  // ==================== My Library ====================
   9  
  10  // User's root library index (kind 30040, d="library-root") resolved into a tree
  11  // Shape: { categories: [{ dtag, title, publications: [{ dtag, title, kind, sectionCount }] }] }
  12  export const userLibrary = writable(null);
  13  
  14  // Selected category d-tag (null = show all)
  15  export const selectedCategory = writable(null);
  16  
  17  // Selected publication d-tag (null = none, opens reader when set)
  18  export const selectedPublication = writable(null);
  19  
  20  // Loading state
  21  export const libraryLoading = writable(false);
  22  
  23  // ==================== Publication Reader ====================
  24  
  25  // Current publication index event (kind 30040)
  26  export const readerIndex = writable(null);
  27  
  28  // Current publication sections (kind 30041[]) in order
  29  export const readerSections = writable([]);
  30  
  31  // Currently viewed section index
  32  export const readerCurrentSection = writable(0);
  33  
  34  // ==================== Publication Editor ====================
  35  
  36  // Editor state
  37  export const editorState = writable({
  38      mode: "new",       // "new" | "edit"
  39      format: "markdown", // "markdown" | "asciidoc"
  40      title: "",
  41      dtag: "",
  42      sections: [],       // [{ dtag, title, content, modified }]
  43      currentSection: 0,
  44      isDirty: false,
  45      categoryDtag: null, // category to attach to
  46  });
  47  
  48  // ==================== Viewing Another User's Library ====================
  49  
  50  // Hex pubkey of the user whose library we're viewing (null = own library)
  51  export const viewingPubkey = writable(null);
  52  
  53  // Their resolved library tree (same shape as userLibrary)
  54  export const viewingLibrary = writable(null);
  55  
  56  // ==================== Bookmarks ====================
  57  
  58  // User's bookmark list (kind 10003) - array of event references
  59  export const bookmarkList = writable([]);
  60  
  61  // User's bookmark sets (kind 30003) - Map of d-tag -> { title, items[] }
  62  export const bookmarkSets = writable(new Map());
  63  
  64  // Bookmark loading state
  65  export const bookmarksLoading = writable(false);
  66  
  67  // ==================== Actions ====================
  68  
  69  /**
  70   * Reset library state (on logout)
  71   */
  72  export function resetLibraryState() {
  73      userLibrary.set(null);
  74      selectedCategory.set(null);
  75      selectedPublication.set(null);
  76      libraryLoading.set(false);
  77      readerIndex.set(null);
  78      readerSections.set([]);
  79      readerCurrentSection.set(0);
  80      editorState.set({
  81          mode: "new",
  82          format: "markdown",
  83          title: "",
  84          dtag: "",
  85          sections: [],
  86          currentSection: 0,
  87          isDirty: false,
  88          categoryDtag: null,
  89      });
  90      viewingPubkey.set(null);
  91      viewingLibrary.set(null);
  92      bookmarkList.set([]);
  93      bookmarkSets.set(new Map());
  94      bookmarksLoading.set(false);
  95  }
  96  
  97  /**
  98   * Open the publication reader
  99   * @param {object} indexEvent - Kind 30040 event
 100   * @param {Array} sections - Kind 30041 events in order
 101   */
 102  export function openReader(indexEvent, sections) {
 103      readerIndex.set(indexEvent);
 104      readerSections.set(sections);
 105      readerCurrentSection.set(0);
 106      activeLibraryView.set("reader");
 107  }
 108  
 109  /**
 110   * Open the publication editor for a new document
 111   * @param {string} format - "markdown" or "asciidoc"
 112   * @param {string|null} categoryDtag - Category to attach to
 113   */
 114  export function openNewEditor(format = "markdown", categoryDtag = null) {
 115      editorState.set({
 116          mode: "new",
 117          format,
 118          title: "",
 119          dtag: "",
 120          sections: [{ dtag: "", title: "Section 1", content: "", modified: false }],
 121          currentSection: 0,
 122          isDirty: false,
 123          categoryDtag,
 124      });
 125      activeLibraryView.set("editor");
 126  }
 127  
 128  /**
 129   * Open the publication editor for an existing document
 130   * @param {object} indexEvent - Kind 30040 event
 131   * @param {Array} sections - Kind 30041 events
 132   */
 133  export function openExistingEditor(indexEvent, sections) {
 134      const format = (indexEvent.tags || []).find(t => t[0] === "format")?.[1] || "markdown";
 135      const title = (indexEvent.tags || []).find(t => t[0] === "title")?.[1] || "";
 136      const dtag = (indexEvent.tags || []).find(t => t[0] === "d")?.[1] || "";
 137      editorState.set({
 138          mode: "edit",
 139          format,
 140          title,
 141          dtag,
 142          sections: sections.map(s => ({
 143              dtag: (s.tags || []).find(t => t[0] === "d")?.[1] || "",
 144              title: (s.tags || []).find(t => t[0] === "title")?.[1] || "",
 145              content: s.content || "",
 146              modified: false,
 147          })),
 148          currentSection: 0,
 149          isDirty: false,
 150          categoryDtag: null,
 151      });
 152      activeLibraryView.set("editor");
 153  }
 154