From d38423f26616102a8f0d3288618baae929584210 Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Tue, 23 Dec 2025 17:18:52 +0900 Subject: [PATCH 01/11] naive direct landing impl (without history adjustment) --- .../src/historySyncPlugin.tsx | 208 ++++++++++++------ 1 file changed, 145 insertions(+), 63 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 507473121..6a5e50ce7 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -64,6 +64,7 @@ type HistorySyncPluginOptions> = ( useHash?: boolean; history?: History; urlPatternOptions?: UrlPatternOptions; + disableDefaultHistorySetupTransition?: boolean; }; export function historySyncPlugin< @@ -258,78 +259,159 @@ export function historySyncPlugin< const defaultHistory = targetActivityRoute.defaultHistory?.(params) ?? []; - initialSetupProcess = new SerialNavigationProcess([ - ...defaultHistory.map( - ({ activityName, activityParams, additionalSteps = [] }) => - () => { - const events: ( - | Omit - | Omit - )[] = [ - { - name: "Pushed", - id: id(), - activityId: id(), - activityName, - activityParams: { - ...activityParams, - }, - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, - }, - }, - }, - ...additionalSteps.map( - ({ - stepParams, - hasZIndex, - }): Omit => ({ - name: "StepPushed", - id: id(), - stepId: id(), - stepParams, - hasZIndex, - }), - ), - ]; - - for (const event of events) { - if (event.name === "Pushed") { + if (options.disableDefaultHistorySetupTransition) { + initialSetupProcess = new SerialNavigationProcess([ + () => { + const events: ( + | Omit + | Omit + )[] = [ + ...defaultHistory.flatMap( + ({ activityName, activityParams, additionalSteps = [] }) => { + const activityId = id(); + activityActivationMonitors.push( new DefaultHistoryActivityActivationMonitor( - event.activityId, + activityId, initialSetupProcess!, ), ); + + const events: ( + | Omit + | Omit + )[] = [ + { + name: "Pushed", + id: id(), + activityId, + activityName, + activityParams: { + ...activityParams, + }, + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, + }, + }, + skipEnterActiveState: true, + }, + ...additionalSteps.map( + ({ + stepParams, + hasZIndex, + }): Omit => ({ + name: "StepPushed", + id: id(), + stepId: id(), + stepParams, + hasZIndex, + }), + ), + ]; + + return events; + }, + ), + { + name: "Pushed", + id: id(), + activityId: id(), + activityName: targetActivityRoute.activityName, + activityParams: + makeTemplate( + targetActivityRoute, + options.urlPatternOptions, + ).parse(currentPath) ?? + urlSearchParamsToMap(pathToUrl(currentPath).searchParams), + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, + }, + }, + skipEnterActiveState: true, + }, + ]; + + return events; + }, + ]); + } else { + initialSetupProcess = new SerialNavigationProcess([ + ...defaultHistory.map( + ({ activityName, activityParams, additionalSteps = [] }) => + () => { + const events: ( + | Omit + | Omit + )[] = [ + { + name: "Pushed", + id: id(), + activityId: id(), + activityName, + activityParams: { + ...activityParams, + }, + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, + }, + }, + }, + ...additionalSteps.map( + ({ + stepParams, + hasZIndex, + }): Omit => ({ + name: "StepPushed", + id: id(), + stepId: id(), + stepParams, + hasZIndex, + }), + ), + ]; + + for (const event of events) { + if (event.name === "Pushed") { + activityActivationMonitors.push( + new DefaultHistoryActivityActivationMonitor( + event.activityId, + initialSetupProcess!, + ), + ); + } } - } - return events; - }, - ), - () => [ - { - name: "Pushed", - id: id(), - activityId: id(), - activityName: targetActivityRoute.activityName, - activityParams: - makeTemplate( - targetActivityRoute, - options.urlPatternOptions, - ).parse(currentPath) ?? - urlSearchParamsToMap(pathToUrl(currentPath).searchParams), - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, + return events; + }, + ), + () => [ + { + name: "Pushed", + id: id(), + activityId: id(), + activityName: targetActivityRoute.activityName, + activityParams: + makeTemplate( + targetActivityRoute, + options.urlPatternOptions, + ).parse(currentPath) ?? + urlSearchParamsToMap(pathToUrl(currentPath).searchParams), + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, + }, }, }, - }, - ], - ]); + ], + ]); + } return initialSetupProcess .captureNavigationOpportunity(null) From 8ac735a133255ce377e05872e395852cf90f08b4 Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Tue, 23 Dec 2025 17:58:39 +0900 Subject: [PATCH 02/11] adjust browsing history after initialization --- .../src/historySyncPlugin.tsx | 92 +++++++++++++++---- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 6a5e50ce7..13c2f8a58 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -415,36 +415,80 @@ export function historySyncPlugin< return initialSetupProcess .captureNavigationOpportunity(null) - .map((event) => ({ + .map((event, index) => ({ ...event, - eventDate: Date.now() - MINUTE, + eventDate: Date.now() - MINUTE + index, })); }, onInit({ actions: { getStack, dispatchEvent, push, stepPush } }) { const stack = getStack(); - const rootActivity = stack.activities[0]; - const match = activityRoutes.find( - (r) => r.activityName === rootActivity.name, - )!; - const template = makeTemplate(match, options.urlPatternOptions); + for (const activity of stack.activities) { + if ( + activity.transitionState === "enter-done" || + activity.transitionState === "enter-active" + ) { + const match = activityRoutes.find( + (r) => r.activityName === activity.name, + )!; + const template = makeTemplate(match, options.urlPatternOptions); - const lastStep = last(rootActivity.steps); + if (activity.isRoot) { + requestHistoryTick(() => { + silentFlag = true; + console.log("replaceActivity", activity); + replaceState({ + history, + pathname: template.fill(activity.params), + state: { + activity: activity, + step: activity.steps[0], + }, + useHash: options.useHash, + }); + console.log("silentFlag - after", silentFlag); + }); + } else { + requestHistoryTick(() => { + silentFlag = true; + console.log("pushActivity", activity); + pushState({ + history, + pathname: template.fill(activity.params), + state: { + activity: activity, + step: activity.steps[0], + }, + useHash: options.useHash, + }); + console.log("silentFlag - after", silentFlag); + }); + } - requestHistoryTick(() => { - silentFlag = true; - replaceState({ - history, - pathname: template.fill(rootActivity.params), - state: { - activity: rootActivity, - step: lastStep, - }, - useHash: options.useHash, - }); - }); + for (const step of activity.steps) { + if (!step.exitedBy && step.enteredBy.name !== "Pushed") { + requestHistoryTick(() => { + console.log("pushStep", step); + silentFlag = true; + pushState({ + history, + pathname: template.fill(activity.params), + state: { + activity: activity, + step: step, + }, + useHash: options.useHash, + }); + console.log("silentFlag - after", silentFlag); + }); + } + } + } + } const onPopState: Listener = (e) => { + console.log("onPopState", e); + console.log("silentFlag", silentFlag); if (silentFlag) { silentFlag = false; return; @@ -603,6 +647,7 @@ export function historySyncPlugin< }, useHash: options.useHash, }); + console.log("silentFlag - after / onPushed", silentFlag); }); }, onStepPushed({ effect: { activity, step } }) { @@ -628,6 +673,7 @@ export function historySyncPlugin< }, useHash: options.useHash, }); + console.log("silentFlag - after / onStepPushed", silentFlag); }); }, onReplaced({ effect: { activity } }) { @@ -651,6 +697,7 @@ export function historySyncPlugin< }, useHash: options.useHash, }); + console.log("silentFlag - after / onReplaced", silentFlag); }); }, onStepReplaced({ effect: { activity, step } }) { @@ -675,6 +722,7 @@ export function historySyncPlugin< }, useHash: options.useHash, }); + console.log("silentFlag - after / onStepReplaced", silentFlag); }); }, onBeforePush({ actionParams, actions: { overrideActionParams } }) { @@ -758,6 +806,7 @@ export function historySyncPlugin< if ((currentActivity?.steps.length ?? 0) > 1) { requestHistoryTick(() => { silentFlag = true; + console.log("silentFlag - before / onBeforeStepPop", silentFlag); history.back(); }); } @@ -786,6 +835,7 @@ export function historySyncPlugin< requestHistoryTick(() => { silentFlag = true; history.back(); + console.log("silentFlag - before / onBeforePop", silentFlag); }); } } @@ -793,6 +843,8 @@ export function historySyncPlugin< onChanged({ actions: { getStack, push, stepPush } }) { const stack = getStack(); + console.log("stack", stack); + initialSetupProcess ?.captureNavigationOpportunity(stack) .forEach((event) => From 7ae6c10a3079eaa9a1475de9c7ad51ff4c64b1da Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Tue, 23 Dec 2025 18:03:45 +0900 Subject: [PATCH 03/11] cleanup console.log --- .../src/historySyncPlugin.tsx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 13c2f8a58..65ca4f306 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -436,7 +436,6 @@ export function historySyncPlugin< if (activity.isRoot) { requestHistoryTick(() => { silentFlag = true; - console.log("replaceActivity", activity); replaceState({ history, pathname: template.fill(activity.params), @@ -446,12 +445,10 @@ export function historySyncPlugin< }, useHash: options.useHash, }); - console.log("silentFlag - after", silentFlag); }); } else { requestHistoryTick(() => { silentFlag = true; - console.log("pushActivity", activity); pushState({ history, pathname: template.fill(activity.params), @@ -461,14 +458,12 @@ export function historySyncPlugin< }, useHash: options.useHash, }); - console.log("silentFlag - after", silentFlag); }); } for (const step of activity.steps) { if (!step.exitedBy && step.enteredBy.name !== "Pushed") { requestHistoryTick(() => { - console.log("pushStep", step); silentFlag = true; pushState({ history, @@ -479,7 +474,6 @@ export function historySyncPlugin< }, useHash: options.useHash, }); - console.log("silentFlag - after", silentFlag); }); } } @@ -487,8 +481,6 @@ export function historySyncPlugin< } const onPopState: Listener = (e) => { - console.log("onPopState", e); - console.log("silentFlag", silentFlag); if (silentFlag) { silentFlag = false; return; @@ -647,7 +639,6 @@ export function historySyncPlugin< }, useHash: options.useHash, }); - console.log("silentFlag - after / onPushed", silentFlag); }); }, onStepPushed({ effect: { activity, step } }) { @@ -673,7 +664,6 @@ export function historySyncPlugin< }, useHash: options.useHash, }); - console.log("silentFlag - after / onStepPushed", silentFlag); }); }, onReplaced({ effect: { activity } }) { @@ -697,7 +687,6 @@ export function historySyncPlugin< }, useHash: options.useHash, }); - console.log("silentFlag - after / onReplaced", silentFlag); }); }, onStepReplaced({ effect: { activity, step } }) { @@ -722,7 +711,6 @@ export function historySyncPlugin< }, useHash: options.useHash, }); - console.log("silentFlag - after / onStepReplaced", silentFlag); }); }, onBeforePush({ actionParams, actions: { overrideActionParams } }) { @@ -806,7 +794,6 @@ export function historySyncPlugin< if ((currentActivity?.steps.length ?? 0) > 1) { requestHistoryTick(() => { silentFlag = true; - console.log("silentFlag - before / onBeforeStepPop", silentFlag); history.back(); }); } @@ -835,7 +822,6 @@ export function historySyncPlugin< requestHistoryTick(() => { silentFlag = true; history.back(); - console.log("silentFlag - before / onBeforePop", silentFlag); }); } } @@ -843,8 +829,6 @@ export function historySyncPlugin< onChanged({ actions: { getStack, push, stepPush } }) { const stack = getStack(); - console.log("stack", stack); - initialSetupProcess ?.captureNavigationOpportunity(stack) .forEach((event) => From 0ef20094142a4a74c29a3d65c85f0467c11f4db9 Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 12:55:25 +0900 Subject: [PATCH 04/11] rename option --- extensions/plugin-history-sync/src/historySyncPlugin.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 65ca4f306..6fc2463a2 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -64,7 +64,7 @@ type HistorySyncPluginOptions> = ( useHash?: boolean; history?: History; urlPatternOptions?: UrlPatternOptions; - disableDefaultHistorySetupTransition?: boolean; + skipDefaultHistorySetupTransition?: boolean; }; export function historySyncPlugin< @@ -259,7 +259,7 @@ export function historySyncPlugin< const defaultHistory = targetActivityRoute.defaultHistory?.(params) ?? []; - if (options.disableDefaultHistorySetupTransition) { + if (options.skipDefaultHistorySetupTransition) { initialSetupProcess = new SerialNavigationProcess([ () => { const events: ( From 91277f199b4390a3b9cbc06cd665c32d0b69539c Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 16:28:51 +0900 Subject: [PATCH 05/11] reformat --- .../src/historySyncPlugin.tsx | 140 +++++++++--------- 1 file changed, 69 insertions(+), 71 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 6fc2463a2..068d0e48a 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -261,82 +261,80 @@ export function historySyncPlugin< if (options.skipDefaultHistorySetupTransition) { initialSetupProcess = new SerialNavigationProcess([ - () => { - const events: ( - | Omit - | Omit - )[] = [ - ...defaultHistory.flatMap( - ({ activityName, activityParams, additionalSteps = [] }) => { - const activityId = id(); - - activityActivationMonitors.push( - new DefaultHistoryActivityActivationMonitor( - activityId, - initialSetupProcess!, - ), - ); - - const events: ( - | Omit - | Omit - )[] = [ - { - name: "Pushed", - id: id(), - activityId, - activityName, - activityParams: { - ...activityParams, - }, - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, - }, + (): ( + | Omit + | Omit + )[] => [ + ...defaultHistory.flatMap( + ({ + activityName, + activityParams, + additionalSteps = [], + }): ( + | Omit + | Omit + )[] => { + const activityId = id(); + + activityActivationMonitors.push( + new DefaultHistoryActivityActivationMonitor( + activityId, + initialSetupProcess!, + ), + ); + + return [ + { + name: "Pushed", + id: id(), + activityId, + activityName, + activityParams: { + ...activityParams, + }, + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, }, - skipEnterActiveState: true, }, - ...additionalSteps.map( - ({ - stepParams, - hasZIndex, - }): Omit => ({ - name: "StepPushed", - id: id(), - stepId: id(), - stepParams, - hasZIndex, - }), - ), - ]; - - return events; - }, - ), - { - name: "Pushed", - id: id(), - activityId: id(), - activityName: targetActivityRoute.activityName, - activityParams: - makeTemplate( - targetActivityRoute, - options.urlPatternOptions, - ).parse(currentPath) ?? - urlSearchParamsToMap(pathToUrl(currentPath).searchParams), - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, + skipEnterActiveState: true, }, + ...additionalSteps.map( + ({ + stepParams, + hasZIndex, + }): Omit => ({ + name: "StepPushed", + id: id(), + stepId: id(), + stepParams, + hasZIndex, + }), + ), + ]; + }, + ), + { + name: "Pushed", + id: id(), + activityId: id(), + activityName: targetActivityRoute.activityName, + activityParams: + makeTemplate( + targetActivityRoute, + options.urlPatternOptions, + ).parse(currentPath) ?? + urlSearchParamsToMap(pathToUrl(currentPath).searchParams), + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, }, - skipEnterActiveState: true, }, - ]; - - return events; - }, + skipEnterActiveState: true, + }, + ], ]); } else { initialSetupProcess = new SerialNavigationProcess([ From 9d0f3a3ced43b96862f5fd49a3f4910aded0b3df Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 16:45:10 +0900 Subject: [PATCH 06/11] simplify --- .../src/historySyncPlugin.tsx | 215 +++++++----------- 1 file changed, 83 insertions(+), 132 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 068d0e48a..11f177833 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -28,7 +28,7 @@ import type { NavigationProcess } from "./NavigationProcess/NavigationProcess"; import { SerialNavigationProcess } from "./NavigationProcess/SerialNavigationProcess"; import { normalizeActivityRouteMap } from "./normalizeActivityRouteMap"; import { Publisher } from "./Publisher"; -import type { RouteLike } from "./RouteLike"; +import type { HistoryEntry, RouteLike } from "./RouteLike"; import { RoutesProvider } from "./RoutesContext"; import { sortActivityRoutes } from "./sortActivityRoutes"; @@ -258,156 +258,107 @@ export function historySyncPlugin< }; const defaultHistory = targetActivityRoute.defaultHistory?.(params) ?? []; + const historyEntryToEvents = ({ + activityName, + activityParams, + additionalSteps = [], + }: HistoryEntry): ( + | Omit + | Omit + )[] => [ + { + name: "Pushed", + id: id(), + activityId: id(), + activityName, + activityParams: { + ...activityParams, + }, + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, + }, + }, + }, + ...additionalSteps.map( + ({ + stepParams, + hasZIndex, + }): Omit => ({ + name: "StepPushed", + id: id(), + stepId: id(), + stepParams, + hasZIndex, + }), + ), + ]; + const createTargetActivityPushEvent = (): Omit< + PushedEvent, + "eventDate" + > => ({ + name: "Pushed", + id: id(), + activityId: id(), + activityName: targetActivityRoute.activityName, + activityParams: + makeTemplate(targetActivityRoute, options.urlPatternOptions).parse( + currentPath, + ) ?? urlSearchParamsToMap(pathToUrl(currentPath).searchParams), + activityContext: { + path: currentPath, + lazyActivityComponentRenderContext: { + shouldRenderImmediately: true, + }, + }, + }); if (options.skipDefaultHistorySetupTransition) { initialSetupProcess = new SerialNavigationProcess([ - (): ( - | Omit - | Omit - )[] => [ - ...defaultHistory.flatMap( - ({ - activityName, - activityParams, - additionalSteps = [], - }): ( - | Omit - | Omit - )[] => { - const activityId = id(); + () => [ + ...defaultHistory.flatMap((historyEntry) => + historyEntryToEvents(historyEntry).map((event) => { + if (event.name !== "Pushed") return event; activityActivationMonitors.push( new DefaultHistoryActivityActivationMonitor( - activityId, + event.activityId, initialSetupProcess!, ), ); - return [ - { - name: "Pushed", - id: id(), - activityId, - activityName, - activityParams: { - ...activityParams, - }, - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, - }, - }, - skipEnterActiveState: true, - }, - ...additionalSteps.map( - ({ - stepParams, - hasZIndex, - }): Omit => ({ - name: "StepPushed", - id: id(), - stepId: id(), - stepParams, - hasZIndex, - }), - ), - ]; - }, + return { + ...event, + skipEnterActiveState: true, + }; + }), ), { - name: "Pushed", - id: id(), - activityId: id(), - activityName: targetActivityRoute.activityName, - activityParams: - makeTemplate( - targetActivityRoute, - options.urlPatternOptions, - ).parse(currentPath) ?? - urlSearchParamsToMap(pathToUrl(currentPath).searchParams), - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, - }, - }, + ...createTargetActivityPushEvent(), skipEnterActiveState: true, }, ], ]); } else { initialSetupProcess = new SerialNavigationProcess([ - ...defaultHistory.map( - ({ activityName, activityParams, additionalSteps = [] }) => - () => { - const events: ( - | Omit - | Omit - )[] = [ - { - name: "Pushed", - id: id(), - activityId: id(), - activityName, - activityParams: { - ...activityParams, - }, - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, - }, - }, - }, - ...additionalSteps.map( - ({ - stepParams, - hasZIndex, - }): Omit => ({ - name: "StepPushed", - id: id(), - stepId: id(), - stepParams, - hasZIndex, - }), + ...defaultHistory.map((historyEntry) => () => { + const events = historyEntryToEvents(historyEntry); + + for (const event of events) { + if (event.name === "Pushed") { + activityActivationMonitors.push( + new DefaultHistoryActivityActivationMonitor( + event.activityId, + initialSetupProcess!, ), - ]; - - for (const event of events) { - if (event.name === "Pushed") { - activityActivationMonitors.push( - new DefaultHistoryActivityActivationMonitor( - event.activityId, - initialSetupProcess!, - ), - ); - } - } - - return events; - }, - ), - () => [ - { - name: "Pushed", - id: id(), - activityId: id(), - activityName: targetActivityRoute.activityName, - activityParams: - makeTemplate( - targetActivityRoute, - options.urlPatternOptions, - ).parse(currentPath) ?? - urlSearchParamsToMap(pathToUrl(currentPath).searchParams), - activityContext: { - path: currentPath, - lazyActivityComponentRenderContext: { - shouldRenderImmediately: true, - }, - }, - }, - ], + ); + } + } + + return events; + }), + () => [createTargetActivityPushEvent()], ]); } From a147c9edc6405cc60262166ab827b19b718c3e5a Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 17:03:09 +0900 Subject: [PATCH 07/11] correct --- .../src/historySyncPlugin.tsx | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 11f177833..72c2fa6b8 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -342,31 +342,38 @@ export function historySyncPlugin< ]); } else { initialSetupProcess = new SerialNavigationProcess([ - ...defaultHistory.map((historyEntry) => () => { - const events = historyEntryToEvents(historyEntry); - - for (const event of events) { - if (event.name === "Pushed") { - activityActivationMonitors.push( - new DefaultHistoryActivityActivationMonitor( - event.activityId, - initialSetupProcess!, - ), - ); - } - } - - return events; + ...defaultHistory.map((historyEntry, index) => () => { + let isFirstPush = true; + + return historyEntryToEvents(historyEntry).map((event) => { + if (event.name !== "Pushed") return event; + const skipEnterActiveState = index === 0 && isFirstPush; + + isFirstPush = false; + activityActivationMonitors.push( + new DefaultHistoryActivityActivationMonitor( + event.activityId, + initialSetupProcess!, + ), + ); + + return { + ...event, + skipEnterActiveState, + }; + }); }), () => [createTargetActivityPushEvent()], ]); } + const now = Date.now(); + return initialSetupProcess .captureNavigationOpportunity(null) - .map((event, index) => ({ + .map((event, index, array) => ({ ...event, - eventDate: Date.now() - MINUTE + index, + eventDate: now - (array.length - index), })); }, onInit({ actions: { getStack, dispatchEvent, push, stepPush } }) { From 29ec5d2dd85ab966db3a612ad8ed0d7b2c36b1f1 Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 17:35:52 +0900 Subject: [PATCH 08/11] fix --- .../src/historySyncPlugin.tsx | 59 ++++++++----------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 72c2fa6b8..618849e1c 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -381,8 +381,8 @@ export function historySyncPlugin< for (const activity of stack.activities) { if ( - activity.transitionState === "enter-done" || - activity.transitionState === "enter-active" + activity.transitionState === "enter-active" || + activity.transitionState === "enter-done" ) { const match = activityRoutes.find( (r) => r.activityName === activity.name, @@ -390,47 +390,38 @@ export function historySyncPlugin< const template = makeTemplate(match, options.urlPatternOptions); if (activity.isRoot) { - requestHistoryTick(() => { - silentFlag = true; - replaceState({ - history, - pathname: template.fill(activity.params), - state: { - activity: activity, - step: activity.steps[0], - }, - useHash: options.useHash, - }); + replaceState({ + history, + pathname: template.fill(activity.params), + state: { + activity: activity, + step: activity.steps[0], + }, + useHash: options.useHash, }); } else { - requestHistoryTick(() => { - silentFlag = true; + pushState({ + history, + pathname: template.fill(activity.params), + state: { + activity: activity, + step: activity.steps[0], + }, + useHash: options.useHash, + }); + } + + for (const step of activity.steps) { + if (!step.exitedBy && step.enteredBy.name !== "Pushed") { pushState({ history, - pathname: template.fill(activity.params), + pathname: template.fill(step.params), state: { activity: activity, - step: activity.steps[0], + step: step, }, useHash: options.useHash, }); - }); - } - - for (const step of activity.steps) { - if (!step.exitedBy && step.enteredBy.name !== "Pushed") { - requestHistoryTick(() => { - silentFlag = true; - pushState({ - history, - pathname: template.fill(activity.params), - state: { - activity: activity, - step: step, - }, - useHash: options.useHash, - }); - }); } } } From c7ca5b2b84db8853fa618d171df5c7ed3f4b32c3 Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 17:45:01 +0900 Subject: [PATCH 09/11] omit step --- extensions/plugin-history-sync/src/historySyncPlugin.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index 618849e1c..c80811464 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -395,7 +395,6 @@ export function historySyncPlugin< pathname: template.fill(activity.params), state: { activity: activity, - step: activity.steps[0], }, useHash: options.useHash, }); @@ -405,7 +404,6 @@ export function historySyncPlugin< pathname: template.fill(activity.params), state: { activity: activity, - step: activity.steps[0], }, useHash: options.useHash, }); From 22f4a66b7036f06eecc19ac7dc2911234b385ee8 Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 17:47:00 +0900 Subject: [PATCH 10/11] skip sync when session was restored --- .../src/historySyncPlugin.tsx | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/extensions/plugin-history-sync/src/historySyncPlugin.tsx b/extensions/plugin-history-sync/src/historySyncPlugin.tsx index c80811464..2698d447d 100644 --- a/extensions/plugin-history-sync/src/historySyncPlugin.tsx +++ b/extensions/plugin-history-sync/src/historySyncPlugin.tsx @@ -379,48 +379,50 @@ export function historySyncPlugin< onInit({ actions: { getStack, dispatchEvent, push, stepPush } }) { const stack = getStack(); - for (const activity of stack.activities) { - if ( - activity.transitionState === "enter-active" || - activity.transitionState === "enter-done" - ) { - const match = activityRoutes.find( - (r) => r.activityName === activity.name, - )!; - const template = makeTemplate(match, options.urlPatternOptions); - - if (activity.isRoot) { - replaceState({ - history, - pathname: template.fill(activity.params), - state: { - activity: activity, - }, - useHash: options.useHash, - }); - } else { - pushState({ - history, - pathname: template.fill(activity.params), - state: { - activity: activity, - }, - useHash: options.useHash, - }); - } + if (parseState(history.location.state) === null) { + for (const activity of stack.activities) { + if ( + activity.transitionState === "enter-active" || + activity.transitionState === "enter-done" + ) { + const match = activityRoutes.find( + (r) => r.activityName === activity.name, + )!; + const template = makeTemplate(match, options.urlPatternOptions); - for (const step of activity.steps) { - if (!step.exitedBy && step.enteredBy.name !== "Pushed") { + if (activity.isRoot) { + replaceState({ + history, + pathname: template.fill(activity.params), + state: { + activity: activity, + }, + useHash: options.useHash, + }); + } else { pushState({ history, - pathname: template.fill(step.params), + pathname: template.fill(activity.params), state: { activity: activity, - step: step, }, useHash: options.useHash, }); } + + for (const step of activity.steps) { + if (!step.exitedBy && step.enteredBy.name !== "Pushed") { + pushState({ + history, + pathname: template.fill(step.params), + state: { + activity: activity, + step: step, + }, + useHash: options.useHash, + }); + } + } } } } From a210e287bd26c0a6227c2af8ecdd546d9168b757 Mon Sep 17 00:00:00 2001 From: anakin_karrot Date: Fri, 26 Dec 2025 22:26:02 +0900 Subject: [PATCH 11/11] cs --- .changeset/shiny-ears-draw.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/shiny-ears-draw.md diff --git a/.changeset/shiny-ears-draw.md b/.changeset/shiny-ears-draw.md new file mode 100644 index 000000000..d0a42c799 --- /dev/null +++ b/.changeset/shiny-ears-draw.md @@ -0,0 +1,5 @@ +--- +"@stackflow/plugin-history-sync": minor +--- + +Add an option to skip default history setup transition