Fix I-1: landing-page edits lost when activePageId goes dangling
buildSavePayload matched the active page by page.id === activePageId, but activePageId defaults to the hardcoded 'home' and load() never updated it. Deleting the original Home page (its replacement gets id page_<ts>), reloading, editing, and saving would then match no page -- the live edit only reached the legacy top-level craft_state, while the authoritative pages[]/pages_craft_state[0] for index.html fell back to stale state. Belt-and-suspenders fix: - buildSavePayload now falls back to pages[0] as the effective active page when a real page is active but activePageId matches nothing. - useWhpApi's load() now points activePageId at the freshly restored first page via a new PageContext setActivePageIdDirect setter (bookkeeping only -- no re-serialize/deserialize), so activePageId stays valid after every load. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,17 @@ interface PageContextValue {
|
||||
setHeaderCraftState: (craftState: string) => void;
|
||||
setFooterCraftState: (craftState: string) => void;
|
||||
setPagesCraftState: (pagesData: { id: string; name: string; slug: string; craftState: string | null }[]) => void;
|
||||
/**
|
||||
* Bookkeeping-only: point `activePageId` at an already-loaded page without
|
||||
* re-serializing/deserializing the canvas (the caller -- e.g. useWhpApi's
|
||||
* `load()` -- has already put the right state on the canvas itself). Used
|
||||
* to fix I-1: `activePageId` defaults to the hardcoded `'home'` and
|
||||
* `load()` never updated it, so after the original Home page was deleted
|
||||
* (its replacement gets a fresh `page_<ts>` id) and the app reloaded,
|
||||
* `activePageId` pointed at nothing in `pages`, and a subsequent edit+save
|
||||
* only reached the legacy top-level fields.
|
||||
*/
|
||||
setActivePageIdDirect: (pageId: string) => void;
|
||||
/** AI helpers — replace entire site or page with a new tree */
|
||||
replaceAllPages: (pages: { name: string; tree: SerializedTreeNode }[]) => void;
|
||||
replaceCurrentPage: (page: { name: string; tree: SerializedTreeNode }) => void;
|
||||
@@ -149,6 +160,7 @@ const PageContext = createContext<PageContextValue>({
|
||||
setHeaderCraftState: () => {},
|
||||
setFooterCraftState: () => {},
|
||||
setPagesCraftState: () => {},
|
||||
setActivePageIdDirect: () => {},
|
||||
replaceAllPages: () => {},
|
||||
replaceCurrentPage: () => {},
|
||||
setHeader: () => {},
|
||||
@@ -385,6 +397,16 @@ export const PageProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
||||
setFooterPage((prev) => ({ ...prev, craftState }));
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Bookkeeping-only setter for `activePageId` -- see the doc comment on
|
||||
* `PageContextValue.setActivePageIdDirect`. Does NOT serialize/deserialize
|
||||
* the canvas; callers that need that should use `switchPage` instead.
|
||||
*/
|
||||
const setActivePageIdDirect = useCallback((pageId: string) => {
|
||||
setActivePageId(pageId);
|
||||
activePageIdRef.current = pageId;
|
||||
}, []);
|
||||
|
||||
/** Allow external code (e.g., load from API) to restore pages with craft states */
|
||||
const setPagesCraftState = useCallback((pagesData: { id: string; name: string; slug: string; craftState: string | null }[]) => {
|
||||
setPages(pagesData.map((p, i) => ({
|
||||
@@ -492,6 +514,7 @@ export const PageProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
||||
setHeaderCraftState,
|
||||
setFooterCraftState,
|
||||
setPagesCraftState,
|
||||
setActivePageIdDirect,
|
||||
replaceAllPages,
|
||||
replaceCurrentPage,
|
||||
setHeader,
|
||||
|
||||
Reference in New Issue
Block a user