Complete Phase C (custom commands & yt-dlp updater) and Phase D (library, UX & notifications)
Phase C had been implemented in the working tree but never committed: named custom-command templates (CRUD + per-download override), command preview, and the in-app yt-dlp self-updater. Phase D adds: history search/kind-filter/multi-select/bulk-delete/ re-download; native OS notifications on completion/failure; a private/ incognito download mode that skips history; settings+template backup/ restore via JSON; and a persistent error log surfaced as a Diagnostics report in Settings. See ROADMAP.md for the full per-item breakdown. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { app } from 'electron'
|
||||
import { join } from 'path'
|
||||
import { readFileSync, writeFileSync, existsSync } from 'fs'
|
||||
import type { CommandTemplate } from '@shared/ipc'
|
||||
|
||||
// Plain JSON in userData, same shape as history.ts.
|
||||
const MAX_TEMPLATES = 100
|
||||
|
||||
function templatesFile(): string {
|
||||
return join(app.getPath('userData'), 'templates.json')
|
||||
}
|
||||
|
||||
export function listTemplates(): CommandTemplate[] {
|
||||
try {
|
||||
if (!existsSync(templatesFile())) return []
|
||||
const data = JSON.parse(readFileSync(templatesFile(), 'utf8'))
|
||||
return Array.isArray(data) ? (data as CommandTemplate[]) : []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
function save(templates: CommandTemplate[]): void {
|
||||
try {
|
||||
writeFileSync(templatesFile(), JSON.stringify(templates.slice(0, MAX_TEMPLATES), null, 2))
|
||||
} catch {
|
||||
/* best-effort; a read-only data dir just means no persisted templates */
|
||||
}
|
||||
}
|
||||
|
||||
function sanitize(t: CommandTemplate): CommandTemplate {
|
||||
return {
|
||||
id: String(t.id),
|
||||
name: (t.name ?? '').trim() || 'Untitled command',
|
||||
args: (t.args ?? '').trim()
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a new template, or update an existing one (matched by id). */
|
||||
export function saveTemplate(template: CommandTemplate): CommandTemplate[] {
|
||||
const clean = sanitize(template)
|
||||
const templates = [clean, ...listTemplates().filter((t) => t.id !== clean.id)]
|
||||
save(templates)
|
||||
return templates
|
||||
}
|
||||
|
||||
export function removeTemplate(id: string): CommandTemplate[] {
|
||||
const templates = listTemplates().filter((t) => t.id !== id)
|
||||
save(templates)
|
||||
return templates
|
||||
}
|
||||
|
||||
/** Replace the entire template list (backup restore) rather than merge-by-id. */
|
||||
export function replaceTemplates(templates: CommandTemplate[]): CommandTemplate[] {
|
||||
const clean = templates.map(sanitize)
|
||||
save(clean)
|
||||
return clean
|
||||
}
|
||||
Reference in New Issue
Block a user