recover(page-tree/dnd): вернуть в develop осиротевший фикс drop-раскрытия (#523/#532) #573

Merged
vvzvlad merged 1 commits from fix/523-tree-dnd into develop 2026-07-12 19:43:37 +03:00
Collaborator

Что это

Восстановление контента PR #532, который был смержен (05:08) в свою стековую базу fix/525-insert-unloaded через 7 минут после того, как сама база ушла в develop через #531 (05:01). Итог: merged: true у #532, но его коммит 27d51303 в develop так и не попал — третий случай болезни стековых мержей (после #518→#540 и #533→#572).

Содержимое

Ровно approved-голова #532 (27d51303, ревью agent_reviewer пройдено, ничего не менялось):

  • задержка авто-раскрытия при hover 500→2000 мс (AUTO_EXPAND_MS)
  • drop внутрь узла не раскрывает цель; teal-пульс data-landed-child + инвалидация крошек
  • guard от потери детей в handleMove при make-child в незагруженную цель (зеркало #525 на DnD-пути)

Безопасность мержа (проверено)

  • git merge-tree --write-tree develop fix/523-tree-dnd0 конфликтов
  • develop не трогал ни один из 6 файлов ветки после merge-base (git diff merge-base..develop -- <files> пуст) — семантических пересечений нет
  • тесты ветки: use-tree-mutation.move-guard.test.tsx (3) + update-cache-on-move.breadcrumbs.test.ts (1)

closes #523

Урок (в третий раз)

Стековые PR мержить строго снизу вверх И ПЕРЕД мержем верхнего ретаргетить его базу на develop. Мерж верхнего PR в уже-уехавшую базу молча хоронит контент при зелёном merged: true.

## Что это Восстановление контента **PR #532**, который был смержен (05:08) в свою стековую базу `fix/525-insert-unloaded` **через 7 минут после того**, как сама база ушла в develop через #531 (05:01). Итог: `merged: true` у #532, но его коммит `27d51303` в develop так и не попал — третий случай болезни стековых мержей (после #518→#540 и #533→#572). ## Содержимое Ровно approved-голова #532 (`27d51303`, ревью agent_reviewer пройдено, ничего не менялось): - задержка авто-раскрытия при hover 500→2000 мс (`AUTO_EXPAND_MS`) - drop внутрь узла не раскрывает цель; teal-пульс `data-landed-child` + инвалидация крошек - guard от потери детей в `handleMove` при make-child в незагруженную цель (зеркало #525 на DnD-пути) ## Безопасность мержа (проверено) - `git merge-tree --write-tree develop fix/523-tree-dnd` — **0 конфликтов** - develop **не трогал** ни один из 6 файлов ветки после merge-base (`git diff merge-base..develop -- <files>` пуст) — семантических пересечений нет - тесты ветки: `use-tree-mutation.move-guard.test.tsx` (3) + `update-cache-on-move.breadcrumbs.test.ts` (1) closes #523 ## Урок (в третий раз) Стековые PR мержить строго снизу вверх И ПЕРЕД мержем верхнего ретаргетить его базу на develop. Мерж верхнего PR в уже-уехавшую базу молча хоронит контент при зелёном `merged: true`.
agent_vscode added the review/approved label 2026-07-12 19:35:12 +03:00
agent_vscode added 1 commit 2026-07-12 19:35:14 +03:00
Пять точечных клиентских правок (дизайн из адверсариального разбора #523):

1. Задержка hover-раскрытия при drag: `AUTO_EXPAND_MS` 500 → 2000 мс, чтобы
   проведение курсора через дерево не раскрывало ряды — только осознанное
   удержание.
2. Не раскрывать цель при drop внутрь (make-child): удалена строка
   `onToggle(target, true)` в `onDrop` (drop оставляет узел свёрнутым; раскрытие
   только по hover-hold). Восстановление раскрытости самого source не тронуто.
3. Guard от потери детей в `handleMove` (обязателен вместе с п.2): раньше эта же
   `onToggle` была ЕДИНСТВЕННЫМ триггером корректирующего lazy-load. `treeModel.move`
   материализует `target.children = [source]`; для НЕзагруженной цели (предикат
   gate `treeModel.isUnloadedBranch`) это скрыло бы остальных серверных детей папки
   (класс #159 #1). Теперь для незагруженной make-child-цели оптимистичное дерево
   строится БЕЗ материализации source: source удаляется из старого родителя, цели
   ставится `hasChildren:true`; gate остаётся взведён и раскрытие догружает полный
   набор. Для загруженной цели поведение прежнее (append сохраняет детей).
4. Инвалидация крошек: `updateCacheOnMovePage` инвалидирует
   `["breadcrumbs", pageId]` — guard делает `remove(source)`, и для текущей
   открытой страницы `findBreadcrumbPath` промахивается → крошки показывали бы
   старого родителя до refocus.
5. Сигнал «уехало сюда»: транзиентный teal-пульс на строке при make-child-drop в
   свёрнутую цель (узел НЕ раскрывается), отдельный `data-landed-child` +
   `DROP_LANDED_HIGHLIGHT_MS`, таймер чистится при анмаунте; уважает
   prefers-reduced-motion.

Тесты: `handleMove` — незагруженная make-child-цель не материализует `[source]`
(мутация guard'а краснит), загруженная цель append'ит и сохраняет детей,
genuinely-empty лист материализует; инвалидация `["breadcrumbs", pageId]`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vvzvlad merged commit 4496afb481 into develop 2026-07-12 19:43:36 +03:00
Sign in to join this conversation.