Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fep-2636-resume-without-queued-events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackflow/core": patch
---

Fix `resume()` leaving a Stack paused when no navigation event was queued after `pause()`.
12 changes: 9 additions & 3 deletions core/src/activity-utils/makeStackReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export function makeStackReducer(context: { now: number; resumedAt?: number }) {
),
Resumed: withActivitiesReducer(
(stack: Stack, event: ResumedEvent): Stack => {
if (stack.globalTransitionState !== "paused" || !stack.pausedEvents) {
if (stack.globalTransitionState !== "paused") {
return { ...stack, events: [...stack.events, event] };
}

Expand All @@ -137,10 +137,16 @@ export function makeStackReducer(context: { now: number; resumedAt?: number }) {
resumedAt: event.eventDate,
});

const { pausedEvents, ...rest } = stack;
const { pausedEvents = [], ...rest } = stack;
const resumedStack = pausedEvents.reduce(reducer, {
...rest,
globalTransitionState: "idle",
globalTransitionState: rest.activities.some(
(activity) =>
activity.transitionState === "enter-active" ||
activity.transitionState === "exit-active",
)
? "loading"
: "idle",
});

return {
Expand Down
29 changes: 29 additions & 0 deletions core/src/aggregate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4132,6 +4132,35 @@ test("aggregate - Pause되면 이벤트가 반영되지 않고, globalTransition
});
});

test("aggregate - queued event 없이 Resumed 되어도 paused 상태를 해제합니다", () => {
const events = [
initializedEvent({
transitionDuration: 300,
}),
registeredEvent({
activityName: "a",
}),
makeEvent("Pushed", {
activityId: "activity-1",
activityName: "a",
eventDate: enoughPastTime(),
activityParams: {},
}),
makeEvent("Paused", {
eventDate: enoughPastTime(),
}),
makeEvent("Resumed", {
eventDate: enoughPastTime(),
}),
];

const output = aggregate(events, nowTime());

expect(output.globalTransitionState).toBe("idle");
expect(output.pausedEvents).toBeUndefined();
expect(output.events).toStrictEqual(events);
});

test("aggregate - Resumed 되면 해당 시간 이후로 Transition이 정상작동합니다", () => {
let pushedEvent1: PushedEvent;
let pushedEvent2: PushedEvent;
Expand Down
48 changes: 48 additions & 0 deletions core/src/makeCoreStore.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,51 @@ test("makeCoreStore - subscribe에 등록한 이후에 아무 Event가 없는

expect(listener1).toHaveBeenCalledTimes(0);
});

test("makeCoreStore - queued event 없이 resume해도 Stack이 재개됩니다", () => {
const onResumed = jest.fn();

const { actions, pullEvents } = makeCoreStore({
initialEvents: [
makeEvent("Initialized", {
transitionDuration: 150,
eventDate: enoughPastTime(),
}),
makeEvent("ActivityRegistered", {
activityName: "hello",
eventDate: enoughPastTime(),
}),
makeEvent("Pushed", {
activityId: "a1",
activityName: "hello",
activityParams: {},
eventDate: enoughPastTime(),
}),
],
plugins: [
() => ({
key: "test",
onResumed,
}),
],
});

actions.pause();

expect(actions.getStack().globalTransitionState).toBe("paused");
expect(actions.getStack().pausedEvents).toBeUndefined();

actions.resume();

expect(actions.getStack().globalTransitionState).toBe("idle");
expect(onResumed).toHaveBeenCalledTimes(1);
expect(last(pullEvents())?.name).toBe("Resumed");

actions.push({
activityId: "a2",
activityName: "hello",
activityParams: {},
});

expect(last(actions.getStack().activities)?.id).toBe("a2");
});
Loading