Skip to content

Commit 0282c64

Browse files
committed
Fix thumbnail preview count display
Keep the raw thumbnail preview count in the redirect URL and format it only while rendering the preview page. This prevents localized values such as 4,980 from being parsed as 4 after redirect. Add a regression test covering counts over 999. Fixes #451 Assisted-by: OpenCode:gpt-5.5
1 parent 40120d8 commit 0282c64

3 files changed

Lines changed: 76 additions & 3 deletions

File tree

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ Version 0.8.1
66

77
To be released.
88

9+
- Fixed thumbnail cleanup preview counts over 999 being truncated after the
10+
localized count was passed through the redirect URL. The preview now keeps
11+
the raw count in the URL and formats it only when rendering. [[#451]]
12+
13+
[#451]: https://github.com/fedify-dev/hollo/issues/451
14+
915

1016
Version 0.8.0
1117
-------------
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Hono } from "hono";
2+
import { beforeEach, describe, expect, it, vi } from "vitest";
3+
4+
import { cleanDatabase } from "../../tests/helpers";
5+
import { getLoginCookie } from "../../tests/helpers/web";
6+
import { getMediaWithDeletableThumbnails } from "../entities/medium";
7+
import thumbnailCleanup from "./thumbnail_cleanup";
8+
9+
vi.mock("../entities/medium", () => ({
10+
getMediaWithDeletableThumbnails: vi.fn(),
11+
}));
12+
13+
const app = new Hono();
14+
app.route("/thumbnail_cleanup", thumbnailCleanup);
15+
16+
type DeletableMedia = Awaited<
17+
ReturnType<typeof getMediaWithDeletableThumbnails>
18+
>;
19+
20+
function createMediaItems(count: number): DeletableMedia {
21+
return Array.from({ length: count }, (_, index) => ({
22+
created: new Date(Date.UTC(2025, 0, index + 1)),
23+
})) as DeletableMedia;
24+
}
25+
26+
describe.sequential("thumbnail cleanup", () => {
27+
beforeEach(async () => {
28+
await cleanDatabase();
29+
vi.mocked(getMediaWithDeletableThumbnails).mockReset();
30+
});
31+
32+
it("preserves preview counts over 999 across the redirect", async () => {
33+
expect.assertions(5);
34+
35+
vi.mocked(getMediaWithDeletableThumbnails).mockResolvedValue(
36+
createMediaItems(4980),
37+
);
38+
39+
const formData = new FormData();
40+
formData.append("before", "2026-04-12");
41+
const cookie = await getLoginCookie();
42+
const response = await app.request("/thumbnail_cleanup/clean_preview", {
43+
method: "POST",
44+
body: formData,
45+
headers: {
46+
Cookie: cookie,
47+
},
48+
});
49+
50+
expect(response.status).toBe(302);
51+
52+
const location = response.headers.get("Location");
53+
expect(location).not.toBeNull();
54+
55+
const url = new URL(location!, "http://localhost");
56+
expect(url.searchParams.get("fileCount")).toBe("4980");
57+
58+
const previewResponse = await app.request(url.pathname + url.search, {
59+
headers: {
60+
Cookie: cookie,
61+
},
62+
});
63+
64+
expect(previewResponse.status).toBe(200);
65+
expect(await previewResponse.text()).toContain("Number of Items: 4,980");
66+
});
67+
});

src/pages/thumbnail_cleanup.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ data.get("/", async (c) => {
2727
const done = c.req.query("done");
2828
const error = c.req.query("error");
2929
const before = c.req.query("before");
30-
const fileCount = Number.parseInt(c.req.query("fileCount") ?? "0");
30+
const fileCount = Number(c.req.query("fileCount") ?? "0");
3131
const firstFile = c.req.query("firstFile");
3232
const lastFile = c.req.query("lastFile");
3333
const cleanupDataResult = c.req.query("cleanup-data-result");
@@ -187,7 +187,7 @@ data.get("/", async (c) => {
187187
{done === "clean_preview" &&
188188
(fileCount > 0 ? (
189189
<p>
190-
Number of Items: {fileCount}
190+
Number of Items: {fileCount.toLocaleString("en")}
191191
<br />
192192
First: {firstFile}
193193
<br />
@@ -356,7 +356,7 @@ data.post("/clean_preview", async (c) => {
356356
doneUrl.searchParams.set("before", beforeParameter);
357357
doneUrl.searchParams.set(
358358
"fileCount",
359-
mediaWithThumbnailToClean.length.toLocaleString("en"),
359+
String(mediaWithThumbnailToClean.length),
360360
);
361361
if (firstItem) {
362362
doneUrl.searchParams.set(

0 commit comments

Comments
 (0)