Скелет заведён лидом (133d80d), P1 слой данных реализован+юнит-тест (8a8f1cf): 8/42 Ф закрыты в коде (create/get/list/favorite/category/rename/delete/save-If-Match/конфликт). Fd=0% (UI не собран). Дальше — P1-UI.
12 KiB
Diff: Заметки (Notes) — итерация 1 (2026-07-13)
Ff_app: 21.7% · Fd_app: 0.0% (среднее по 6 экранам) · n-a: 0
✅ Скелет модуля заведён лидом (
133d80d, mail/096). Итерация 1a — слой данных реализован и верифицирован (коммит8a8f1cf): пункты, помеченные[done]ниже = логика в коде + юнит-тест (7/7, MockWebServer), UI-экраны (список/редактор/диалог/навигация) — следующий заход P1-UI, девайс/визуал-сверка позже. Fd=0% пока держится (ни один экран визуально не собран). Пишущее проверено ЮНИТАМИ, не на forbion (mail/073).Что готово в коде (1a):
NotesApiClient(Notes API v1: list exclude=content+If-None-Match, get, create, saveContent сIf-Match→412NoteConflictException, setFavorite/Category/rename, delete) ·NotesRepository(offline-first список: 304/сеть→кэш) ·NotesCache(дисковый ETag-кэш) ·Noteмодель. Осталось для полного P1: UI-экраны +/autotitle+undo+ категории-CRUD (PATCH/DELETE /category) + settings API.
Сверка веб (nextcloud/notes v5.0.0 + тема forbion) ↔ натив (отсутствует). Карта-источник:
notes.md (снята из кода + визуально сверена на forbion, Browser 1, read-only).
Метки: [Ф|Д] (функционал/дизайн) · [open|done|n-a]. Подход к реализации согласован —
Notes API v1 + ETag-кэш, план 1→2→3 (mail/071).
Приоритеты предлагаю в конце (P1→P3); финальную приоритизацию — за лидом.
Экран 1. Список заметок (главный) — Ff 20% · Fd 0%
Ф (10, open 8):
- [Ф][done] создать заметку (
NotesApiClient.create, юнит-тест) — UI-кнопка следующим заходом - [Ф][open] поле «Искать заметки» (фильтр по заголовку) + очистка — P2
- [Ф][done] загрузка заметки (
get) + списка (listNotesoffline-first) — данные готовы; UI строки P1-UI - [Ф][open] индикатор «расшарена» на строке — P3
- [Ф][open] меню строки «⋯» (см. Экран 2) — P1
- [Ф][open] группировка по таймслотам (сегодня/недавние/…) — P2
- [Ф][open] группировка по категориям (капшены) — P2
- [Ф][open] сортировка «избранное вверх» + по дате изменения — P2
- [Ф][open] пустое состояние Welcome (текст + «Новая заметка» + «создать образец») — P2
- [Ф][open] «Найти во всех категориях» (сброс фильтра при пустом поиске в категории) — P3
- (состояние загрузки «Загрузка …» — Д)
Д (6, open 6): [Д][open] композиция экрана-списка · [Д][open] мобильная вёрстка по
_mobile-notes.css (content-list__search, перенос) · [Д][open] порядок элементов шапки ·
[Д][open] типографика (Raleway, тема) · [Д][open] иконки (звезда избранного, share-индикатор) ·
[Д][open] состояние загрузки/пустое
Экран 2. Меню заметки «⋯» (всплывающее, mail/087) — Ff 66.7% · Fd 0%
Полный состав из кода (NoteItem #actions), порядок сверен визуально:
Ф (6, open 2):
- [Ф][done] «Добавить/Удалить из избранного» (
setFavorite, юнит-тест) — данные готовы; UI P1-UI - [Ф][open] «Поделиться» → сайдбар шаринга (NC sharing) — P3
- [Ф][done] «<Категория>» / «Изменить категорию» (
setCategory) — данные готовы; UI-мультиселект P2 - [Ф][done] «Переименовать» (
rename) — данные готовы; UI-инлайн P2 - [Ф][done] «Удалить заметку» (
delete, юнит-тест) — данные готовы; UI P1-UI - [Ф][open] отмена удаления (
POST /notes/undo) — не реализовано — P2
Д (3, open 3): [Д][open] состав/порядок пунктов меню · [Д][open] иконки пунктов · [Д][open] инлайн-поля (переименование/категория)
Экран 3. Редактор заметки (rich / plain / preview) — Ff 10% · Fd 0%
Ф (10, open 9):
- [Ф][open] rich-редактор (@nextcloud/text) — P1
- [Ф][open] панель форматирования: жирный/курсив/цитата/моно/очистить/список/нумерованный/ заголовок/крупный заголовок/ссылка (всплывающая тулбар-панель, mail/087) — P2
- [Ф][open] plain-режим — P2
- [Ф][open] тумблер «Просмотр»/«Правка» (preview⇄edit) — P2
- [Ф][open] тумблер «Полный экран» — P3
- [Ф][done] автосохранение с
If-Match: "<etag>"(saveContent, юнит-тест 412) — данные готовы; UI-редактор P1-UI - [Ф][open] автозаголовок из первой строки (
PUT /autotitle) — P2 - [Ф][open] состояние read-only заметки (индикатор, блок правки) — P2
- [Ф][open] «Сохранение не удалось. Нажмите, чтобы повторить» (ручной ретрай) — P2
- [Ф][open] плейсхолдеры «Write …» / «Empty note» — P3
Д (5, open 5): [Д][open] вёрстка редактора · [Д][open] перенос тулбара форматирования на
мобильном (.text-menubar__entries flex-wrap) · [Д][open] типографика тела · [Д][open] меню
действий редактора (preview/fullscreen) · [Д][open] индикатор read-only
Экран 4. Диалог конфликта версий — Ff 33.3% · Fd 0%
Ф (3, open 2):
- [Ф][done] детект конфликта (412 на
If-Match→NoteConflictException+ перечитка серверной версии, юнит-тест) — логика готова; UI-диалог P1-UI - [Ф][open] «Использовать версию с сервера» — P1
- [Ф][open] «Использовать текущую версию» — P1
- (⚠ обязателен — НЕ молчаливая перезапись, согласовано mail/071 п.2)
Д (1, open 1): [Д][open] вёрстка диалога конфликта
Экран 5. Навигация категорий (шторка) — Ff 0% · Fd 0%
Всплывающие/контекстные меню категории (mail/087): «Новая категория», «⋯»-действия категории. Ф (8, open 8):
- [Ф][open] «Новая категория» (создать; drag заметки → назначить) — P2
- [Ф][open] «Все заметки» + счётчик (сброс фильтра) — P1
- [Ф][open] «Без категории» + счётчик — P2
- [Ф][open] список категорий + счётчики, фильтрация по тапу — P2
- [Ф][open] «Переименовать категорию» (инлайн) — P3
- [Ф][open] «Удалить категорию» + диалог подтверждения — P3
- [Ф][open] вложенные подкатегории (
parent/child) — P3 - [Ф][open] вход «Настройки заметок» (шестерёнка) — P2
Д (4, open 4): [Д][open] композиция шторки навигации · [Д][open] иконки папок (тема — серая
folder-gray.svg) · [Д][open] счётчики-бейджи · [Д][open] порядок (Все/Категории)
Экран 6. Модалка «Настройки заметок» — Ff 0% · Fd 0%
Ф (5, open 5):
- [Ф][open] «Отображение»: Форматированный текст / Простой текст / Просмотр — P2
- [Ф][open] «Расширение файла»: .md / .txt / Свой (+ поле) — P3
- [Ф][open] «Папка заметок» (WebDAV picker) — P3
- [Ф][open] секция «Мобильные приложения» (Android / iPhone) — P3
- [Ф][open] секция «Комбинации клавиш» (в теме скрыта) — n-a? (уточнить — пока open) — P3
Д (2, open 2): [Д][open] полноэкранная модалка на мобильном (_mobile-notes.css) ·
[Д][open] вёрстка секций/переключателей
Сводка
| Экран | Ф всего | Ф open | Ff% | Д всего | Д open | Fd% |
|---|---|---|---|---|---|---|
| 1. Список | 10 | 8 | 20.0% | 6 | 6 | 0% |
| 2. Меню «⋯» | 6 | 2 | 66.7% | 3 | 3 | 0% |
| 3. Редактор | 10 | 9 | 10.0% | 5 | 5 | 0% |
| 4. Конфликт | 3 | 2 | 33.3% | 1 | 1 | 0% |
| 5. Категории | 8 | 8 | 0% | 4 | 4 | 0% |
| 6. Настройки | 5 | 5 | 0% | 2 | 2 | 0% |
| Итого | 42 | 34 | 19.0% | 21 | 21 | 0% |
Ff_app = 21.7% (среднее по 6 экранам: 20+66.7+10+33.3+0+0) · Fd_app = 0.0% (UI не собран). Абсолютно: 8 из 42 Ф закрыты в коде (слой данных), 34 open. Fd — весь бэклог (нет ни одного собранного экрана).
Предлагаемый порядок реализации (план 1→2→3, mail/071)
- P1 — read-only ядро: список заметок (открыть/просмотр), rich-редактор, автосейв
If-Match, удаление, избранное, «Все заметки», диалог конфликта. (= итерация 1 плана) - P2 — запись/организация: создание, переименование, категории (создать/сменить/фильтр), автозаголовок, поиск, группировка, настройки отображения. (= итерация 2)
- P3 — добивка: шаринг, подкатегории, удаление/переименование категорий, полноэкранный
режим, расширение файла/папка, попиксельная вёрстка по
_mobile-notes.css. (= итерация 3)
Блокеры
Скелет модуля— снят: заведён лидом (133d80d, mail/096). Слой данных 1a — в коде (8a8f1cf).- NC-апп
notesна glb — установлен ли (для интеграционной проверки записи на живом сервере); лид спросил в PPS 069. До ответа write-путь проверяется юнит-тестами (MockWebServer), не на forbion (read-only, mail/073). НЕ блокирует разработку — только живую верификацию. - Повторный (подтверждающий) прогон для гейта — после реализации P1-UI, на устройстве/
bmob-*.
Дальше (следующий заход, автономно)
P1-UI: NotesScreen (список+поиск+пусто-состояние) → NoteEditorScreen (rich/plain/preview +
автосейв) → диалог ConflictSolution → регистрация экрана у лида (переключение веб-пункта меню
на нативный — зона app/, делает лид по готовности). Затем P2 (категории-CRUD/autotitle/undo/
settings), P3 (шаринг/добивка вёрстки).