feat: multiple pages
This commit is contained in:
@@ -10,6 +10,19 @@ export type { StoredGraphState }
|
||||
/** BlockNote document: array of blocks (PartialBlock). Stored as JSON. */
|
||||
export type StoredLogosContent = Record<string, unknown>[]
|
||||
|
||||
/** Id for a Logos page or subpage. */
|
||||
export type LogosPageId = string
|
||||
|
||||
/** Metadata for one page or subpage in the Logos hierarchy (one level: page → subpages). */
|
||||
export type LogosPageMeta = {
|
||||
id: LogosPageId
|
||||
title: string
|
||||
/** null = top-level page; non-null = subpage under that page. */
|
||||
parentId: LogosPageId | null
|
||||
/** Order among siblings (same parent). */
|
||||
position: number
|
||||
}
|
||||
|
||||
/** One entry in the render-output cache (one per rendering node, overwritten on each update). */
|
||||
export type RenderOutputCacheEntry = {
|
||||
nodeId: string
|
||||
@@ -36,6 +49,8 @@ export const RECOLLECTION_VERSION = 1
|
||||
|
||||
const GRAPH_KEY_PREFIX = 'zui_graph_'
|
||||
const LOGOS_KEY_PREFIX = 'zui_logos_'
|
||||
const LOGOS_PAGE_TREE_PREFIX = 'zui_logos_pagetree_'
|
||||
const LOGOS_PAGE_CONTENT_PREFIX = 'zui_logos_page_'
|
||||
const RENDER_CACHE_KEY_PREFIX = 'zui_render_cache_'
|
||||
|
||||
function getGraphKey(recollectionId: string): string {
|
||||
@@ -46,6 +61,14 @@ function getLogosKey(recollectionId: string): string {
|
||||
return `${LOGOS_KEY_PREFIX}${recollectionId}`
|
||||
}
|
||||
|
||||
function getLogosPageTreeKey(recollectionId: string): string {
|
||||
return `${LOGOS_PAGE_TREE_PREFIX}${recollectionId}`
|
||||
}
|
||||
|
||||
function getLogosPageContentKey(recollectionId: string, pageId: LogosPageId): string {
|
||||
return `${LOGOS_PAGE_CONTENT_PREFIX}${recollectionId}_${pageId}`
|
||||
}
|
||||
|
||||
function getRenderCacheKey(recollectionId: string): string {
|
||||
return `${RENDER_CACHE_KEY_PREFIX}${recollectionId}`
|
||||
}
|
||||
@@ -89,6 +112,61 @@ export function setLogosContent(recollectionId: string, content: StoredLogosCont
|
||||
localStorage.setItem(getLogosKey(recollectionId), JSON.stringify(content))
|
||||
}
|
||||
|
||||
/** Logos page tree: ordered list of page metas (pages and subpages). */
|
||||
export function getLogosPageTree(recollectionId: string): LogosPageMeta[] {
|
||||
try {
|
||||
const raw = localStorage.getItem(getLogosPageTreeKey(recollectionId))
|
||||
if (!raw) return []
|
||||
const data = JSON.parse(raw) as unknown
|
||||
if (!Array.isArray(data)) return []
|
||||
return data.filter(
|
||||
(item): item is LogosPageMeta =>
|
||||
item != null &&
|
||||
typeof item === 'object' &&
|
||||
typeof (item as LogosPageMeta).id === 'string' &&
|
||||
typeof (item as LogosPageMeta).title === 'string' &&
|
||||
((item as LogosPageMeta).parentId === null || typeof (item as LogosPageMeta).parentId === 'string') &&
|
||||
typeof (item as LogosPageMeta).position === 'number'
|
||||
) as LogosPageMeta[]
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
export function setLogosPageTree(recollectionId: string, tree: LogosPageMeta[]): void {
|
||||
localStorage.setItem(getLogosPageTreeKey(recollectionId), JSON.stringify(tree))
|
||||
}
|
||||
|
||||
/** Per-page Logos content (for page/subpage hierarchy). */
|
||||
export function getLogosContentForPage(
|
||||
recollectionId: string,
|
||||
pageId: LogosPageId
|
||||
): StoredLogosContent | null {
|
||||
try {
|
||||
const raw = localStorage.getItem(getLogosPageContentKey(recollectionId, pageId))
|
||||
if (!raw) return null
|
||||
const data = JSON.parse(raw) as unknown
|
||||
if (!Array.isArray(data)) return null
|
||||
if (!data.every((item) => item != null && typeof item === 'object')) return null
|
||||
return data as StoredLogosContent
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function setLogosContentForPage(
|
||||
recollectionId: string,
|
||||
pageId: LogosPageId,
|
||||
content: StoredLogosContent
|
||||
): void {
|
||||
localStorage.setItem(getLogosPageContentKey(recollectionId, pageId), JSON.stringify(content))
|
||||
}
|
||||
|
||||
/** Remove stored content for a single page (e.g. when deleting that page). */
|
||||
export function removeLogosPageContent(recollectionId: string, pageId: LogosPageId): void {
|
||||
localStorage.removeItem(getLogosPageContentKey(recollectionId, pageId))
|
||||
}
|
||||
|
||||
/** Render output cache: one entry per rendering node (keyed by nodeId). Used by Logos "Insert from Flux" block. */
|
||||
export function getRenderOutputCache(recollectionId: string): RenderOutputCacheEntry[] {
|
||||
try {
|
||||
@@ -120,9 +198,14 @@ export function upsertRenderOutputEntry(recollectionId: string, entry: RenderOut
|
||||
)
|
||||
}
|
||||
|
||||
/** Removes both graph, logos, and render cache data for the recollection. */
|
||||
/** Removes both graph, logos (legacy + page tree + all per-page content), and render cache for the recollection. */
|
||||
export function removeRecollectionData(recollectionId: string): void {
|
||||
localStorage.removeItem(getGraphKey(recollectionId))
|
||||
localStorage.removeItem(getLogosKey(recollectionId))
|
||||
const tree = getLogosPageTree(recollectionId)
|
||||
for (const page of tree) {
|
||||
removeLogosPageContent(recollectionId, page.id)
|
||||
}
|
||||
localStorage.removeItem(getLogosPageTreeKey(recollectionId))
|
||||
localStorage.removeItem(getRenderCacheKey(recollectionId))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user