Skip to content

Latest commit

Β 

History

History
416 lines (307 loc) Β· 16.4 KB

File metadata and controls

416 lines (307 loc) Β· 16.4 KB

OnTime Flutter Project Architecture

This document provides a comprehensive overview of the OnTime Flutter project's architecture, folder structure, and design patterns.

πŸ—οΈ Architecture Overview

OnTime follows Clean Architecture principles with a clear separation of concerns across three main layers:

  • Presentation Layer: UI components, state management (BLoC/Cubit), and navigation
  • Domain Layer: Business logic, entities, use cases, and repository interfaces
  • Data Layer: Repository implementations, data sources (local/remote), and data models

Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    PRESENTATION LAYER                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ Screens & Components                                     β”‚
β”‚  β€’ BLoC/Cubit (State Management)                           β”‚
β”‚  β€’ Navigation (GoRouter)                                   β”‚
β”‚  β€’ Theme & Localization                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     DOMAIN LAYER                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ Entities (Business Objects)                             β”‚
β”‚  β€’ Use Cases (Business Logic)                              β”‚
β”‚  β€’ Repository Interfaces                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      DATA LAYER                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β€’ Repository Implementations                              β”‚
β”‚  β€’ Data Sources (Remote API, Local Database, Local Storage)β”‚
β”‚  β€’ Data Models (JSON Serialization)                        β”‚
β”‚  β€’ Database Tables & DAOs                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“ Project Structure

lib/
β”œβ”€β”€ πŸ“± presentation/          # UI Layer (Screens, Widgets, State Management)
β”‚   β”œβ”€β”€ alarm/               # Alarm and timer functionality
β”‚   β”œβ”€β”€ app/                 # Main app setup and global BLoC
β”‚   β”œβ”€β”€ calendar/            # Calendar views and components
β”‚   β”œβ”€β”€ early_late/          # Early/late arrival screens
β”‚   β”œβ”€β”€ home/                # Home screen and dashboard
β”‚   β”œβ”€β”€ login/               # Authentication screens
β”‚   β”œβ”€β”€ my_page/             # User profile and settings
β”‚   β”œβ”€β”€ notification_allow/  # Notification permission
β”‚   β”œβ”€β”€ onboarding/          # User onboarding flow
β”‚   β”œβ”€β”€ schedule_create/     # Schedule creation and editing
β”‚   └── shared/              # Shared UI components and utilities
β”‚       β”œβ”€β”€ components/      # Reusable widgets
β”‚       β”œβ”€β”€ router/          # Navigation configuration
β”‚       β”œβ”€β”€ theme/           # App theming
β”‚       └── utils/           # UI utilities
β”‚
β”œβ”€β”€ 🏒 domain/               # Business Logic Layer
β”‚   β”œβ”€β”€ entities/            # Business objects (User, Schedule, etc.)
β”‚   β”œβ”€β”€ repositories/        # Repository interfaces
β”‚   └── use-cases/           # Business logic operations
β”‚
β”œβ”€β”€ πŸ’Ύ data/                 # Data Access Layer
β”‚   β”œβ”€β”€ daos/                # Database Access Objects (Drift)
β”‚   β”œβ”€β”€ data_sources/        # Data source interfaces/implementations
β”‚   β”œβ”€β”€ models/              # API request/response models
β”‚   β”œβ”€β”€ repositories/        # Repository implementations
β”‚   └── tables/              # Database table definitions
β”‚
β”œβ”€β”€ πŸ”§ core/                 # Core Infrastructure
β”‚   β”œβ”€β”€ constants/           # App constants and environment variables
β”‚   β”œβ”€β”€ database/            # Database configuration (Drift)
β”‚   β”œβ”€β”€ di/                  # Dependency injection setup (Injectable)
β”‚   β”œβ”€β”€ dio/                 # HTTP client configuration
β”‚   β”œβ”€β”€ services/            # Core services (navigation, notifications)
β”‚   └── utils/               # Core utilities and converters
β”‚
β”œβ”€β”€ 🌍 l10n/                 # Localization files
β”œβ”€β”€ firebase_options.dart    # Firebase configuration
└── main.dart               # Application entry point

πŸ› οΈ Technology Stack

Core Framework & Language

  • Flutter: Cross-platform mobile framework
  • Dart: Programming language

State Management

  • BLoC/Cubit: Business Logic Component pattern for state management
  • Riverpod: Additional state management for specific use cases
  • Equatable: Value equality for state objects

Dependency Injection

  • Injectable: Code generation for dependency injection
  • GetIt: Service locator pattern

