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
11 changes: 11 additions & 0 deletions photomap/frontend/static/javascript/slideshow.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,19 @@ export async function toggleSlideshowWithIndicator(e) {

if (slideShowRunning()) {
// pause
const wasShuffling = state.mode === "random";
try {
state.single_swiper.pauseSlideshow();
// A shuffle run fills the swiper buffer with slides in random order. Once
// stopped, the forward/back buttons just walk that buffer, so the user
// would see the shuffled neighborhood instead of the current image's real
// sequential neighbors. Rebuild the buffer in album order around the
// current slide so manual navigation behaves sequentially again.
// (Sequential runs already leave an in-order buffer, so only shuffle needs
// this.)
if (wasShuffling) {
await state.single_swiper.resetAllSlides();
}
} catch (err) {
console.warn("pauseSlideshow failed:", err);
}
Expand Down
46 changes: 44 additions & 2 deletions tests/frontend/slideshow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ jest.unstable_mockModule("../../photomap/frontend/static/javascript/umap.js", ()
}));

// Now import the module we want to test
const { slideShowRunning, updateSlideshowButtonIcon, showPlayPauseIndicator, removeExistingIndicator } =
await import("../../photomap/frontend/static/javascript/slideshow.js");
const {
slideShowRunning,
updateSlideshowButtonIcon,
showPlayPauseIndicator,
removeExistingIndicator,
toggleSlideshowWithIndicator,
} = await import("../../photomap/frontend/static/javascript/slideshow.js");

const { state } = await import("../../photomap/frontend/static/javascript/state.js");

Expand Down Expand Up @@ -165,6 +170,43 @@ describe("slideshow.js", () => {
});
});

describe("toggleSlideshowWithIndicator (pause path)", () => {
beforeEach(() => {
document.body.innerHTML = `
<div id="slideshowIcon"></div>
<button id="startStopSlideshowBtn" title=""></button>
`;
});

it("rebuilds the buffer sequentially when pausing a shuffle run", async () => {
// Regression: after stopping a shuffle slideshow, the swiper buffer is
// still in random order, so forward/back navigation would walk the
// leftover shuffle instead of the current image's sequential neighbors.
const resetAllSlides = jest.fn(() => Promise.resolve());
const pauseSlideshow = jest.fn();
state.single_swiper = { swiper: { autoplay: { running: true } }, pauseSlideshow, resetAllSlides };
state.mode = "random";

await toggleSlideshowWithIndicator();

expect(pauseSlideshow).toHaveBeenCalled();
expect(resetAllSlides).toHaveBeenCalled();
});

it("does not rebuild the buffer when pausing a sequential run", async () => {
// Sequential runs already leave an in-order buffer, so no rebuild needed.
const resetAllSlides = jest.fn(() => Promise.resolve());
const pauseSlideshow = jest.fn();
state.single_swiper = { swiper: { autoplay: { running: true } }, pauseSlideshow, resetAllSlides };
state.mode = "chronological";

await toggleSlideshowWithIndicator();

expect(pauseSlideshow).toHaveBeenCalled();
expect(resetAllSlides).not.toHaveBeenCalled();
});
});

describe("showPlayPauseIndicator", () => {
it("should create indicator element when showing play", () => {
state.mode = "chronological";
Expand Down
Loading