Cozy World — это Flutter-приложение для управления важными датами, ежедневными сообщениями поддержки, категоризированным контентом и воспоминаниями. Проект демонстрирует best practices чистой архитектуры (Clean Architecture), работу с GraphQL, управление состоянием и локальное хранилище в Flutter.
- О проекте
- Что уже реализовано
- Технологии
- Архитектура
- Структура репозитория
- Требования
- Быстрый старт
- Установка и разработка
- Конфигурация и секреты
- GraphQL и генерация кода
- Тесты и качество кода
- Сборка релиза
- Вклад в проект
- Безопасность
- Лицензия
Приложение построено как Android-first Flutter-проект и использует:
- Router 2.0 для декларативной навигации.
- GetX для DI и управления состоянием контроллеров.
- Ferry (GraphQL client) для запросов и мутаций к Supabase GraphQL.
- flutter_secure_storage + get_storage для хранения конфигурации и локального состояния.
Точка входа: lib/main.dart.
- Экран счетчика: расчет прошедшего времени от опорных дат (знакомство/отношения).
- Экран поддержки: сообщение дня + сетка категорий сообщений.
- Экран категории: карточки сообщений с переворотом и изменением статуса прочитано/непрочитано.
- Экран истории: свайп-карточки фото с предзагрузкой и пустыми состояниями.
- Обработка ошибок и локализованные строки в слоях data/domain/presentation.
- Инициализация зависимостей по слоям (
setupDataLayer,setupDomainLayer,setupPresentationLayer).
- Язык: Dart
- Фреймворк: Flutter
- State Management / DI: GetX
- Сеть: GraphQL (Ferry + gql_http_link)
- Хранилище: flutter_secure_storage, get_storage
- UI: Lottie, flip_card, flutter_card_swiper, auto_size_text
- Линтинг: flutter_lints
- Генерация: build_runner + ferry_generator
Проект организован по слоям:
lib/data:- источники данных (локальные/статические/GraphQL),
- реализации репозиториев,
- сервис подключения GraphQL-клиента.
lib/domain:- сущности,
- интерфейсы репозиториев,
- use-case классы.
lib/presentation:- страницы,
- контроллеры,
- маршрутизация (Router 2.0),
- общие UI-компоненты.
Особенность конфигурации: API-ключ и endpoint берутся через String.fromEnvironment (ключи apiKey и endPointUrl) с fallback в flutter_secure_storage.
lib/
config/ # DI и конфигурация зависимостей
core/ # тема, утилиты, расширения
data/ # Data Layer
constants/ # GraphQL конфиг
datasources/ # интерфейсы и реализации источников данных
exceptions/ # исключения слоя данных
implementations/ # реализации репозиториев и сервисов
mappers/ # маппинг между слоями
services/ # сервисы (GraphQL подключение)
strings/ # централизованные строки данных
domain/ # Domain Layer
constants/ # бизнес-константы
entities/ # сущности (value objects)
exceptions/ # исключения
failures/ # типы ошибок/результатов
repositories/ # интерфейсы репозиториев
strings/ # строки domain слоя
usecases/ # бизнес-логика (use cases)
presentation/ # Presentation Layer
exceptions/ # ошибки UI
extensions/ # расширения (enum utils, etc)
modules/ # экраны (по feature: counter, support, history)
routes/ # маршрутизация
services/ # сервисы UI (навигация)
shared/ # переиспользуемые виджеты и утилиты
strings/ # строки интерфейса
utils/ # вспомогательные классы UI
main.dart # точка входа
packages/
app_assets/ # централизованные ассеты и константы
dates_api/ # интерфейс API для работы с датами
dates_impl/ # реализация работы с датами
strings_api/ # интерфейс API для строк
strings_impl/ # реализация (все строки приложения)
private_*/ # приватные пакеты (не для публикации)
assets/ # Lottie анимации, иконки, иллюстрации
test/
widget_test.dart # smoke-тесты инициализации приложения
android/
key.properties.example # шаблон локального файла подписи
.gitignore # Android-специфичные игнорления
.github/
workflows/ # GitHub Actions CI/CD
.pre-commit-config.yaml # Pre-commit hooks для локальной разработки
analysis_options.yaml # Dart анализ и linting правила
pubspec.yaml # дефиниции зависимостей и метаданные
build.yaml # конфигурация build_runner для генерации кода
- Flutter SDK с поддержкой Dart
^3.10.3. - Android SDK (проект ориентирован на Android).
- Установленные зависимости Flutter toolchain (
flutter doctorбез критичных ошибок).
- Flutter SDK 3.10.3 или выше (
flutter doctorдолжен пройти без критичных ошибок) - Dart 3.10.3 или выше
- Android SDK (minSdk 21 по умолчанию)
- Git
git clone https://github.com/Yukovsky/cozy-world
cd cozy_world
flutter pub get
dart run build_runner build --delete-conflicting-outputsflutter runflutter run \
--dart-define=apiKey=YOUR_SUPABASE_ANON_KEY \
--dart-define=endPointUrl=https://your-project.supabase.co/graphql/v1# Статический анализ
flutter analyze
# Запуск тестов
flutter test
# Форматирование кода
dart format .Подробную инструкцию см. в INSTALL.md, которая включает:
- Установку зависимостей
- Конфигурацию локальной разработки
- Настройку подписей Android
- Инструкции по pre-commit hooks
- Типичные ошибки и их решение
Быстро: Если у вас уже установлены Flutter и Android SDK:
git clone https://github.com/Yukovsky/cozy-world
cd cozy_world
flutter pub get
dart run build_runner build --delete-conflicting-outputs
flutter runAPI-ключ и endpoint для GraphQL можно передать тремя способами (в порядке приоритета):
-
IDE/командная строка (разработка):
flutter run \ --dart-define=apiKey=YOUR_KEY \ --dart-define=endPointUrl=https://...
-
Файл конфигурации (
lib/config/.env, не коммитить):apiKey=YOUR_SUPABASE_ANON_KEY endPointUrl=https://your-project.supabase.co/graphql/v1 -
Secure storage (fallback при запуске): Приложение сохраняет конфиг в защищённое хранилище
flutter_secure_storage.
Для сборки release-версии:
-
Скопируйте android/key.properties.example в
android/key.properties. -
Заполните реальными значениями:
storePassword— пароль keystore файлаkeyPassword— пароль приватного ключаkeyAlias— alias ключа в keystorestoreFile— абсолютный путь кkeystore.jks
-
НИКОГДА не коммитьте реальный
android/key.properties.
- Ротируйте ключ у провайдера (Supabase, и т.д.)
- Выпустите новый release
- Сообщите об инциденте в SECURITY.md
Схема GraphQL: lib/data/datasources/remote/graphql/schema/schema.graphql.
Запросы и мутации:
lib/data/datasources/remote/graphql/queries/*.graphqllib/data/datasources/remote/graphql/mutations/*.graphql
Генерация (build.yaml уже настроен):
dart run build_runner build --delete-conflicting-outputsПри активной разработке:
dart run build_runner watch --delete-conflicting-outputsПроверка проекта перед commit или push:
flutter analyze
flutter test
dart format . --set-exit-if-changedНа данный момент в test/widget_test.dart есть smoke-test инициализации приложения.
Для автоматической проверки перед каждым коммитом установите pre-commit:
pip install pre-commit
pre-commit installЭто установит hooks для проверки:
- Форматирования Dart кода
- Статического анализа Flutter
- Утечек секретов (trufflehog, gitleaks)
- Git конфликтов и других проблем
Подробнее: PRE_COMMIT_SETUP.md
На каждый push и pull request:
- Запускается
flutter analyze - Запускаются все тесты
- Проверяется форматирование
- Сканируются потенциальные секреты
- Собирается debug APK
Workflows находятся в .github/workflows/.
Перед релизом Android:
- Создать локальный
android/key.propertiesпо шаблону. - Убедиться, что keystore-файл доступен по пути
storeFile. - Передать production-конфиг через
--dart-define.
Команда сборки APK:
flutter build apk --release \
--dart-define=apiKey=YOUR_SUPABASE_ANON_KEY \
--dart-define=endPointUrl=https://YOUR_PROJECT.supabase.co/graphql/v1Команда сборки App Bundle:
flutter build appbundle --release \
--dart-define=apiKey=YOUR_SUPABASE_ANON_KEY \
--dart-define=endPointUrl=https://YOUR_PROJECT.supabase.co/graphql/v1Спасибо за интерес к проекту! Инструкции для контрибьюторов описаны в CONTRIBUTING.md.
Быстро:
- Форкните репо и создайте ветку:
git checkout -b feature/ваша-фишка - Убедитесь что локально работает:
flutter analyze flutter test dart format . --set-exit-if-changed
- Создайте Pull Request с описанием изменений
Важно: Перед PR убедитесь что нет утечек секретов:
# Pre-commit hooks проверят автоматически, или вручную:
git diff HEAD — ':(exclude)*.example' | grep -E "password|apiKey|token|secret"Если вы обнаружили уязвимость, не публикуйте ее в открытом issue.
Процесс ответственного раскрытия (responsible disclosure) описан в SECURITY.md.
Краткая инструкция:
- Отправьте приватное сообщение с описанием уязвимости
- Укажите шаги для воспроизведения
- Предоставьте рекомендации по исправлению
Спасибо за помощь в улучшении безопасности проекта!
Проект распространяется по лицензии MIT. Подробности: LICENSE.
- INSTALL.md — пошаговая установка и настройка
- CONTRIBUTING.md — как контрибьютить в проект
- SECURITY.md — как сообщить об уязвимостях
- CODE_OF_CONDUCT.md — правила поведения в сообществе
- PRE_COMMIT_SETUP.md — настройка pre-commit hooks
- PRE_RELEASE_CHECKLIST.md — чеклист перед релизом