FlowNote · Бортжурнал с синхронизацией
FlowNote — хронологическая лента записей (текст, фото, аудио, файлы, AI) на Android и в браузере. Один аккаунт, один бакет Yandex Object Storage, один UX.
Возможности
- Лента — карточки с датой и временем, превью текста (2 строки) и миниатюрами медиа.
- Блоки записи — текст (markdown), камера, диктофон, произвольные файлы (в том числе видео), AI-запрос и ответ.
- Поиск — по тексту, тегам, именам и MIME файлов.
- Фильтры — все / текст / фото / аудио / файлы; отдельный браузер тегов.
- Действия — тап открывает редактор; long-press: теги, репост, AI-анализ, удаление; выделение и объединение записей.
- Шапка — слева аватар и email; справа выделение, синхронизация, бургер (настройки / выход).
- Auth — email и пароль через EuropaServer App Auth (
appId=flownote). - Синхронизация — Android ↔ Web через Yandex S3, offline-first, 3-way merge конфликтов.
- Настройки аккаунта — S3, AI (Bothub.chat) и аватар едут вместе с логином (LWW).
Требования
- Android: 8.0 (API 26) и выше; сборка:
compileSdk/targetSdk35, JDK 17, Android Studio с AGP 8.7. - Web: современный браузер, Node.js 18+ для
npm. - Auth: EuropaServer, плагин App Auth (порт 5030 / путь
/app-auth). - Sync: бакет Yandex Object Storage (S3 API), ключи Access/Secret.
- AI: сеть и API-ключ Bothub.chat (без ключа анализ недоступен).
- Камера и микрофон — опционально, для фото и диктофона.
Установка и запуск
Версия Android: 1.4.0 (versionCode 6). Gradle Wrapper: 8.9. Kotlin Android plugin: 2.0.21. Compose BOM: 2024.12.01.
1. Auth API (EuropaServer)
На VDS активируйте плагин:
sudo bash /home/projects/plugins/app-auth/setup.sh
Auth Base URL для клиентов: http://<server-ip>/app-auth
Локальный запуск плагина без nginx: http://localhost:5030
Эмулятор Android → ПК: http://10.0.2.2:5030
Аккаунты можно создавать в панели: http://<server-ip>/app-auth/
По умолчанию в клиентах: http://185.72.10.96/app-auth.
2. Android
- Клонируйте репозиторий и откройте проект в Android Studio.
- Синхронизируйте Gradle.
- Run
appна устройстве или эмуляторе.
Из корня проекта:
.\gradlew.bat assembleDebug
3. Web
cd web
npm install
npm run dev
Откройте http://localhost:5173 — тот же Auth API и те же настройки S3.
Сборка: npm run build, превью: npm run preview.
Использование
Вход и регистрация
- На экране входа укажите Auth API URL (если не подходит значение по умолчанию).
- Зарегистрируйтесь (email + пароль) или войдите.
- Сброс пароля по email пока отключён — смена в панели App Auth.
- После логина клиент подтягивает S3, AI и аватар из
/auth/me/config, если они уже привязаны к аккаунту.
Лента
- Карточки идут по времени. Поиск — поле в шапке.
- Иконки фильтров: все, текст, фото, аудио, файлы. Кнопка тегов открывает браузер тегов.
- FAB [+] создаёт новую запись.
- Тап по карточке открывает редактор (на Web ещё есть отдельный просмотр).
Шапка
- Слева: аватар и email.
- Справа: выделение записей → синхронизация (облако) → бургер (Настройки, Выйти).
Новая запись и блоки
- Нажмите [+] в ленте.
- Между блоками круглая кнопка [+] открывает меню: AI запрос, Текст, Камера, Диктофон, Файлы.
- Текст поддерживает markdown. Видео кладётся как файл с video MIME и играет inline.
- На Android системная «Назад» возвращает на ленту, не закрывает приложение.
Действия с записью
Долгое нажатие на карточку:
- Теги — список тегов записи.
- Репост — копия записи в ленту.
- AI анализ — разбор содержимого через Bothub.chat, результат как блок в записи.
- Удалить — soft-delete, уедет в синк.
Режим выделения: иконка в шапке → чекбоксы на карточках → объединение выбранных.
Настройки
Бургер → Настройки (иконка галочки сохраняет):
- Профиль — выбрать или сбросить аватар (файл в
users/{userId}/media/avatar.*). - Синхронизация — Auth URL, S3 endpoint / region / bucket / keys. Кнопки «Проверить S3» и «Синхронизировать сейчас».
- AI — ключ Bothub.chat, base URL, модель, vision-модель, температура, max tokens, длина текста.
При сохранении S3, AI и аватар пишутся в аккаунт (Auth API + account-config.json в S3) и подхватываются на другом устройстве после логина.
Синхронизация
- Заполните бакет и ключи (или получите их с аккаунта после логина).
- Нажмите облако в шапке или «Синхронизировать сейчас» в настройках.
- Offline: пишите локально (Room / IndexedDB). При сети клиент заливает очередь и тянет чужие записи.
- Конфликт правок одной записи — 3-way merge, обе стороны блоков сохраняются. Схема объектов — в
doc/SYNC.md.
CORS (Web → Yandex S3)
В кабинете Object Storage для бакета разрешите origin вашего Web-приложения:
- методы: GET, PUT, HEAD;
- Allowed headers:
*.
Без CORS браузер не достучится до бакета (Android ходит напрямую, CORS ему не нужен).
Структура проекта
FlowNote/
├── app/src/main/java/com/flownote/app/
│ ├── MainActivity.kt # точка входа
│ ├── data/ # Room, медиа, AI, профиль
│ ├── sync/ # S3, Auth, SyncEngine, merge
│ └── ui/ # экраны, ViewModel, компоненты
├── web/src/
│ ├── components/ # лента, редактор, настройки, теги
│ ├── hooks/ # useJournal
│ ├── lib/ # IndexedDB, Auth, S3, AI
│ ├── styles/ # tokens.css, global.css
│ └── types/
├── gradle/
├── doc/ # ARCHITECTURE, CHANGELOG, AI_RULES, SYNC, DESIGN
├── build.gradle.kts
└── README.md
Слои и потоки данных — в doc/ARCHITECTURE.md.
Технологии
- Kotlin / Java 17 — Android-клиент.
- Android Gradle Plugin 8.7.3, Gradle 8.9 — модуль
:app. - Jetpack Compose (BOM 2024.12.01), Material 3 — экраны без XML-layout.
- Room 2.6.1 — локальная база
flownote.dbv5 (journal_entries+journal_blocks). - Coil 2.7 / OkHttp 4.12 — картинки и HTTP (Auth, S3, Bothub).
- React 19, TypeScript 5.7, Vite 6 — Web-клиент.
- IndexedDB v4 — локальное хранилище Web (
entries,blocks). - EuropaServer App Auth — JWT,
appId=flownote. - Yandex Object Storage — журнал, медиа, конфиг аккаунта (S3 API, AWS Signature V4).
Разрешения (Android)
| Разрешение | Зачем |
|————|———|
| CAMERA | фото блока «Камера» (камера не обязательна) |
| RECORD_AUDIO | диктофон |
| INTERNET | Auth, S3, Bothub |
| READ_EXTERNAL_STORAGE | файлы на Android 12 и ниже (maxSdkVersion 32) |
| READ_MEDIA_IMAGES, READ_MEDIA_AUDIO | медиа на Android 13+ |
HTTP к Auth API разрешён через network_security_config (cleartext). FileProvider — кэш камеры.
Настройка AI (Bothub.chat)
- Получите API-ключ Bothub.chat.
- Настройки → вставьте ключ → сохраните. Ключ не хранится в исходниках, едет в конфиге аккаунта.
Параметры по умолчанию:
- Base URL:
https://bothub.chat/api/v2/openai/v1 - Модель:
gemini-2.0-flash-001 - Vision-модель:
gpt-4.1 - Температура:
0.7 - Макс. токенов:
1200 - Макс. длина текста:
5000символов
История изменений
[Unreleased]
Added
- Конфиг аккаунта (S3, AI, аватар) следует за логином: Auth API
/auth/me/config+account-config.jsonв S3, LWW поupdatedAt - Аватар в профиле и шапке; загрузка в
users/{userId}/media/avatar.* - Web
SyncEngine— полный паритет с Android (manifest, entries, media, 3-way merge, конфликты)
Changed
- Room v5, IndexedDB v4 — поля синка и
conflictOfу блоков - README приведён к полной структуре: требования, установка, сценарии (вход, лента, блоки, действия, настройки, синк), дерево, стек, разрешения Android, AI и CORS
- ARCHITECTURE: шапка (аватар / выделение / синк / бургер), offline-first, дерево
data/иweb/src
[1.5.0] — 2026-08-11
Changed
- Auth переведён на EuropaServer плагин App Auth (
appId=flownote); локальныйauth-server/удалён - Клиенты передают
appIdв register/login; сброс пароля по email временно недоступен (смена в панели/app-auth/)
[1.4.0] — 2026-07-15
Added
- Auth API (
auth-server/): регистрация/логин по email, восстановление пароля - Настройки Yandex S3 в приложении (endpoint, region, bucket, keys, Auth URL)
- Android
SyncEngine: manifest, entries/media upload-download, 3-way merge с архивом конфликтов - UUID
remoteId,revision,syncStatus, soft-delete для синка - Кнопка синхронизации в шапке; документация SYNC.md
Changed
- Экран входа: email/пароль вместо локального имени аккаунта
- Версия приложения 1.4.0
[1.3.0] — 2026-07-10
Added
- Фильтры ленты с иконками вместо текста; кнопка «Теги» и экран браузера тегов
- Блок «AI запрос» с кнопкой Ai и ответом в оранжевом текстовом блоке
- Кнопка редактирования в просмотре записи
- Drag-and-drop перестановка блоков в редакторе
- Системная кнопка «Назад» возвращает на ленту (не выходит из приложения)
Changed
- Полноэкранный сине-фиолетовый градиент и glassmorphism: прозрачные шапки, полупрозрачные карточки и чипы (Android + Web)
- Круглая бледная кнопка [+] между блоками, накладывается на соседние элементы
- Видео в просмотре воспроизводится inline с кнопкой play/pause
- Тап по карточке открывает запись сразу в редакторе (режим просмотра объединён с редактированием)
- AI-блоки в редакторе — одно редактируемое поле (без дубля превью)
- В карточках ленты текст обрезается до 2 строк; для обычных записей убрана подпись «Запись» (остаётся только дата / «Репост»)
- Кнопка [+] между блоками — только иконка без фона и обводки
- Тап по картинке в блоке открывает полноэкранный просмотр
- «Диктофон» открывает диалог записи звука (а не выбор файла)
[1.2.0] — 2026-07-08
Added
- Сохранение фото с камеры в галерею устройства (Android, MediaStore)
- Просмотр и воспроизведение медиа в редакторе и просмотре записи (аудио, видео, изображения, открытие файлов)
- Поиск по тексту, тегам, именам и типам файлов
- Экран настроек AI (Bothub.chat): API key, base URL, модели, температура, max tokens
- Интеграция AI-анализа с Bothub.chat OpenAI-compatible API (при указанном ключе)
Changed
- В ленте у «Запись» / «Репост» отображается дата; время — справа
- Заглушка с расширением файла только в свёрнутых карточках и только для не-картинок
- Кнопка настроек рядом с профилем в шапке
[1.1.0] — 2026-07-08
Added
- Новая модель данных: Запись (контейнер) + Блоки (текст, фото, аудио, файл, AI-анализ)
- Универсальный экран добавления/редактирования с кнопкой
[+]между блоками - Меню блоков: Текст, Камера, Диктофон, Файлы (множественный выбор на Web)
- Просмотр записи по короткому нажатию
- Долгое нажатие → Редактировать, Теги, Репост, AI анализ, Удалить
- AI анализ добавляется как выделенный текстовый блок внутри записи
- Сокращённый превью в ленте: 4 миниатюры файлов + обрезанный текст
- Режим выделения и объединения записей (чекбокс + «Объединить»)
- Фильтр «Файлы» в панели типов
Changed
- Room DB v4 / IndexedDB v3 — раздельные таблицы
journal_entriesиjournal_blocks - Android и Web синхронизированы по UX
[1.0.1] — 2026-07-07
Fixed
- Краш при запуске из-за несовместимой схемы Room после добавления
accountId - Миграции БД 1→2 и 2→3 с проверкой колонки
accountId - Отложенная инициализация Room до входа в аккаунт
- Разделение экрана авторизации и основного журнала
[1.2.0] — 2026-07-07
Added
- Начальный экран авторизации для Android и Web
- Создание и вход в локальные аккаунты по имени
- Переключение аккаунтов и logout в шапке приложения
- Разделение записей журнала по
accountIdна обеих платформах
Changed
- Android Room схема обновлена:
journal_entries.accountId(DB version 2) - Web IndexedDB схема обновлена: индекс
accountId
[1.1.0] — 2026-07-06
Added
- Web-версия (
web/) — React + Vite + TypeScript - Адаптивный UI: мобильный full-bleed + desktop «окно» 720px
- IndexedDB для локального хранения записей
- Камера и запись аудио через Web API (getUserMedia, MediaRecorder)
- doc/DESIGN.md — общие design tokens Android ↔ Web
Changed
- README: инструкции для Android и Web
- ARCHITECTURE: мультиплатформенная схема
[1.0.0] — 2026-07-06
Added
- Начальная версия Android-приложения FlowNote (бортжурнал)
- Экран-лента записей в формате чата (
JournalScreen) - Типы записей: текст, фото (камера / галерея), аудио
- Панель фильтров по типу (FilterChip)
- FAB [+] с bottom sheet выбора типа контента
- Действия по тапу на запись: репост, AI анализ (заглушка)
- Локальная БД Room (
journal_entries)
Технические заметки
- AI анализ — локальная заглушка на обеих платформах
- Синхронизация между Android и Web пока отсутствует




