diff --git a/site/scripts/generate-pack-data.ts b/site/scripts/generate-pack-data.ts index 245d576..f55a14d 100644 --- a/site/scripts/generate-pack-data.ts +++ b/site/scripts/generate-pack-data.ts @@ -135,6 +135,7 @@ interface RegistryEntry { source_path: string; trust_tier?: string; tags?: string[]; + added?: string; } interface PackData { @@ -155,6 +156,7 @@ interface PackData { previewSounds: { file: string; label: string; audioUrl: string }[]; sourceRepo?: string; sourcePath?: string; + dateAdded?: string; } // ── Config ────────────────────────────────────────────────────────────────── @@ -175,7 +177,7 @@ const REGISTRY_INDEX_URL = // ── Helpers ───────────────────────────────────────────────────────────────── // audioBase should be the URL of the directory containing sounds/ // e.g. "https://raw.../og-packs/v1.0.0/peon" or "https://raw.../mypack/v1.0.0" -function processManifest(manifest: Manifest, packName: string, audioBase: string, trustTier: string = "community", registryTags?: string[], sourceRepo?: string, sourcePath?: string): PackData { +function processManifest(manifest: Manifest, packName: string, audioBase: string, trustTier: string = "community", registryTags?: string[], sourceRepo?: string, sourcePath?: string, dateAdded?: string): PackData { const categories: PackData["categories"] = []; const previewSounds: PackData["previewSounds"] = []; let soundCount = 0; @@ -218,6 +220,7 @@ function processManifest(manifest: Manifest, packName: string, audioBase: string previewSounds, sourceRepo, sourcePath, + dateAdded, }; } @@ -298,7 +301,7 @@ async function generateFromRemote(): Promise { ? `${rawBase}/${entry.source_path}` : rawBase; - return processManifest(manifest, packName, audioBase, entry.trust_tier || "community", entry.tags, entry.source_repo, entry.source_path || undefined); + return processManifest(manifest, packName, audioBase, entry.trust_tier || "community", entry.tags, entry.source_repo, entry.source_path || undefined, entry.added); }) ); diff --git a/site/src/app/packs/PacksClient.tsx b/site/src/app/packs/PacksClient.tsx index ab6c06f..7fcdad3 100644 --- a/site/src/app/packs/PacksClient.tsx +++ b/site/src/app/packs/PacksClient.tsx @@ -34,13 +34,15 @@ const LANGUAGE_LABELS: Record = { const PACKS_PER_PAGE = 24; -type SortKey = "name-asc" | "name-desc" | "sounds-desc" | "sounds-asc"; +type SortKey = "name-asc" | "name-desc" | "sounds-desc" | "sounds-asc" | "date-desc" | "date-asc"; const SORT_OPTIONS: { value: SortKey; label: string }[] = [ { value: "name-asc", label: "A → Z" }, { value: "name-desc", label: "Z → A" }, { value: "sounds-desc", label: "Most sounds" }, { value: "sounds-asc", label: "Fewest sounds" }, + { value: "date-desc", label: "Newest" }, + { value: "date-asc", label: "Oldest" }, ]; // ── Helpers ────────────────────────────────────────────────────────────────── @@ -56,6 +58,20 @@ function sortPacks(packs: ReturnType, key: SortKey) { return sorted.sort((a, b) => b.totalSoundCount - a.totalSoundCount); case "sounds-asc": return sorted.sort((a, b) => a.totalSoundCount - b.totalSoundCount); + case "date-desc": + return sorted.sort((a, b) => { + if (!a.dateAdded && !b.dateAdded) return 0; + if (!a.dateAdded) return 1; + if (!b.dateAdded) return -1; + return b.dateAdded.localeCompare(a.dateAdded); + }); + case "date-asc": + return sorted.sort((a, b) => { + if (!a.dateAdded && !b.dateAdded) return 0; + if (!a.dateAdded) return 1; + if (!b.dateAdded) return -1; + return a.dateAdded.localeCompare(b.dateAdded); + }); default: return sorted; } diff --git a/site/src/lib/types.ts b/site/src/lib/types.ts index 36bd8d4..8e8c448 100644 --- a/site/src/lib/types.ts +++ b/site/src/lib/types.ts @@ -32,6 +32,7 @@ export interface PackMeta { previewSounds: SoundEntry[]; sourceRepo?: string; sourcePath?: string; + dateAdded?: string; } export interface PacksData {