style(frontend): Prettier config + one-time repo-wide format pass
Prettier 3 (pinned), printWidth 100, double quotes — chosen to match the existing hand-formatting and minimise reflow. This commit is ONLY the mechanical format pass (`prettier --write`) plus the config/ignore/scripts, isolated so it never pollutes a feature diff. Verified behaviour-neutral: typecheck, eslint (0 errors), and vitest all green before and after. See .git-blame-ignore-revs — `git blame` skips this sha.
This commit is contained in:
@@ -82,7 +82,14 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
});
|
||||
|
||||
const onDelete = async (p: DownloadProfile) => {
|
||||
if (await confirm({ title: t("downloads.profiles.delete"), message: t("downloads.profiles.deleteConfirm", { name: p.name }), confirmLabel: t("downloads.profiles.delete"), danger: true })) {
|
||||
if (
|
||||
await confirm({
|
||||
title: t("downloads.profiles.delete"),
|
||||
message: t("downloads.profiles.deleteConfirm", { name: p.name }),
|
||||
confirmLabel: t("downloads.profiles.delete"),
|
||||
danger: true,
|
||||
})
|
||||
) {
|
||||
del.mutate(p.id);
|
||||
}
|
||||
};
|
||||
@@ -95,23 +102,41 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
<Modal title={t("downloads.profiles.title")} onClose={onClose} maxWidth="max-w-xl">
|
||||
{/* Existing formats */}
|
||||
<div className="space-y-1.5 mb-4">
|
||||
<div className="text-xs uppercase tracking-wide text-muted">{t("downloads.profiles.builtin")}</div>
|
||||
<div className="text-xs uppercase tracking-wide text-muted">
|
||||
{t("downloads.profiles.builtin")}
|
||||
</div>
|
||||
{builtins.map((p) => (
|
||||
<div key={p.id} className="flex items-center gap-2 text-sm px-3 py-1.5 rounded-lg glass-card">
|
||||
<div
|
||||
key={p.id}
|
||||
className="flex items-center gap-2 text-sm px-3 py-1.5 rounded-lg glass-card"
|
||||
>
|
||||
<Lock className="w-3.5 h-3.5 text-muted shrink-0" />
|
||||
<span className="flex-1 truncate">{p.name}</span>
|
||||
</div>
|
||||
))}
|
||||
{mine.length > 0 && (
|
||||
<div className="text-xs uppercase tracking-wide text-muted pt-2">{t("downloads.profiles.yours")}</div>
|
||||
<div className="text-xs uppercase tracking-wide text-muted pt-2">
|
||||
{t("downloads.profiles.yours")}
|
||||
</div>
|
||||
)}
|
||||
{mine.map((p) => (
|
||||
<div key={p.id} className="flex items-center gap-2 text-sm px-3 py-1.5 rounded-lg glass-card">
|
||||
<div
|
||||
key={p.id}
|
||||
className="flex items-center gap-2 text-sm px-3 py-1.5 rounded-lg glass-card"
|
||||
>
|
||||
<span className="flex-1 truncate">{p.name}</span>
|
||||
<button onClick={() => startEdit(p)} title={t("downloads.actions.rename")} className="p-1 rounded hover:bg-surface text-muted hover:text-fg">
|
||||
<button
|
||||
onClick={() => startEdit(p)}
|
||||
title={t("downloads.actions.rename")}
|
||||
className="p-1 rounded hover:bg-surface text-muted hover:text-fg"
|
||||
>
|
||||
<Pencil className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
<button onClick={() => onDelete(p)} title={t("downloads.profiles.delete")} className="p-1 rounded hover:bg-surface text-muted hover:text-red-400">
|
||||
<button
|
||||
onClick={() => onDelete(p)}
|
||||
title={t("downloads.profiles.delete")}
|
||||
className="p-1 rounded hover:bg-surface text-muted hover:text-red-400"
|
||||
>
|
||||
<Trash2 className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -129,11 +154,18 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
<div className="rounded-xl border border-border p-4 space-y-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">{t("downloads.profiles.name")}</label>
|
||||
<input value={name} onChange={(e) => setName(e.target.value)} placeholder={t("downloads.profiles.namePlaceholder")} className={inputCls} />
|
||||
<input
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder={t("downloads.profiles.namePlaceholder")}
|
||||
className={inputCls}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">{t("downloads.profiles.mode")}</label>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.mode")}
|
||||
</label>
|
||||
<select value={spec.mode} onChange={set("mode")} className={inputCls}>
|
||||
<option value="av">{t("downloads.profiles.modeAv")}</option>
|
||||
<option value="v">{t("downloads.profiles.modeV")}</option>
|
||||
@@ -142,10 +174,14 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
</div>
|
||||
{spec.mode !== "a" ? (
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">{t("downloads.profiles.quality")}</label>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.quality")}
|
||||
</label>
|
||||
<select
|
||||
value={spec.max_height ?? ""}
|
||||
onChange={(e) => patch({ max_height: e.target.value === "" ? null : Number(e.target.value) })}
|
||||
onChange={(e) =>
|
||||
patch({ max_height: e.target.value === "" ? null : Number(e.target.value) })
|
||||
}
|
||||
className={inputCls}
|
||||
>
|
||||
{HEIGHTS.map((h) => (
|
||||
@@ -157,8 +193,14 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">{t("downloads.profiles.audioFormat")}</label>
|
||||
<select value={spec.audio_format ?? "m4a"} onChange={set("audio_format")} className={inputCls}>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.audioFormat")}
|
||||
</label>
|
||||
<select
|
||||
value={spec.audio_format ?? "m4a"}
|
||||
onChange={set("audio_format")}
|
||||
className={inputCls}
|
||||
>
|
||||
<option value="m4a">M4A</option>
|
||||
<option value="mp3">MP3</option>
|
||||
<option value="opus">Opus</option>
|
||||
@@ -168,15 +210,23 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
{spec.mode !== "a" && (
|
||||
<>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">{t("downloads.profiles.container")}</label>
|
||||
<select value={spec.container ?? "mp4"} onChange={set("container")} className={inputCls}>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.container")}
|
||||
</label>
|
||||
<select
|
||||
value={spec.container ?? "mp4"}
|
||||
onChange={set("container")}
|
||||
className={inputCls}
|
||||
>
|
||||
<option value="mp4">MP4</option>
|
||||
<option value="mkv">MKV</option>
|
||||
<option value="webm">WebM</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-1">{t("downloads.profiles.vcodec")}</label>
|
||||
<label className="block text-sm font-medium mb-1">
|
||||
{t("downloads.profiles.vcodec")}
|
||||
</label>
|
||||
<select value={spec.vcodec ?? ""} onChange={set("vcodec")} className={inputCls}>
|
||||
<option value="">{t("downloads.profiles.any")}</option>
|
||||
<option value="h264">H.264</option>
|
||||
@@ -189,14 +239,33 @@ export default function ProfileEditor({ onClose }: { onClose: () => void }) {
|
||||
</div>
|
||||
<div className="space-y-1.5 pt-1">
|
||||
{spec.mode !== "a" && (
|
||||
<Check label={t("downloads.profiles.embedSubs")} checked={spec.embed_subs} onChange={(v) => patch({ embed_subs: v })} />
|
||||
<Check
|
||||
label={t("downloads.profiles.embedSubs")}
|
||||
checked={spec.embed_subs}
|
||||
onChange={(v) => patch({ embed_subs: v })}
|
||||
/>
|
||||
)}
|
||||
<Check label={t("downloads.profiles.embedChapters")} checked={spec.embed_chapters} onChange={(v) => patch({ embed_chapters: v })} />
|
||||
<Check label={t("downloads.profiles.embedThumbnail")} checked={spec.embed_thumbnail} onChange={(v) => patch({ embed_thumbnail: v })} />
|
||||
<Check label={t("downloads.profiles.sponsorblock")} checked={spec.sponsorblock} onChange={(v) => patch({ sponsorblock: v })} />
|
||||
<Check
|
||||
label={t("downloads.profiles.embedChapters")}
|
||||
checked={spec.embed_chapters}
|
||||
onChange={(v) => patch({ embed_chapters: v })}
|
||||
/>
|
||||
<Check
|
||||
label={t("downloads.profiles.embedThumbnail")}
|
||||
checked={spec.embed_thumbnail}
|
||||
onChange={(v) => patch({ embed_thumbnail: v })}
|
||||
/>
|
||||
<Check
|
||||
label={t("downloads.profiles.sponsorblock")}
|
||||
checked={spec.sponsorblock}
|
||||
onChange={(v) => patch({ sponsorblock: v })}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-end gap-2 pt-1">
|
||||
<button onClick={() => setFormOpen(false)} className="px-3 py-1.5 rounded-lg text-sm text-muted hover:text-fg hover:bg-surface transition">
|
||||
<button
|
||||
onClick={() => setFormOpen(false)}
|
||||
className="px-3 py-1.5 rounded-lg text-sm text-muted hover:text-fg hover:bg-surface transition"
|
||||
>
|
||||
{t("downloads.actions.cancel")}
|
||||
</button>
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user