diff --git a/CHANGELOG.md b/CHANGELOG.md index 93d8669..dcb24a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,26 @@ All notable changes to Phokus are documented here. The format is based on aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (0.x: anything may change between minor versions). +## [Unreleased] + +### Added + +- Failed AI-tagging jobs can now be located from the background worker prompt, + including a gallery filter for images with failed tags and an expanded list + of failed filenames/errors. +- A new theme system adds Phokus, Subtle Light, and Conventional Dark chrome + options across the app. +- First-run onboarding now includes an inline theme picker so new users can + choose their preferred app chrome before continuing the tour. + +### Changed + +- Polished the new theme surfaces before release, including readable + subtle-light secondary buttons, failed-worker action buttons, and onboarding + controls. +- Onboarding preview media keeps the dark gallery/media surface regardless of + the active chrome theme. + ## [0.1.0] — 2026-06-14 First public release. Windows desktop, distributed as an unsigned NSIS diff --git a/package.json b/package.json index 4267de3..bda87fe 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dev:web": "cd website && pnpm dev", "build:app:cpu": "tauri build -- --no-default-features", "build:app:cuda": "tauri build --config src-tauri/tauri.cuda.conf.json", + "changelog:add": "node tools/changelog-add.mjs", "dev:vite": "vite", "preview": "vite preview", "tauri": "tauri" diff --git a/tools/changelog-add.mjs b/tools/changelog-add.mjs new file mode 100644 index 0000000..cb24c92 --- /dev/null +++ b/tools/changelog-add.mjs @@ -0,0 +1,71 @@ +#!/usr/bin/env node +import { readFileSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const SECTION_BY_TYPE = { + added: "Added", + changed: "Changed", + deprecated: "Deprecated", + removed: "Removed", + fixed: "Fixed", + security: "Security", +}; + +function usage() { + console.error([ + "Usage:", + " pnpm changelog:add -- --type fixed --message \"Fix thing\"", + "", + `Types: ${Object.keys(SECTION_BY_TYPE).join(", ")}`, + ].join("\n")); + process.exit(1); +} + +function argValue(name) { + const index = process.argv.indexOf(`--${name}`); + if (index === -1) return null; + return process.argv[index + 1] ?? null; +} + +const type = argValue("type")?.toLowerCase(); +const message = argValue("message")?.trim(); + +if (!type || !message || !SECTION_BY_TYPE[type]) { + usage(); +} + +const section = SECTION_BY_TYPE[type]; +const changelogPath = resolve("CHANGELOG.md"); +let changelog = readFileSync(changelogPath, "utf8"); + +if (!/^## \[Unreleased\]/m.test(changelog)) { + changelog = changelog.replace( + /(\r?\n)(## \[[^\r\n]+\])/, + `$1## [Unreleased]$1$1$2`, + ); +} + +const unreleasedMatch = changelog.match(/^## \[Unreleased\][\s\S]*?(?=^## \[|\z)/m); +if (!unreleasedMatch) { + throw new Error("Could not find or create an Unreleased section."); +} + +const unreleased = unreleasedMatch[0]; +const lineEnding = changelog.includes("\r\n") ? "\r\n" : "\n"; +const bullet = `- ${message}`; + +let nextUnreleased; +const sectionRegex = new RegExp(`(^### ${section}\\s*)([\\s\\S]*?)(?=^### |\\z)`, "m"); +const sectionMatch = unreleased.match(sectionRegex); + +if (sectionMatch) { + const body = sectionMatch[2].trimEnd(); + const replacement = `${sectionMatch[1]}${body ? `${body}${lineEnding}` : ""}${bullet}${lineEnding}${lineEnding}`; + nextUnreleased = unreleased.replace(sectionRegex, replacement); +} else { + const insert = `${lineEnding}### ${section}${lineEnding}${lineEnding}${bullet}${lineEnding}`; + nextUnreleased = unreleased.trimEnd() + insert + lineEnding; +} + +changelog = changelog.replace(unreleased, nextUnreleased); +writeFileSync(changelogPath, changelog);