Files
jellybit/internal/httpapi/files.go
T
avandClaude Opus 4.8 4e2593ac31 Перенос дизайна в server-rendered веб-UI (web-ui)
Новая capability web-ui: презентационный перенос готового дизайна
(семантический HTML + единый jellybit.css, тёмная тема по настройке ОС)
в html/template без шага сборки.

- Встроенная (go:embed) отдача статики под /static с Cache-Control и
  cache-busting (?v=<hash> по содержимому css/js).
- Шрифты IBM Plex self-hosted (@font-face, cyrillic+latin), без CDN.
- Наколеночный менеджер зависимостей: вендор (htmx + шрифты) не хранится
  в репо (gitignore), идемпотентно добывается `task assets` по
  web/assets.manifest с проверкой sha256; task build/run зависят от assets.
- Общие партиалы: шапка, бейдж статуса (карта всех 14 состояний),
  виджет «файл источника → раскладка» (общий для review и download).
- Страницы: список с фильтром/поиском, ревью, новая страница просмотра
  загрузки (/download/{id}). deleted скрыт по умолчанию.
- Превью раскладки берётся из единой логики internal/layout
  (buildFileRows), без дублирования правил имён в шаблонах.
- Убраны meta-refresh и инлайн-стили; copyHash на vanilla с fallback
  на execCommand и честной индикацией (целевой деплой — HTTP LAN).

Вне scope (отдельный change): живые обновления прогресса и раздел
раздачи, клиентский режим ручной раскладки файл→серия (с Alpine.js).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 19:59:19 +03:00

58 lines
1.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package httpapi
import (
"git.vakhrushev.me/av/jellybit/internal/layout"
"git.vakhrushev.me/av/jellybit/internal/recognize"
)
// fileRow — строка виджета «файл источника → раскладка», общего для экранов
// ревью и просмотра загрузки. Целевой путь берётся из превью (единая логика
// internal/layout), а не вычисляется в шаблоне.
type fileRow struct {
Src string
Dst string // целевой путь; пусто — файл не раскладывается
RoleLabel string
Linked bool
Ignored bool
}
// buildFileRows сшивает файлы плана с целевыми путями из превью раскладки.
func buildFileRows(plan recognize.Plan, preview []layout.Link) []fileRow {
dstBySrc := make(map[string]string, len(preview))
for _, l := range preview {
dstBySrc[l.Src] = l.Dst
}
rows := make([]fileRow, 0, len(plan.Files))
for _, f := range plan.Files {
dst := dstBySrc[f.Src]
rows = append(rows, fileRow{
Src: f.Src,
Dst: dst,
RoleLabel: roleLabel(string(f.Role)),
Linked: dst != "",
Ignored: f.Role == "ignore",
})
}
return rows
}
// roleLabel — человекочитаемая роль файла раскладки.
func roleLabel(role string) string {
switch role {
case "episode":
return "эпизод"
case "main", "movie":
return "фильм"
case "subtitle":
return "субтитры"
case "extra":
return "допматериал"
case "sample":
return "семпл"
case "ignore":
return "игнор"
default:
return role
}
}