Database & Persistence

  • Drift: Type-safe SQL database library
  • SharedPreferences: Simple key-value storage
  • FlutterSecureStorage: Secure token storage

Networking

  • Dio: HTTP client with interceptors
  • JSON Annotation: JSON serialization code generation

Navigation

  • GoRouter: Declarative routing solution

UI Components

  • Material Design: Google's design system
  • Flutter SVG: SVG asset support
  • TableCalendar: Calendar widget

Authentication

  • Google Sign-In: Google OAuth integration
  • Kakao SDK: Kakao social login
  • Firebase Auth: Authentication backend

Notifications

  • Firebase Messaging: Push notifications
  • Flutter Local Notifications: Local notifications

Development Tools

  • Freezed: Code generation for immutable classes
  • Build Runner: Code generation runner
  • Widgetbook: Component development environment

πŸ“‹ Architecture Patterns

1. Clean Architecture Layers

Presentation Layer

  • Screens: Full-screen widgets representing app pages
  • Components: Reusable UI widgets
  • BLoC/Cubit: State management following BLoC pattern
  • Navigation: Declarative routing with GoRouter

Domain Layer

  • Entities: Core business objects using Freezed for immutability
  • Use Cases: Single-responsibility business logic operations
  • Repository Interfaces: Contracts for data access

Data Layer

  • Repository Implementations: Concrete implementations of domain interfaces
  • Data Sources: Abstraction over remote APIs and local storage
  • Models: Data transfer objects with JSON serialization

2. Dependency Injection

// Injectable annotation for automatic registration
@Injectable()
class UserRepository implements UserRepositoryInterface {
  // Implementation
}

// GetIt service locator configuration
final getIt = GetIt.instance;

@InjectableInit()
void configureDependencies() => getIt.init();

3. State Management with BLoC

// BLoC for handling user authentication state
@Injectable()
class AppBloc extends Bloc<AppEvent, AppState> {
  AppBloc(this._streamUserUseCase, this._signOutUseCase)
      : super(AppState(user: const UserEntity.empty())) {
    on<AppUserSubscriptionRequested>(_onUserSubscriptionRequested);
    on<AppSignOutPressed>(_onSignOutPressed);
  }
}

4. Data Models with JSON Serialization

@JsonSerializable()
class GetUserResponseModel {
  final int userId;
  final String email;
  final String name;

  // Conversion to domain entity
  UserEntity toEntity() {
    return UserEntity(
      id: userId.toString(),
      email: email,
      name: name,
    );
  }
}

5. Database Layer with Drift

AppDatabase uses encrypted local schema 4 and eleven owned tables. The checked-in historical contracts independently describe schemas 1–4; the shared current-version and supported-lineage declaration lives in lib/core/database/schema_contracts.schema.json. build_runner embeds that input in an ignored generated Dart file, and CI validates its digest and the executable DDL.

Normal legacy startup may migrate supported schemas 1/2/3 to 4. Active replacement pairs start with schema 4; candidate validation never implicitly migrates. Before writes, openers require SQLCipher, the existing key, and a matching historical schema. Unknown, partial, future, and nonempty version-zero stores remain preserved for Recovery. Creation requires the initial-store guard or explicit owned candidate authority.

Migration DDL, backfill, schema/foreign-key checks and user_version commit in one SQLite transaction. The later Drift version acknowledgement can still fail after a complete commit, so response errors alone do not prove rollback. Foreign-key connection settings remain outside the transaction. See ADR 0023 and the D04 historical fixtures for invariants and evidence scope.

πŸ”„ Data Flow

1. User Interaction Flow

User Input β†’ Widget β†’ BLoC Event β†’ Use Case β†’ Repository β†’ Data Source β†’ API/DB
                ↓
Widget ← BLoC State ← Use Case ← Repository ← Data Source ← Response

2. Authentication Flow

Login Screen β†’ AppBloc β†’ SignInUseCase β†’ UserRepository β†’ AuthDataSource β†’ API
      ↓
Navigation ← AppBloc ← UserEntity ← UserRepository ← AuthDataSource ← Token

3. Schedule Management Flow

Schedule Form β†’ ScheduleBloc β†’ CreateScheduleUseCase β†’ ScheduleRepository
                     ↓
ScheduleRemoteDataSource β†’ API

🎯 Key Features Architecture

1. Authentication System

  • Google OAuth and Kakao Login integration
  • JWT token management with secure storage
  • Stream-based user state management
  • Automatic token refresh via interceptors

