juice 1.1.1 copy "juice: ^1.1.1" to clipboard
juice: ^1.1.1 copied to clipboard

Juice is an opinionated, team-friendly, modular reactive state management framework for Flutter. It enforces clear boundaries and structured development, combining Clean Architecture-style use cases w [...]

example/lib/main.dart

import 'package:juice/juice.dart';

import 'blocs/auth/ui/auth_page.dart';
import 'blocs/file_upload/src/ui/file_upload_page.dart';
import 'blocs/chat/ui/chat_page.dart';
import 'blocs/counter/ui/counter_page.dart';
import 'blocs/counter/ui/counter_builder_page.dart';
import 'blocs/form/ui/form_page.dart';
import 'blocs/relay_demo/ui/relay_demo_page.dart';
import 'blocs/todo/ui/todo_page.dart';
import 'blocs/weather/ui/weather_page.dart';
import 'blocs/blocs.dart';
import 'config/bloc_registration.dart';

// Example routes definition
final exampleRoutes = {
  '/auth': (context) => const AuthPage(),
  '/counter': (context) => const CounterPage(),
  '/counter-builder': (context) => const CounterBuilderPage(),
  '/todo': (context) => const TodoPage(),
  '/chat': (context) => const ChatPage(),
  '/form': (context) => const FormPage(),
  '/relay-demo': (context) => const RelayDemoPage(),
  '/weather': (context) => const WeatherPage(),
  '/upload': (context) => const FileUploadPage(),
  '/onboard': (context) => OnboardingScreen(),
};

void main() {
  // Initialize bloc registrations with lifecycle management
  BlocRegistry.initialize(ExampleDeepLinkConfig.config);

  // Get initial deep link if any
  final args = Uri.base.queryParameters;
  final initialExample = args['example'];

  runApp(MyApp(initialExample: initialExample));
}

class MyApp extends StatefulWidget {
  final String? initialExample;

  const MyApp({super.key, this.initialExample});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();

    // Handle initial deep link after first frame
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (widget.initialExample != null) {
        // Use BlocScope.get for permanent blocs
        final appBloc = BlocScope.get<AppBloc>();
        appBloc.send(UpdateEvent(
          aviatorName: 'deepLink',
          aviatorArgs: {'deepLink': widget.initialExample},
        ));
      }
    });
  }

  @override
  void dispose() {
    // Clean up all blocs on app shutdown
    BlocScope.endAll();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: BlocScope.get<AppBloc>().navigatorKey,
      title: 'Juice Examples',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      // Handle both initial route and deep links
      initialRoute: '/',
      onGenerateRoute: (settings) {
        if (settings.name == '/') {
          return MaterialPageRoute(
            builder: (context) => const MyHomePage(title: 'Juice Examples'),
          );
        }

        // Find matching example route
        final builder = exampleRoutes[settings.name];
        if (builder != null) {
          return MaterialPageRoute(
            builder: (context) => builder(context),
          );
        }

        // Handle unknown routes
        return MaterialPageRoute(
          builder: (context) => const MyHomePage(title: 'Juice Examples'),
        );
      },
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  Widget build(BuildContext context) {
    final examples = [
      {'title': 'Auth & EventSubscription', 'route': '/auth'},
      {'title': 'Counter Example', 'route': '/counter'},
      {'title': 'Counter (Builder Pattern)', 'route': '/counter-builder'},
      {'title': 'StateRelay & StatusRelay Demo', 'route': '/relay-demo'},
      {'title': 'Todo Example', 'route': '/todo'},
      {'title': 'Chat Example', 'route': '/chat'},
      {'title': 'Form Example', 'route': '/form'},
      {'title': 'Weather Example', 'route': '/weather'},
      {'title': 'File Upload', 'route': '/upload'},
      {'title': 'Onboard example', 'route': '/onboard'},
    ];

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView.builder(
        itemCount: examples.length,
        itemBuilder: (context, index) {
          final example = examples[index];
          return ListTile(
            title: Text(example['title'] as String),
            trailing: const Icon(Icons.arrow_forward),
            onTap: () {
              Navigator.pushNamed(context, example['route'] as String);
            },
          );
        },
      ),
    );
  }
}

// Add DeepLinkAviator configuration
class ExampleDeepLinkConfig {
  static final config = DeepLinkConfig(
    authRoute: '/', // No auth needed for examples
    routes: {
      'auth': DeepLinkRoute(path: ['/auth']),
      'counter': DeepLinkRoute(path: ['/counter']),
      'relay-demo': DeepLinkRoute(path: ['/relay-demo']),
      'todo': DeepLinkRoute(path: ['/todo']),
      'chat': DeepLinkRoute(path: ['/chat']),
      'form': DeepLinkRoute(path: ['/form']),
      'weather': DeepLinkRoute(path: ['/weather']),
      'upload': DeepLinkRoute(path: ['/upload']),
      'onboard': DeepLinkRoute(path: ['/onboard']),
    },
  );
}
6
likes
130
points
13
downloads

Publisher

verified publishernuovea.com

Weekly Downloads

Juice is an opinionated, team-friendly, modular reactive state management framework for Flutter. It enforces clear boundaries and structured development, combining Clean Architecture-style use cases with a BLoC-inspired, stream-driven state model for predictable async workflows and scalable feature composition.

Homepage
Repository (GitHub)
View/report issues
Contributing

Topics

#bloc #reactive #clean-architecture #state-management

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

cupertino_icons, flutter, flutter_test, logger, rxdart

More

Packages that depend on juice