From 4ca8b205082ef8fab304104a6773406d9c79e4f8 Mon Sep 17 00:00:00 2001 From: Darrell van Swinderen Date: Wed, 23 Sep 2026 16:19:56 +0200 Subject: [PATCH] feat(library): the view count is a chip beside Published A count only exists for a published clip, so it sits with the chip that says so: (Published) (eye 37), top right of the card. The metadata line under the title goes back to length, game, date and size, which was one fact too long with the count on the end. The chip is an eye and a number; its accessible name and tooltip carry the words and when it was last opened. Null and zero still draw nothing. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../src/components/Library/ClipCard.vue | 8 +++-- .../src/components/Library/ClipMetadata.vue | 22 +----------- .../components/Library/ClipPublishedBadge.vue | 36 +++++++++++++++++-- src/renderer/src/utils/viewCount.ts | 15 +++++--- tests/unit/renderer/viewCount.spec.ts | 15 +++++++- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/src/renderer/src/components/Library/ClipCard.vue b/src/renderer/src/components/Library/ClipCard.vue index 75ae18f5..b2cce2e3 100644 --- a/src/renderer/src/components/Library/ClipCard.vue +++ b/src/renderer/src/components/Library/ClipCard.vue @@ -273,7 +273,11 @@ function handleCardClick(event: MouseEvent) { - + -
+
Published + +
- diff --git a/src/renderer/src/utils/viewCount.ts b/src/renderer/src/utils/viewCount.ts index 75dbe20a..adbe53f9 100644 --- a/src/renderer/src/utils/viewCount.ts +++ b/src/renderer/src/utils/viewCount.ts @@ -1,7 +1,8 @@ import { pluralize } from './pluralize'; /** - * What a library card says about how often a published clip has been watched. + * How often a published clip has been watched, as the figure on its card's + * chip beside Published: `37`, `1,234`. Empty means the chip is not drawn. * * **Null says nothing.** It means nobody has counted: a publisher older than * the counter, or no sync yet. A number there would be invented. @@ -13,8 +14,14 @@ import { pluralize } from './pluralize'; * * Grouped digits because a clip that went round a Discord can reach four. */ -export function viewCountLabel(views: number | null | undefined): string { +export function viewCountFigure(views: number | null | undefined): string { if (views == null || !Number.isFinite(views) || views <= 0) return ''; - const whole = Math.floor(views); - return `${whole.toLocaleString('en-US')} ${pluralize(whole, 'view')}`; + return Math.floor(views).toLocaleString('en-US'); +} + +/** The same count in words, for a screen reader: the chip itself is an eye and a number. */ +export function viewCountLabel(views: number | null | undefined): string { + const figure = viewCountFigure(views); + if (!figure) return ''; + return `${figure} ${pluralize(Math.floor(views as number), 'view')}`; } diff --git a/tests/unit/renderer/viewCount.spec.ts b/tests/unit/renderer/viewCount.spec.ts index e9397668..90276cd6 100644 --- a/tests/unit/renderer/viewCount.spec.ts +++ b/tests/unit/renderer/viewCount.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { viewCountLabel } from '../../../src/renderer/src/utils/viewCount'; +import { viewCountFigure, viewCountLabel } from '../../../src/renderer/src/utils/viewCount'; /** * The view count on a library card. @@ -31,3 +31,16 @@ describe('viewCountLabel', () => { expect(viewCountLabel(1234)).toBe('1,234 views'); }); }); + +describe('viewCountFigure', () => { + it('is empty wherever the label is, so the chip and its words agree', () => { + for (const views of [null, undefined, 0, -3, Number.NaN]) { + expect(viewCountFigure(views)).toBe(''); + } + }); + + it('is the grouped number alone', () => { + expect(viewCountFigure(1)).toBe('1'); + expect(viewCountFigure(1234)).toBe('1,234'); + }); +});