2. Schedule Management

  • CRUD operations for schedules
  • Calendar integration with multiple view modes
  • Preparation time calculation and management
  • In-memory schedule stream updates after remote reads and writes
  • Runtime preparation flow with official timer starts, early-start entry, and finish/lateness handling
  • Cache-coherent timed-preparation resume using snapshot metadata and fingerprint invalidation
  • Automatic timer system for schedule start notifications

πŸ“– Detailed Documentation: For the canonical v2 state machine, sequence flows, cache coherence model, and verification matrix, see Schedule Timer & Preparation Runtime Flow (v2)

3. Notification System

  • Firebase push notifications for schedule reminders
  • Local notifications for preparation alerts
  • Permission handling for notification access

4. Local Runtime Persistence

  • Local persistence for runtime state such as timed-preparation snapshots, early-start sessions, and alarm registry records
  • Remote-only schedule persistence for schedule CRUD/read operations
  • In-memory schedule streams for loaded schedule ranges; no offline schedule CRUD/cache contract is currently implemented

5. Error Handling System

  • Result pattern for explicit, type-safe error handling
  • Structured failure hierarchy across all layers (Core, Domain, Data)
  • Automatic logging to Firebase Crashlytics in production
  • Environment-aware messaging: detailed errors in debug, user-friendly messages in production
  • Layer-appropriate failures: Domain failures contain no infrastructure details

πŸ“– Detailed Documentation: For comprehensive information about the error handling system, see Error Handling System

6. Local Storage for Timed Preparation

  • PreparationWithTimeLocalDataSource persists PreparationWithTimeEntity per schedule using SharedPreferences.
  • Intended for lightweight, per-schedule timer state (elapsed time, completion) that should survive app restarts.
  • Repository reads canonical schedule/preparation data from the remote API; BLoC can merge it with locally persisted timing state when needed.

πŸ§ͺ Testing Strategy

Structure

test/
β”œβ”€β”€ config/              # Test configuration
β”œβ”€β”€ data/               # Data layer tests
└── helpers/            # Test utilities

Testing Approach

  • Unit Tests: Use cases, repositories, and business logic
  • Widget Tests: UI components and screen interactions
  • Integration Tests: End-to-end user flows
  • Mocking: Using Mockito for external dependencies

πŸ“¦ Build & Deployment

Development Environment

  • Flutter SDK: ^3.5.4
  • Dart SDK: Latest stable
  • Build Tools: build_runner for code generation

Code Generation Commands

# Generate all code (models, dependency injection, etc.)
dart run build_runner build

# Watch for changes and regenerate
dart run build_runner watch

Platform Support

  • Android: Native Android build
  • iOS: Native iOS build
  • Web: Progressive Web App support

πŸ”§ Development Guidelines

1. Code Organization

  • Follow Clean Architecture principles
  • Separate concerns across layers
  • Use feature-based folder structure in presentation layer

2. State Management

  • Use BLoC pattern for complex state management
  • Use Cubit for simpler state scenarios
  • Keep business logic in use cases, not in BLoCs

3. Data Handling

  • Always use entities in the domain layer
  • Convert models to entities at repository boundaries
  • Implement proper error handling throughout the layers
  • Use Result pattern for all operations that can fail

πŸ“– Detailed Documentation: For comprehensive information about error handling, see Error Handling System

4. Naming Conventions

  • Entities: UserEntity, ScheduleEntity
  • Use Cases: GetUserUseCase, CreateScheduleUseCase
  • Repositories: UserRepository, ScheduleRepository
  • BLoCs: UserBloc, ScheduleFormBloc
  • Models: GetUserResponseModel, CreateScheduleRequestModel

5. Dependencies

  • Register all dependencies using @Injectable() annotation
  • Use interfaces for repository contracts
  • Avoid direct dependencies between layers

πŸš€ Getting Started for New Developers

  1. Setup Environment

    • Install Flutter SDK
    • Configure IDE (VS Code/Android Studio)
    • Run flutter pub get to install dependencies
  2. Code Generation

    • Run dart run build_runner build
    • This generates dependency injection, JSON serialization, and Freezed code
  3. Database Setup

    • Database migrations are handled automatically
    • Local database files are created on first run
  4. Understanding the Flow

    • Start with main.dart to understand app initialization
    • Explore presentation/app/ for global app state
    • Check domain/use-cases/ for business logic
    • Review data/repositories/ for data access patterns
  5. Making Changes

    • Create new features following the existing layer structure
    • Add new entities in domain/entities/
    • Implement use cases in domain/use-cases/
    • Create repository interfaces and implementations
    • Build UI components in presentation/

This architecture documentation is maintained alongside the codebase. Please update it when making significant architectural changes.