diff --git a/docs/app-map/notes.md b/docs/app-map/notes.md new file mode 100644 index 0000000..d5381ab --- /dev/null +++ b/docs/app-map/notes.md @@ -0,0 +1,156 @@ +# Карта: Заметки + +Приложение «Заметки» (`/apps/notes/`) на forbion.f7cloud.ru. Структура кнопок/меню снята +**из кода** (метод mail/078): апстрим `nextcloud/notes` **v5.0.0** (`src/**/*.vue` — точная +версия с forbion, канон README) + мобильная тема forbion +(`design-reference/forbion-theme/css/pages/pages-mobile/_mobile-notes.css`, +`css/pages/app-notes/`). Живой мобильный web (Browser 1, `cloude`, mail/079) — только для +визуальной сверки «как выглядит/порядок»; **строго read-only** (mail/073): ничего не +создаётся/не меняется/не удаляется. Приватность: реальные заголовки/тексты заметок не +фиксируются — только структура UI и дерево переходов. + +> Статус визуальной сверки на живом forbion: **ожидает** — автопереход Chrome на forbion в +> моей сессии блокирует защитный классификатор (переход инициирован из письма, не владельцем). +> Дерево ниже построено из кода и валидно; отметки `визуал(?)` = требуют финального взгляда +> на экран. + +## Компоненты-источники (nextcloud/notes v5.0.0) +`App.vue` (шелл: навигация категорий + настройки) · `NotesView.vue` (список + поиск + «Новая +заметка») · `NotesList.vue`/`NoteItem.vue` (строка заметки + меню действий) · +`CategoriesList.vue` (навигация: Все заметки / Категории) · `Note.vue`→`NoteRich.vue` +(rich-редактор @nextcloud/text) / `NotePlain.vue` (простой/preview) · `AppSettings.vue` +(модалка настроек) · `Welcome.vue` (пустое состояние) · `ConflictSolution.vue` (конфликт +версий) · `NoteShareSidebar.vue` (шаринг). + +## Вход +Шторка приложений (по «трём полоскам») → «Заметки», или прямой URL `/apps/notes/`. +Оболочку (нижняя панель, шторка, бургер) описывает `shell.md` (зона лида) — здесь только +специфика приложения. На мобильном (узкий вьюпорт) сначала показывается **список заметок**; +выбор заметки открывает **редактор** поверх (`NcAppContent` show-details), возврат — «назад». + +## Экран: Список заметок (главный) +**Шапка списка (`content-list__search`):** +- Кнопка «**Новая заметка**» (primary, иконка +) → создаёт заметку и открывает редактор + (write — на forbion НЕ нажимаю). +- Поле «**Искать заметки**» (`Search for notes`) → фильтрация списка по заголовку по мере + ввода; крестик (trailing) очищает поиск. + +**Тело:** список строк-заметок, сгруппированный. Группировка (`NotesView` groupedNotes): +- если выбраны «Все заметки» и настроен режим — по **временным слотам** (заголовки-капшены + через `NotesCaption`: сегодня/недавние/… — таймслоты) и/или по **категориям**; +- избранные сортируются выше (favorite → вверх), затем по дате изменения. + +**Строка заметки (`NoteItem` = `NcListItem`):** +- Тап по строке → открыть заметку в редакторе. +- Индикатор «расшарена» (значок ShareVariant, если у заметки есть шаринг). +- Кнопка «**действия**» (⋮, меню строки) → см. «Меню заметки». + +**Пустое состояние (нет заметок / `Welcome.vue`):** заголовок «Заметки» + «Start writing a +note by clicking on “New note”» + кнопка «**Новая заметка**»; подсказки: «Пишите мысли без +отвлечений», «Используйте Markdown», кнопка «**Создать образец заметки с Markdown**» +(`CreateSampleButton` — write, не нажимаю), «Организуйте заметки по категориям». + +**Состояние загрузки:** «Загрузка …» (`Loading …`). **Пустой поиск в категории:** кнопка +«**Найти во всех категориях**» (сбрасывает выбранную категорию). + +## Меню заметки (⋮ в строке — `NoteItem` #actions) +Порядок пунктов из кода: +- «**Добавить в избранное**» / «**Удалить из избранного**» (тумблер, звезда) → `PUT /favorite`. +- «**Поделиться**» (Share) → открывает сайдбар шаринга (`NoteShareSidebar`, стандартный + NC-шэринг). *(состав панели — общий NC sharing; детально не раскрывал — визуал(?))* +- «**<Категория>**» / «**Изменить категорию**» → инлайн-выбор категории (мультиселект с + возможностью ввести новую, taggable) → `PUT /category`. +- «**Переименовать**» → инлайн-поле ввода нового заголовка → `PUT /title`. +- —— разделитель —— +- «**Удалить заметку**» (если не read-only) → удаление (`DELETE`) с возможностью отмены + (`POST /notes/undo`). (write — не выполняю на forbion.) + +## Экран: Редактор заметки +Открывается тапом по заметке или «Новая заметка». Режим определяется настройкой Display +(rich / plain / preview, см. Настройки). + +**Заголовок:** формируется автоматически из первой строки (autotitle, `PUT /autotitle`); +пустая заметка → «Новая заметка». + +**Rich-режим (`NoteRich` → редактор @nextcloud/text):** +- **Панель форматирования** (`.text-menubar` — в теме `_mobile-notes.css` она переносится на + мобильном: `flex-wrap: wrap`). Инструменты (из списка горячих клавиш `AppSettings`): + жирный, курсив, цитата, моноширинный, очистить стиль, список, нумерованный список, + заголовок / крупный заголовок, вставить ссылку. *(точный набор иконок на узком экране — + визуал(?))* +- Тело — редактируемый markdown-контент; автосохранение (debounce) → `PUT /notes/{id}` + с заголовком `If-Match: ""`. + +**Plain-режим (`NotePlain`) — меню действий редактора (`NcActions`):** +- «**Просмотр**» / «**Правка**» (тумблер preview⇄edit, подсказка «CTRL + /»). +- «**Полный экран**» / «**Выйти из полноэкранного режима**» (тумблер). +- Плейсхолдер пустого тела: «Write …» (или «Empty note» в preview). + +**Read-only заметка:** пункт-индикатор «**Заметка только для чтения. Вы не можете её +изменить.**» (`PencilOffOutline`), редактирование заблокировано. + +**Ошибка сохранения:** пункт «**Сохранение не удалось. Нажмите, чтобы повторить.**» +(`onManualSave`) — ручной повтор `PUT`. + +## Диалог: Конфликт версий (`ConflictSolution`) +Возникает, если заметка изменена в другой сессии (сервер вернул конфликт на `If-Match`): +- Текст: «Заметка была изменена в другой сессии. Выберите, какую версию сохранить.» +- Кнопка «**Использовать версию с сервера**». +- Кнопка «**Использовать текущую версию**». +> Прямое подтверждение моего плана (mail/071 п.2): конфликт разрешается ЯВНЫМ выбором, а не +> молчаливой перезаписью. Нативный `NoteEditorScreen` обязан воспроизвести этот диалог. + +## Навигация: Категории (левая шторка — `App.vue` + `CategoriesList`) +На мобильном — за «бургером»/шторкой навигации приложения (не нижняя панель оболочки). +- «**Новая категория**» (`NcAppNavigationNew`, иконка папка+) → создание категории + (drag-n-drop заметки на неё тоже вешает категорию). (write — не выполняю.) +- «**Все заметки**» + счётчик (bubble) → сброс фильтра категории, весь список. +- Капшен «**Категории**», далее список категорий: + - «**Без категории**» (uncategorized) + счётчик. + - Каждая категория: название (иконка папки, в теме заменена на серую + `folder-gray.svg`) + счётчик; действия: «**Переименовать категорию**» (инлайн-правка), + «**Удалить категорию**» → подтверждение (диалог «Удалить категорию» / «Удалить» / + «Отмена»). (write — не выполняю.) +- Подкатегории: имя вида `parent/child` разворачивается вложенно. +- Внизу навигации: «**Настройки заметок**» (шестерёнка) → модалка настроек. + +## Модалка: Настройки заметок (`AppSettings`) +На мобильном тема раскрывает её на весь экран (`_mobile-notes.css`: modal-container height +100%, скрыт заголовок modal-header). Секции: +- **Общее** (`General`): + - «**Отображение**» (Display): «Форматированный текст» (rich) / «Простой текст» (plain) / + «Просмотр» (preview). + - «**Расширение файла**» (для новых заметок): «.md» / «.txt» / «Свой» (+ поле «Своё + расширение файла»). + - «**Файлы**» → «**Папка заметок**» (`NcFormBoxButton`) → выбор папки хранения заметок + (WebDAV picker). (write-настройка — не меняю.) +- **Мобильные приложения** (`Mobile apps`) — ссылки/подсказки на приложения (в теме + секция клавиш-шорткатов и это скрыты частично — визуал(?)). +- **Комбинации клавиш** (`Shortcuts`) — справочный список (см. панель форматирования выше). + В теме forbion секция `keyboard-shortcuts` **скрыта** (`display:none`) — на forbion её, + вероятно, не видно. `визуал(?)` + +## API-контур (для нативного модуля — подтверждает mail/071) +Базовый путь `apps/notes/api/v1` (в вебе — `apps/notes/...`): +- `GET /notes?pruneBefore=` — список (инкрементальный синк по времени; в нашем клиенте — + `exclude=content` для лёгкого списка + ETag-коллекция). +- `GET /notes/{id}` — заметка; `POST /notes` — создать; `PUT /notes/{id}` (тело `content`, + заголовок `If-Match: ""`) — сохранить; `DELETE /notes/{id}`; `POST /notes/undo`. +- `PUT /notes/{id}/favorite`, `/category`, `/title`, `/autotitle`; + `PATCH /notes/category` (переименовать), `DELETE /notes/category` (удалить категорию). +- Поля модели: `id, title, category, content, favorite, modified, etag, readonly`. + +## Расхождения с нативным клиентом +Модуль `feature/notes` ещё **не создан** (скелет заводит лид по mail/071) — поэтому полный +список расхождений = весь функционал выше как первичный бэклог. Ключевые пункты к паритету +при реализации плана 1→2→3 (mail/071): +- Список: поиск по заголовку, группировка (таймслоты + категории), сортировка «избранное + вверх», индикатор шаринга, пустое/загрузочное состояния. +- Меню заметки: избранное, категория (с созданием новой), переименование, удаление с undo, + шаринг. +- Редактор: rich (панель форматирования) ↔ plain ↔ preview, полноэкранный режим, автосейв + с `If-Match`, автозаголовок, read-only состояние. +- **Диалог конфликта версий** (обязателен — не молчаливая перезапись). +- Категории: навигация «Все/Без категории/по категориям» со счётчиками, CRUD категорий, + вложенность `parent/child`. +- Настройки: режим отображения, расширение файла, папка заметок.