Skip to content

v1.0.3

Choose a tag to compare

@github-actions github-actions released this 19 May 08:51
· 2 commits to master since this release

Поверх v1.0.2 — четыре функциональные доработки и пара фиксов производительности UI. Ничего из v1.0.2 не ломается, апдейт безопасный.

Главное в этом релизе — менеджер пресетов (отдельная панель со всеми пресетами разом, их расписаниями автовыгрузки, кнопками быстрого запуска), пересборка манифеста по диску (если папка разъехалась с .manifest.json) и формат имени файла JoySave-совместимый.

Менеджер пресетов

Сверху в шапке между ⚙ и 📋 появилась кнопка «📑 Пресеты». Открывает отдельную панель со всеми сохранёнными пресетами в виде компактных карточек — две строки на пресет:

| Имя · #теги · @автор · ★рейтинг · лимит        [▶ 📂 📋 🗑] |
| ☐ Авто-обновление  ⏱ N назад  → через X ч Y мин            |

Что показано в строке:

  • Сводка фильтров в одну строку: первые теги через ·, @автор, ★200+, NSFW only, лимит — то, что помогает опознать пресет на лету.
  • Папка — в tooltip на строке (мышью наводишь — видишь полный путь; чтобы открыть, жми 📂).
  • Чекбокс «Авто-обновление» — мгновенно переключает Preset.AutoPull, без необходимости загружать пресет в форму.
  • ⏱ «N назад» — сколько прошло с последней автовыгрузки (в tooltip — точная дата). «ни разу» если ещё не выгружался.
  • → «через N ч M мин» — live-обратный отсчёт до следующего автозапуска (тикает раз в секунду, пересчитывается из глобального интервала ⚙ → Авто-обновление). «готова к запуску», когда таймер достиг нуля. «автовыгрузка выключена», если чекбокс не отмечен.

Кнопки действий в строке:

  • — запустить пресет вручную сейчас. Создаёт задачу в очереди тем же путём, что и scheduler. Помечает LastAutoPullAt = now, поэтому следующий автозапуск произойдёт через полный интервал, а не сразу — «ручной запуск съедает запланированный».
  • 📂 — открыть папку пресета в проводнике.
  • 📋 — загрузить пресет в форму фильтров (для редактирования всех полей, включая теги/рейтинг/размеры).
  • 🗑 — удалить пресет с подтверждением.

Сортировка: пресеты с включённой автовыгрузкой первыми, затем по алфавиту.

В шапке панели показан текущий глобальный интервал автовыгрузки (24 ч по умолчанию). Меняется по-прежнему в ⚙ → Авто-обновление.

Пересборка манифеста по диску

.manifest.json — это файл, в котором приложение хранит, какие attribute.id уже скачаны. По этому файлу при следующих сканированиях фильтра решается, какие картинки уже есть локально (бейдж «✓» на плитке, пропуск в очереди загрузки). Раньше его можно было только удалить целиком («забыть всё»). Но если часть файлов в папке загрузок перетасовали мимо приложения (переименовали, перенесли между подпапками, дозалили картинки извне, импортировали папку из другого даунлоадера), то манифест и реальное содержимое уходили в рассинхрон, и приложение либо качало дубликаты, либо считало удалённые файлы скачанными.

В ⚙ → Манифест добавилась кнопка «🔄 Полностью пересобрать по файлам из директории…»:

  1. Указываешь папку для сканирования.
  2. Приложение рекурсивно её обходит, парсит имена в одном из четырёх поддерживаемых форматов:
    • <номер_поста>_<id_аттрибута>.<ext> — наш дефолтный «По ID».
    • [тег1][тег2]..._<номер_поста>_<id_аттрибута>.<ext> — наш «По тегам (в скобках)».
    • <номер_поста>_<0|1>_<id, padded к 9>__<тег1>-<тег2>...<ext> — наш новый «JoySave-совместимый» формат (см. ниже), а также имена, написанные JoySave.
    • <slug-через-дефисы>-<id_аттрибута>.<ext> — формат JR CDN, то есть имена картинок, сохранённых из браузера правой кнопкой.
  3. Манифест приводится в точное соответствие с тем, что найдено на диске:
    • неизвестные файлы — добавляются (с текущим timestamp);
    • записи, у которых файла на диске больше нет — удаляются;
    • совпавшие записи сохраняют свой исходный timestamp скачивания и URL.

