feat(calendar): P1 разворот повторений — CalendarRecurrence (RRULE-оккуренции на лету) + eventOccursOnDay RRULE-осознан +11 тестов; refresh detekt-baseline (v0.5.144-долг)

This commit is contained in:
b-mob-calendar
2026-07-13 07:36:19 +00:00
parent 1c1e9c89e2
commit e7d0a5a9ee
6 changed files with 442 additions and 94 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
| notes | b-mob-notes | 1 | 21.7 | 0.0 | 34 | 21 | нет | P1 слой данных в коде+юнит-тест (`8a8f1cf`: Notes API v1 клиент/репо/ETag-кэш/конфликт 412); скелет заведён лидом (`133d80d`); далее P1-UI (экраны/редактор/диалог) |
| notifications | b-mob-notify | 0 | — | — | — | — | нет | карта готова, diff |
| deck | b-mob-deck | 1 | 22.6 | предв. | 52 | ? | нет | P1 начат: «Назначить мне/снять» done (6eeba1b, green compile); далее бейджи чек-пунктов/комментариев, меню колонки (Удалить/Переименовать), быстрые сроки; Fd на устройстве |
| calendar | b-mob-calendar | 1 | 51.6 | 67.0 | ~38 | ~7 | нет | diff итер.1 (`calendar.diff.md`); P1 разворот повторений; Appointments — вопрос n-a лиду |
| calendar | b-mob-calendar | 1 | 53.3 | 67.0 | ~37 | ~7 | нет | P1 разворот повторений ЗАКРЫТ в коде (`CalendarRecurrence`+11 тестов, compile+detekt green); NB: обновил протухший detekt-baseline модуля (v0.5.144-долг, не мой); далее P2 EXDATE/RECURRENCE-ID; Appointments — вопрос n-a лиду |
| contacts | b-mob-contacts | 1 | 26.7 | предв. | ~40 | ? | нет | diff выложен (7 экранов); P1 — edit/delete (core-правка одобрена 072), далее группы/типы |
Обозначения статуса: `карта``diff` (итерация 1) → `правки``повторный прогон`
+18 -12
View File
@@ -1,9 +1,15 @@
# Diff: Календарь (Calendar) — итерация 1 (2026-07-13)
Ff_app: **51.6%** · Fd_app: **67.0%** (среднее по 6 экранам, невзвешенно) · n-a: 0
_(без экрана Appointments, если владелец сочтёт его мобильно-неприменимым: Ff_app **62.0%** /
Ff_app: **53.3%** · Fd_app: **67.0%** (среднее по 6 экранам, невзвешенно) · n-a: 0
_(без экрана Appointments, если владелец сочтёт его мобильно-неприменимым: Ff_app **64.0%** /
Fd_app **80.4%** по 5 экранам — вопрос лиду в конце.)_
> **P1 закрыт в коде** (итерация правок 1): разворот повторяющихся событий реализован —
> `CalendarRecurrence` (генератор оккуренций RRULE на лету, без кэша и без `<c:expand>`,
> mail/072) + `eventOccursOnDay` теперь RRULE-осознан; +11 юнит-тестов
> (`CalendarRecurrenceTest`, зелёные), `:feature:calendar:compileReleaseKotlin`+`detekt` green.
> Ждёт девайс-сверки (подтверждающий второй прогон, mail/084).
Сверка веб (`nextcloud/calendar v6.4.0` + тема `_mobile-calendar.css`, карта `calendar.md`) ↔
натив (`feature/calendar`: `CalendarScreen`, `CalendarComponents`, `CalendarExtendedUi`,
`CalendarViewModel`, `CalendarRepository`, `RecurrenceRule`). Метки: `[Ф|Д]` · `[open|done|n-a]`.
@@ -21,17 +27,17 @@ mail/085) добавлю следующим проходом — этот про
---
## Экран 1. Календарь (сетка + шапка + виды) — Ff 90.0% · Fd 75.0%
Ф (10, open 1):
## Экран 1. Календарь (сетка + шапка + виды) — Ff 100% · Fd 75.0%
Ф (10, open 0):
- [Ф][done] предыдущий/следующий период · [Ф][done] «Сегодня»
- [Ф][done] переключатель вида: День/Неделя/Месяц/**Год/Список** (все 5, `CalendarViewMode`)
- [Ф][done] «Создать событие» · [Ф][done] открыть навигацию (бургер)
- [Ф][done] тап по дню → выбор дня · [Ф][done] тап по событию → открыть
- [Ф][done] «Показать незапланированные задачи» (`loadUnscheduledTasks`)
- [Ф][open] **разворот повторяющихся событий в сетке**`rememberEventsByDay`
`eventOccursOnDay` кладёт событие только на DTSTART (для timed) / DTSTART..DTEND (all-day),
**RRULE НЕ итерируется**: 2-я и дальше оккуренции в сетке/списке не видны (долг №2 mail/072,
подтверждён лидом). Это ядро P1.
- [Ф][done] **разворот повторяющихся событий в сетке**реализован: `CalendarRecurrence`
генерирует оккуренции RRULE (DAILY/WEEKLY+BYDAY/MONTHLY/YEARLY, INTERVAL, UNTIL/COUNT) на
лету, `eventOccursOnDay` теперь RRULE-осознан → 2-я и дальше оккуренции видны в сетке/списке/
дне (долг №2 закрыт в коде; +11 юнит-тестов). Ждёт девайс-сверки.
Д (8, open 2): [Д][done] безрамочная месячная сетка + гридлайны (v0.5.114) · [Д][done] «сегодня»
в зелёном круге · [Д][done] пилюли событий (до 2 + «+N») · [Д][done] пилюли дней недели ·
[Д][done] таймлайн День/Неделя · [Д][done] русская локализация шапки · [Д][open] пиксель-вид
@@ -140,10 +146,10 @@ pill-поля 40dp, шапка с крестиком/галочкой, высо
Натив: Изменить `done` (открывает диалог с удалением) · Экспорт/Копировать-ссылку `open`.
## Предлагаемый порядок правок (жду приоритизацию лида)
- **P1 — Разворот повторений в сетке/списке** (Экран 1, долг №2): в `CalendarRepository`
реализовать генерацию оккуренций по RRULE в видимом диапазоне поверх CTag-кэша (по граблям из
ответа лида mail/072: развёртка ПОСЛЕ парсинга, экземпляры не кэшировать, ключ уникальности
`uid+recurrenceStart`). Заодно вскроется `RecurrenceRule.toRrule` для `BYDAY=1MO`.
- **P1 — Разворот повторений в сетке/списке** (Экран 1, долг №2): **СДЕЛАНО в коде**
(`CalendarRecurrence` + `eventOccursOnDay`, mail/072-совместимо: развёртка на лету, без кэша
и `<c:expand>`; +11 тестов). Остаётся девайс-сверка (подтверждающий прогон). NB: `BYDAY=1MO`
(месячный n-й день недели) в модели `RecurrenceRule` ещё не хранится — уходит в P2.
- **P2 — EXDATE + RECURRENCE-ID** (Экран 6, долг №3): чтение EXDATE (не показывать удалённые
оккуренции) → выбор области правки/удаления «это / это и будущие» → запись без затирания серии.
- **P3 — Настройки** (Экран 4): вынести веб-параметры (номера недель/выходные/задачи-в-календаре/