layerman 0.2.0 copy "layerman: ^0.2.0" to clipboard
layerman: ^0.2.0 copied to clipboard

Headless overlay queue orchestrator: serial one-at-a-time queueing with priority, replace, overlap, conditions, cooldown and two-phase close; renders through any UI backend (showDialog / GetX / bot_to [...]

example/lib/main.dart

import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:layerman/layerman.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'demo_shell.dart';
import 'manager.dart';

// Re-export manager/helper symbols so integration tests can use `app.om` and
// `app.openCard(...)` via
// `import 'package:layerman_example/main.dart' as app; app.om.resumeAll()`.
export 'manager.dart' show om, restartApp, createFreshManager;
export 'helpers.dart' show openCard;

final GlobalKey<_AppRootState> _appRootKey = GlobalKey<_AppRootState>();

void main() {
  om.setContext({'route': '/home'});
  runApp(AppRoot(key: _appRootKey));
}

class AppRoot extends StatefulWidget {
  const AppRoot({super.key});

  @override
  State<AppRoot> createState() => _AppRootState();
}

class _AppRootState extends State<AppRoot> {
  int _gen = 0;

  @override
  void initState() {
    super.initState();
    registerRestartCallback(_doRestart);
  }

  void _doRestart() {
    // `dispose()` synchronously pops any still-open dialog routes on the
    // CURRENT navigator (via each entry's `present`-backend dismiss) --
    // Navigator route removal schedules its own deferred focus-update
    // microtask. Doing that INSIDE the same `setState` that also swaps
    // DemoShell's key (below) raced that microtask against the very same
    // frame tearing down the old subtree, throwing "FocusManager used after
    // being disposed". Running it as a plain statement BEFORE `setState`
    // lets that microtask settle against the still-fully-mounted old tree,
    // and only then does `setState` remount with the fresh generation.
    om.dispose();
    final fresh = createFreshManager();
    fresh.setContext({'route': '/home'});
    setState(() {
      om = fresh;
      _gen++;
    });
  }

  @override
  Widget build(BuildContext context) {
    final botToastBuilder = BotToastInit();
    return GetMaterialApp(
      title: 'layerman demo',
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
      ),
      // LayermanNavigatorObserver feeds every push/pop into om.setContext
      // automatically. BotToastNavigatorObserver maintains bot_toast's layer.
      navigatorObservers: [
        BotToastNavigatorObserver(),
        LayermanNavigatorObserver(om),
      ],
      // Layer order (top → bottom):
      //   bot_toast  >  ShadSonner toasts  >  routes
      //
      // The manager is headless now — it renders nothing itself, so there is
      // no scope/overlay layer to mount for it. `om` (see manager.dart) is a
      // plain object; every demo page presents through a real backend
      // (showDialog/Get.dialog/bot_toast/ShadSonner) that the manager only
      // sequences.
      //
      // ShadTheme must be an ancestor of all shadcn/ui widgets (ShadButton,
      // ShadDialog, ShadSheet) rendered inside present callbacks and dialogs.
      // ShadSonner is keyed so present-callbacks can reach it without context.
      builder: (context, child) => botToastBuilder(
        context,
        ShadTheme(
          data: ShadThemeData(colorScheme: const ShadSlateColorScheme.light()),
          child: ShadSonner(
            key: shadSonnerKey,
            child: child!,
          ),
        ),
      ),
      // Use initialRoute + routes so the home page has name '/home'
      // (not '/' which is Flutter's implicit defaultRouteName for home:).
      initialRoute: '/home',
      routes: {'/home': (_) => DemoShell(key: ValueKey(_gen))},
    );
  }
}
0
likes
150
points
358
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Headless overlay queue orchestrator: serial one-at-a-time queueing with priority, replace, overlap, conditions, cooldown and two-phase close; renders through any UI backend (showDialog / GetX / bot_toast / your own).

Homepage
Repository (GitHub)
View/report issues

Topics

#overlay #dialog #toast #queue #snackbar

License

MIT (license)

Dependencies

flutter

More

Packages that depend on layerman