Расширения принимаются только из списка медиа JR (jpeg/png/gif/bmp/tiff/mp4/webm/webp) — это сделано чтобы случайные посторонние файлы с числами в конце (IMG_20250115_NNN.jpg, RDT_*.jpg, отчёты 2025-01-15.jpg) не попали в манифест.

⚠️ Операция разрушительная. Если используется глобальный режим манифеста (один общий .manifest.json на всё приложение), пересборка по одной из папок сотрёт записи о файлах, лежащих в других папках. UI выводит соответствующий confirm-диалог с явным предупреждением.

Имя файла «JoySave-совместимый»

В ⚙ → Формат имени файла появился третий вариант «JoySave-совместимый». Имена строятся 1:1 как у JoySave (corax4/JoySave), что полезно если папка делится между двумя инструментами или импортируется готовый архив:

<номер_поста>_0_<id_аттрибута, padded к 9 нулями>__<до 4 тегов через `-`>.<ext>

Пример: пост 12345, картинка 67890, теги «art», «cat ears», «anime»:

12345_0_000067890__art-cat-ears-anime.jpeg

Детали:

  • _0_ — у JoySave это слот «откуда картинка»: 0 для тела поста, 1 для приложения в комментарии. У нас массовая загрузка ходит только за Post.Attributes через Query.search (картинок из комментариев в этой загрузке нет), так что _0_ захардкожен.
  • ID аттрибута выравнивается нулями слева до 9 символов (67890000067890).
  • Тег-блок: первые 4 тега в исходном порядке (без алфавитной сортировки — как у JoySave), разделитель -, пробелы внутри имени тега → -.
  • Запрещённые в Windows символы (\/:*?|<>") на всём имени → @ (post-process sweep как у JoySave).

Отличия от существующих форматов:

  • «По ID» (12345_67890.jpg) и «По тегам (в скобках)» ([art][cat][dog]_12345_67890.jpg) — наши собственные форматы, дают детерминированное имя (теги сортируются алфавитно).
  • «JoySave-совместимый» — побайтовая совместимость с JoySave: один и тот же пост может дать разные имена при двух запусках, если API вернул теги в разном порядке. Это осознанный tradeoff — обмен на то, что файлы 1:1 узнаются JoySave-ом.

Дедупликация при скачивании во всех случаях остаётся по attribute.id в манифесте — формат имени на это не влияет.

Выбранный в ⚙ → Формат имени файла формат применяется ко всем способам запуска задачи — ручному «+ Добавить в очередь», запуску ▶ из менеджера пресетов и автоматической выгрузке через scheduler.

UI: меньше перерисовок при массовой загрузке

В v1.0.2 при активной массовой загрузке UI ощутимо «дёргался» — мерцали hover-состояния кнопок, теги-чипы, выпадайка автокомплита, изредка прыгал каретка ввода. Причина: каждое сохранение картинки (job:update) триггерило полную перерисовку #app.innerHTML — топбар, форма фильтров, грид превью, всё, до 60 раз в секунду, хотя реально менялось максимум одна зелёная галка на превью раз в секунду.

В v1.0.3:

  • Обновление зелёных галок «уже скачано» на плитках теперь делается хирургически: новая функция проходит по уже отрендеренным плиткам и точечно добавляет/удаляет/обновляет только сам бейдж. Полная перерисовка не вызывается.
  • Обновления счётчиков задач (saved/skipped/failed) не вызывают рендер, если очередь задач закрыта (там нечему меняться). Открыли очередь — openQueue() сам подтянет накопленное состояние.
  • При открытой очереди счётчики обновляются с дебаунсом 250 мс (≤4 раза/сек вместо 60). Глазу разницы нет, но шелл больше не пересобирается.

Переходы между состояниями задач (running → done/canceled/error, удаление, добавление) по-прежнему отрабатываются мгновенно — топбар-бейдж и таблица очереди обновляются без задержки.

Скачивание

Тот же набор файлов, что и в v1.0.2 — Windows portable / NSIS-setup, macOS universal .app, Linux .tar.gz.

Лицензия

MIT.

Full Changelog: v1.0.2...v1.0.3