Skip to content

ZsoltFischer/Flutter-Stopwatch

Repository files navigation

Stopwatch

coverage style: very good analysis License: MIT

Flutter Stopwatch App

A stopwatch application built with Flutter, following clean architecture principles. This project demonstrates state management using the BLoC library, testing, and modular design for scalable Flutter apps.

The project template was generated with very_good_cli (v0.27.0) and was developed on Flutter 3.35.3.

Features

  • Stopwatch Functionality: Start, pause, stop, and record laps with millisecond precision.
  • Multiple Clock Displays: Digital and analog clock widgets for flexible UI.
  • State Management: Bloc pattern.
  • Clean Architecture: Separation of data, domain, and presentation layers.
  • Testing:
    • Unit, widget, and integration tests
    • Custom robots and fakes for UI and business logic coverage
  • Platform Support: Android, iOS, Web, macOS, Windows

The packages/ directory contains shared Flutter package(s) for modularity and code reuse. Each package is intended to be reused across multiple apps inside an organization - either in a monorepo setup like in this project - or published separately for easy dependency handling.

  • utils/: Common utilities, constants, extensions, and error handling used across multiple apps and features.

⚠️ Missing Features / Roadmap

  • Persistence (Planned): The architecture is prepared for future support of persistent stopwatch state, enabling the stopwatch to continue running in the background and survive app restarts.

    ⚠️ This feature is not yet implemented. The codebase is structured for easy extension to background and persistent operation, but persistence is currently missing.

Project Structure

  • The project follows a feature-first clean architecture style
lib/
    app/                # App bootstrap, theming, navigation
    exceptions/         # Error handling
    features/
        stopwatch/        # Stopwatch feature
            data/           # Data sources, models, repositories
            domain/         # Entities, repositories, services, use cases
            presentation/   # Bloc, widgets, pages
    routing/            # Routing configuration
    l10n/               # Localization files

integration_test/     # End-to-end and workflow tests
    app_robot.dart      # Robot for UI automation
    app_test.dart       # Main integration test
    workflows.dart      # Complex workflow coverage

test/                 # Unit and widget tests
    feature/            # Feature-specific tests
    helpers/            # Test helpers, fakes, robots


packages/
    utils/              # Common utilities, extensions, error handling. 

Getting Started

  1. Clone the repository
    git clone https://github.com/ZsoltFischer/Flutter-Stopwatch.git
    cd Flutter-Stopwatch
  2. Install dependencies
    flutter pub get
  3. Run the app This project contains 3 flavors:
  • development
  • staging
  • production

To run the desired flavor either use the launch configuratiions in VSCode or run the appropriate command:

# Development
$ flutter run --flavor development --target lib/main_development.dart

# Staging
$ flutter run --flavor staging --target lib/main_staging.dart

# Production
$ flutter run --flavor production --target lib/main_production.dart
  1. Run tests Unit/Widget tests:
$ flutter test

or

$ very_good test --coverage --test-randomize-ordering-seed random

Integration tests (requires emulator/device):

$ flutter test integration_test --flavor <flavor> integration_test/app_test.dart

To view the generated coverage report you can use lcov.

# Generate Coverage Report
$ genhtml coverage/lcov.info -o coverage/

# Open Coverage Report
$ open coverage/index.html

Testing Approach

  • Unit Tests: Validate business logic and state transitions.
  • Widget Tests: Verify UI rendering and interaction in test/feature/stopwatch/presentation/widgets/.
  • Integration Tests: Use integration_test/app_robot.dart for complex workflows and end-to-end scenarios.
  • ⚠️ Golden Tests: On the roadmap. Verify individual components like the analog clock face
  • Test Helpers: Custom fakes, robots, and pump helpers for maintainable tests.

Architecture

  • Feature-first -- Data Layer: Handles data sources, models, and repository implementations. -- Domain Layer: Contains entities, repository interfaces, services, and use cases. -- Presentation Layer: Manages UI, Bloc state, and widget composition.

Working with Translations

This project relies on flutter_localizations and follows the official internationalization guide for Flutter.

Adding Strings

  1. To add a new localizable string, open the app_en.arb file at lib/l10n/arb/app_en.arb.
{
    "@@locale": "en",
    "counterAppBarTitle": "Counter",
    "@counterAppBarTitle": {
        "description": "Text shown in the AppBar of the Counter Page"
    }
}
  1. Then add a new key/value and description
{
    "@@locale": "en",
    "counterAppBarTitle": "Counter",
    "@counterAppBarTitle": {
        "description": "Text shown in the AppBar of the Counter Page"
    },
    "helloWorld": "Hello World",
    "@helloWorld": {
        "description": "Hello World Text"
    }
}
  1. Use the new string
import 'package:stopwatch/l10n/l10n.dart';

@override
Widget build(BuildContext context) {
  final l10n = context.l10n;
  return Text(l10n.helloWorld);
}

Adding Supported Locales

Update the CFBundleLocalizations array in the Info.plist at ios/Runner/Info.plist to include the new locale.

    ...

    <key>CFBundleLocalizations</key>
	<array>
		<string>en</string>
		<string>es</string>
	</array>

    ...

Adding Translations

  1. For each supported locale, add a new ARB file in lib/l10n/arb.
├── l10n
│   ├── arb
│   │   ├── app_en.arb
│   │   └── app_es.arb
  1. Add the translated strings to each .arb file:

app_en.arb

{
    "@@locale": "en",
    "counterAppBarTitle": "Counter",
    "@counterAppBarTitle": {
        "description": "Text shown in the AppBar of the Counter Page"
    }
}

app_es.arb

{
    "@@locale": "es",
    "counterAppBarTitle": "Contador",
    "@counterAppBarTitle": {
        "description": "Texto mostrado en la AppBar de la página del contador"
    }
}

Generating Translations

To use the latest translations changes, you will need to generate them:

  1. Generate localizations for the current project:
flutter gen-l10n --arb-dir="lib/l10n/arb"

Alternatively, run flutter run and code generation will take place automatically.

Author


For more details, see the source code and tests in the repository.


About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published