Files
easy-png-tools2/docs/archive/plan-update-ux.md
T

9.2 KiB
Raw Blame History

План: раскладка «исходник слева — результат справа» + вставка изображения

СТАТУС: ВЫПОЛНЕН 2026-08-22.

Что сделано по этапам:

  • A — общая MIME-валидация isSupportedImage + unsupportedImageMessage в core/io.ts; DropZone переведён на них ✔
  • B — постоянная двухпанельная раскладка: одна карточка-«сцена» с равными половинами «Исходник | Результат», кнопки внутри своих половин, параметры — отдельной карточкой ниже; контент сайта растянут на всю ширину окна ✔
  • C — Ctrl+V: <svelte:window onpaste>, поиск image-item в буфере, общая валидация; текстовые вставки не затрагиваются ✔
  • D — drag-замена: компонент DropOverlay с вуалью-подсказкой и счётчиком dragenter/dragleave против мерцания; тот же счётчик в DropZone
  • E — верификация: тесты 85/85, svelte-check 0 ошибок, статический билд с 11 страницами; ручной смоук-чеклист §5 пройден ✔

Отступления от исходного плана в ходе реализации: вместо пропа overlay у DropZone сделан отдельный компонент-обёртка DropOverlay (drag-события ловит контент под курсором); раскладка доработана по ревью — одна карточка равных половин вместо двух независимых колонок, сайт без ограничения ширины.

1. Целевое поведение

  1. Постоянная двухпанельная раскладка страницы инструмента — отдельного состояния «страница загрузки» больше нет:
    • Слева — исходник, панель есть всегда. Не загружено → пустое дроп-поле (drag&drop или клик). Загружено → превью исходника.
    • Справа — результат: до загрузки — EmptyState «Результат появится здесь»; во время обработки — EmptyState «Обработка…»; после — превью результата (для info-инструмента — InfoPanel).
  2. Ctrl+V — картинка из буфера обмена вставляется как исходник с любого места страницы.
  3. Замена перетаскиванием — новый файл, брошенный на левую панель с загруженной картинкой, заменяет исходник (с оверлеем-подсказкой во время перетаскивания).
  4. Кнопка «Заменить» под превью исходника (переносится туда текущая «Загрузить другое изображение»).

На мобильной ширине панели складываются в столбец: исходник сверху, результат снизу.

2. Изменения по файлам

Новые компоненты не вводим — EmptyState, Preview, DropZone покрывают всё. Меняем три файла:

  • core/io.ts — экспорт isSupportedImage(file): boolean: общая MIME-проверка на базе ACCEPTED_IMAGE_TYPES.
  • DropZone.svelte — переходит на isSupportedImage; новый опциональный проп overlay — режим «невидимая зона приёма поверх контента» для замены перетаскиванием.
  • ToolPage.svelte — постоянная сетка из двух панелей; <svelte:window onpaste>; drag-оверлей левой панели; кнопки замены/сброса переезжают в левую панель; правая панель — три состояния через EmptyState.

3. Этапы и проверки

  • A. Общая валидацияisSupportedImage в io.ts, DropZone переведён на неё. Проверка: pnpm check.
  • B. Раскладка — две постоянные колонки в ToolPage; правая панель через EmptyState; кнопки уходят в левую панель; обёртка {#if !source} на всю страницу убирается. Проверка: визуальный осмотр всех инструментов, check/build.
  • C. Ctrl+Vonpaste на окне → поиск image-item в clipboardData → тот же handleFile; не-изображения игнорируются молча. Проверка: ручной смоук со скриншотом из буфера.
  • D. Drag-замена — оверлей DropZone(overlay) при dragover на левой панели; drop → handleFile нового файла. Проверка: ручной смоук «бросить файл на загруженный исходник».
  • E. Итог — полный ручной смоук-чеклист (§5). Проверка: test/check/build зелёные.

4. Нюансы и решения

  • Мерцание dragleave — классическая проблема оверлеев: используем счётчик dragenter/dragleave, оверлей скрывается только когда счётчик обнулился и произошёл drop/dragend.
  • Paste при фокусе в поле параметров — обрабатываем всегда: если в буфере именно изображение, пользователь очевидно хочет заменить исходник; текстовые вставки обработчик не трогает.
  • Форматы буфера — скриншоты приходят как PNG, часть приложений отдаёт JPEG/WebP; все проходят общую isSupportedImage. GIF/BMP из буфера редки, но тоже допустимы.
  • Info-инструменты — ведут себя так же: слева исходник, справа после загрузки появляется InfoPanel.
  • Состояние ошибки — баннер остаётся сверху страницы; неудачная замена не сбрасывает старый исходник.

5. Чеклист ручного смоука

  1. Пустые обе панели → drag&drop файла слева → появился исходник и результат.
  2. Клик по пустой левой панели → выбор файла.
  3. Ctrl+V со скриншотом → исходник заменился, результат пересчитался.
  4. Drag файла на загруженную левую панель → оверлей виден, после drop — замена.
  5. Отмена перетаскивания (Esc / мимо) → оверлей скрылся, исходник не изменился.
  6. Бросок неподдерживаемого файла (например .txt) → баннер ошибки, старый исходник цел.
  7. Кнопка «Заменить» открывает выбор файла.
  8. png-info: работает та же схема, справа сводка.
  9. Мобильная ширина: панели в столбец, порядок исходник → результат.
  10. Все 11 инструментов отвечают на замену исходника корректным пересчётом.

6. Критерии готовности

  • На странице инструмента нет состояния «только дропзона на всю страницу» — раскладка двухпанельная всегда.
  • Загрузка работает тремя способами: клик, drag&drop (включая замену), Ctrl+V.
  • Ошибочные файлы и отмена перетаскивания не портят текущий исходник.
  • test/check/build зелёные; чеклист §5 пройден.

7. Что сознательно не делаем (граница скоупа этого плана)

  • Множественная загрузка / пакетная обработка — вне скоупа этого плана.
  • Камера/скриншот-инструменты захвата — только буфер обмена.
  • Прогресс-бары декодирования — файлы читаются быстро, достаточно индикации «Обработка…».