ChokQu Fusion 🚀

A powerful, opinionated MVVM framework for Flutter with elegant architecture and developer-friendly tools.

CI/CD License Flutter Dart

Features

🎯 MVVM Architecture - Clean separation of concerns with ViewModel-based architecture 📱 Reactive Programming - Built-in reactive values with RxValue<T> 🔧 Dependency Injection - Powered by get_it and injectable 🎨 Smart Widgets - Intelligent UI components that handle state automatically 📦 Provider Integration - Seamless integration with Flutter's Provider package 🚀 Developer Experience - Rich extensions and utilities for faster development

Quick Start

1. Add to pubspec.yaml

dependencies:
  chokqu_fusion: ^1.0.0-dev.1

2. Set up dependency injection

// main.dart
import 'package:flutter/material.dart';
import 'package:chokqu_fusion/chokqu_fusion.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await configureDependencies();
  runApp(MyApp());
}

3. Create a ViewModel

import 'package:chokqu_fusion/chokqu_fusion.dart';

@injectable
class CounterViewModel extends FusionViewModel {
  final _counter = RxValue<int>(0);
  int get counter => _counter.value;

  @override
  Future<void> onReady() async {
    // Initialize data here
  }

  void increment() {
    _counter.value++;
  }

  void decrement() {
    _counter.value--;
  }
}

4. Create a View

import 'package:flutter/material.dart';
import 'package:chokqu_fusion/chokqu_fusion.dart';

class CounterView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter')),
      body: FusionView<CounterViewModel>(
        builder: (context, vm, child) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Count: ${vm.counter}',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
                SizedBox(height: 20),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    ElevatedButton(
                      onPressed: vm.decrement,
                      child: Icon(Icons.remove),
                    ),
                    SizedBox(width: 20),
                    ElevatedButton(
                      onPressed: vm.increment,
                      child: Icon(Icons.add),
                    ),
                  ],
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

5. Use Smart State Management

class UserListView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Users')),
      body: FusionStateView<UserViewModel>(
        contentBuilder: (context, vm) {
          return ListView.builder(
            itemCount: vm.users.length,
            itemBuilder: (context, index) {
              final user = vm.users[index];
              return ListTile(
                title: Text(user.name),
                subtitle: Text(user.email),
              );
            },
          );
        },
      ),
    );
  }
}

Key Concepts

ViewModels

ViewModels are the heart of the Fusion framework. They extend FusionViewModel and provide:

  • Lifecycle Management: onInit(), onDependenciesReady(), onReady(), onClose()
  • State Management: Built-in ViewState enum (idle, busy, error, success, empty)
  • Reactive Values: Use RxValue<T> for reactive programming
  • Error Handling: Automatic error state management

Smart Views

Fusion provides intelligent widgets that handle common UI patterns:

  • FusionView<T>: Basic ViewModel provider and consumer
  • FusionStateView<T>: Automatically handles different view states
  • Context Extensions: Easy ViewModel access with context.vm<T>() and context.watch<T>()

Reactive Programming

Use RxValue<T> for reactive variables in your ViewModels:

class MyViewModel extends FusionViewModel {
  final _name = RxValue<String>('');
  String get name => _name.value;

  final _users = RxValue<List<User>>([]);
  List<User> get users => _users.value;

  void updateName(String newName) {
    _name.value = newName;
  }
}

Dependency Injection

Fusion uses get_it and injectable for dependency injection:

@injectable
class ApiService {
  Future<List<User>> getUsers() async {
    // API implementation
  }
}

@injectable
class UserViewModel extends FusionViewModel {
  final ApiService _apiService;
  
  UserViewModel(this._apiService);
  
  Future<void> loadUsers() async {
    final users = await runBusyFuture(
      _apiService.getUsers(),
      busyMessage: 'Loading users...',
    );
    if (users != null) {
      _users.value = users;
    }
  }
}

Documentation

For detailed documentation and advanced usage, please visit our documentation site.

Community

Contributing

We welcome contributions! Please read our contributing guide for details.

Author

License

This project is licensed under the MIT License - see the LICENSE file for details.