29560a6865
Read-only, метод mail/078. Визуальная сверка на forbion ожидает (блокер автоперехода Chrome). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
157 lines
14 KiB
Markdown
157 lines
14 KiB
Markdown
# Карта: Заметки
|
||
|
||
Приложение «Заметки» (`/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: "<etag>"`.
|
||
|
||
**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=<ts>` — список (инкрементальный синк по времени; в нашем клиенте —
|
||
`exclude=content` для лёгкого списка + ETag-коллекция).
|
||
- `GET /notes/{id}` — заметка; `POST /notes` — создать; `PUT /notes/{id}` (тело `content`,
|
||
заголовок `If-Match: "<etag>"`) — сохранить; `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`.
|
||
- Настройки: режим отображения, расширение файла, папка заметок.
|