quick_popup_manager 0.0.2 copy "quick_popup_manager: ^0.0.2" to clipboard
quick_popup_manager: ^0.0.2 copied to clipboard

Global popup system for Flutter without BuildContext.

example/lib/main.dart

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

void main() {
  runApp(const MyApp());
}

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

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

class _MyAppState extends State<MyApp> {
  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

  @override
  void initState() {
    super.initState();
    // Initialize after first frame
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_navigatorKey.currentState != null &&
          _navigatorKey.currentState!.overlay != null) {
        QuickPopupManager().initialize(_navigatorKey.currentState!.overlay!);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Quick Popup Manager Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      // IMPORTANT: Add the navigator observer to enable global popups
      navigatorObservers: [QuickPopupNavigatorObserver()],
      navigatorKey: _navigatorKey,
      builder: (context, child) {
        // Ensure initialization on every build (synchronously)
        final navigator = Navigator.maybeOf(context, rootNavigator: true);
        if (navigator != null && navigator.overlay != null) {
          QuickPopupManager().initialize(navigator.overlay!);
        }
        return child ?? const SizedBox();
      },
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Quick Popup Manager'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildSection(
            title: '🍞 Toast Notifications',
            description: 'No BuildContext needed!',
            children: [
              _buildButton(
                'Success Toast (Top)',
                Icons.check_circle,
                Colors.green,
                () => QuickPopupManager().showSuccessToast(
                  message: 'Operation completed successfully!',
                  title: 'Success',
                  position: PopupPosition.top,
                ),
              ),
              _buildButton(
                'Error Toast (Bottom)',
                Icons.error,
                Colors.red,
                () => QuickPopupManager().showErrorToast(
                  message: 'Something went wrong!',
                  title: 'Error',
                  position: PopupPosition.bottom,
                ),
              ),
              _buildButton(
                'Warning Toast (Center)',
                Icons.warning,
                Colors.orange,
                () => QuickPopupManager().showWarningToast(
                  message: 'Please check your input',
                  title: 'Warning',
                  position: PopupPosition.center,
                ),
              ),
              _buildButton(
                'Info Toast',
                Icons.info,
                Colors.blue,
                () => QuickPopupManager().showInfoToast(
                  message: 'New features available',
                  title: 'Info',
                ),
              ),
              _buildButton(
                'Custom Toast',
                Icons.star,
                Colors.purple,
                () => QuickPopupManager().showToast(
                  message: 'Custom styled toast!',
                  title: 'Custom',
                  icon: Icons.star,
                  position: PopupPosition.top,
                  style: PopupStyle(
                    backgroundColor: Colors.purple,
                    borderRadius: 20,
                    titleStyle: const TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                    messageStyle: const TextStyle(color: Colors.white),
                  ),
                  animation: const AnimationConfig.spring(),
                ),
              ),
            ],
          ),
          const SizedBox(height: 24),
          _buildSection(
            title: '🍔 Snackbars',
            description: 'Top/Bottom, Floating/Attached, Swipe to dismiss',
            children: [
              _buildButton(
                'Bottom Snackbar (Floating)',
                Icons.message,
                Colors.blue,
                () => QuickPopupManager().showSnackbar(
                  message: 'Item added to cart',
                  title: 'Success',
                  icon: Icons.shopping_cart,
                  position: SnackbarPosition.bottom,
                  behavior: SnackbarBehavior.floating,
                ),
              ),
              _buildButton(
                'Top Snackbar (Attached)',
                Icons.arrow_upward,
                Colors.teal,
                () => QuickPopupManager().showSnackbar(
                  message: 'Message sent',
                  title: 'Notification',
                  subtitle: 'Your message has been delivered',
                  icon: Icons.send,
                  position: SnackbarPosition.top,
                  behavior: SnackbarBehavior.attached,
                ),
              ),
              _buildButton(
                'Snackbar with Preset',
                Icons.palette,
                Colors.pink,
                () => QuickPopupManager().showSnackbar(
                  message: 'Profile updated',
                  title: 'Success',
                  icon: Icons.person,
                  style: PopupStyle.success(),
                  position: SnackbarPosition.bottom,
                ),
              ),
              _buildButton(
                'Replace Current Snackbar',
                Icons.swap_horiz,
                Colors.indigo,
                () {
                  QuickPopupManager().showSnackbar(
                    message: 'First snackbar',
                    position: SnackbarPosition.bottom,
                  );
                  Future.delayed(const Duration(milliseconds: 500), () {
                    QuickPopupManager().showSnackbar(
                      message: 'This replaced the previous one!',
                      replaceCurrent: true,
                      position: SnackbarPosition.bottom,
                    );
                  });
                },
              ),
            ],
          ),
          const SizedBox(height: 24),
          _buildSection(
            title: '🚩 Banners',
            description: 'Top/Bottom banners with auto-dismiss',
            children: [
              _buildButton(
                'Top Banner',
                Icons.flag,
                Colors.orange,
                () => QuickPopupManager().showBanner(
                  message: 'New update available!',
                  title: 'Update',
                  icon: Icons.system_update,
                  position: PopupPosition.top,
                  style: PopupStyle.info(),
                ),
              ),
              _buildButton(
                'Bottom Banner',
                Icons.arrow_downward,
                Colors.deepPurple,
                () => QuickPopupManager().showBanner(
                  message: 'Connection restored',
                  title: 'Network',
                  icon: Icons.wifi,
                  position: PopupPosition.bottom,
                  style: PopupStyle.success(),
                ),
              ),
              _buildButton(
                'Error Banner',
                Icons.error_outline,
                Colors.red,
                () => QuickPopupManager().showBanner(
                  message: 'Failed to sync data',
                  title: 'Sync Error',
                  icon: Icons.sync_problem,
                  position: PopupPosition.top,
                  style: PopupStyle.error(),
                  duration: const Duration(seconds: 4),
                ),
              ),
            ],
          ),
          const SizedBox(height: 24),
          _buildSection(
            title: '💬 Dialogs',
            description: 'Regular, Loading, Destructive',
            children: [
              _buildButton(
                'Simple Dialog',
                Icons.chat_bubble,
                Colors.blue,
                () => QuickPopupManager().showDialogPopup(
                  title: 'Confirm Action',
                  message: 'Are you sure you want to proceed?',
                  onConfirm: () {
                    QuickPopupManager().showSuccessToast(
                      message: 'Action confirmed!',
                    );
                  },
                  onCancel: () {
                    QuickPopupManager().showInfoToast(
                      message: 'Action cancelled',
                    );
                  },
                ),
              ),
              _buildButton(
                'Loading Dialog',
                Icons.hourglass_empty,
                Colors.amber,
                () async {
                  final loadingId = QuickPopupManager().showLoadingDialog(
                    message: 'Processing...',
                  );
                  // Simulate work
                  await Future.delayed(const Duration(seconds: 2));
                  QuickPopupManager().hideLoadingDialog(loadingId);
                  QuickPopupManager().showSuccessToast(
                    message: 'Processing complete!',
                  );
                },
              ),
              _buildButton(
                'Destructive Dialog',
                Icons.delete,
                Colors.red,
                () => QuickPopupManager().showDestructiveDialog(
                  title: 'Delete Item',
                  message: 'This action cannot be undone. Are you sure?',
                  onConfirm: () {
                    QuickPopupManager().showErrorToast(message: 'Item deleted');
                  },
                  confirmText: 'Delete',
                ),
              ),
              _buildButton(
                'Custom Dialog',
                Icons.tune,
                Colors.purple,
                () => QuickPopupManager().showDialogPopup(
                  title: 'Custom Dialog',
                  content: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const TextField(
                        decoration: InputDecoration(
                          labelText: 'Enter your name',
                          border: OutlineInputBorder(),
                        ),
                      ),
                      const SizedBox(height: 16),
                      const Text('This is custom content!'),
                    ],
                  ),
                  style: PopupStyle(
                    backgroundColor: Colors.white,
                    borderRadius: 16,
                  ),
                  onConfirm: () {
                    QuickPopupManager().showInfoToast(
                      message: 'Custom dialog confirmed',
                    );
                  },
                ),
              ),
              _buildButton(
                'Non-Dismissible Dialog',
                Icons.lock,
                Colors.grey,
                () => QuickPopupManager().showDialogPopup(
                  title: 'Important',
                  message: 'You cannot dismiss this by tapping outside',
                  barrierDismissible: false,
                  onConfirm: () {
                    QuickPopupManager().showInfoToast(message: 'Dialog closed');
                  },
                ),
              ),
            ],
          ),
          const SizedBox(height: 24),
          _buildSection(
            title: '📄 Bottom Sheets',
            description: 'Drag to dismiss, Custom heights, Keyboard-aware',
            children: [
              _buildButton(
                'Half Height Sheet',
                Icons.vertical_align_center,
                Colors.teal,
                () => QuickPopupManager().showBottomSheet(
                  title: 'Half Height Sheet',
                  message: 'This is a half-height bottom sheet',
                  height: 300,
                  onConfirm: () {
                    QuickPopupManager().showInfoToast(
                      message: 'Sheet confirmed',
                    );
                  },
                ),
              ),
              _buildButton(
                'Full Height Sheet',
                Icons.fullscreen,
                Colors.indigo,
                () => QuickPopupManager().showBottomSheet(
                  title: 'Full Height Sheet',
                  message: 'Drag down to dismiss',
                  isScrollControlled: true,
                  enableDrag: true,
                  content: ListView.builder(
                    itemCount: 20,
                    itemBuilder: (context, index) => ListTile(
                      title: Text('Item ${index + 1}'),
                      leading: const Icon(Icons.star),
                    ),
                  ),
                ),
              ),
              _buildButton('Selection Sheet', Icons.list, Colors.pink, () {
                final options = [
                  'Option A',
                  'Option B',
                  'Option C',
                  'Option D',
                ];
                int selectedIndex = 0;

                QuickPopupManager().showBottomSheet(
                  title: 'Choose an option',
                  content: StatefulBuilder(
                    builder: (context, setState) {
                      return Column(
                        mainAxisSize: MainAxisSize.min,
                        children: options.asMap().entries.map((entry) {
                          final index = entry.key;
                          final option = entry.value;
                          return RadioListTile<int>(
                            title: Text(option),
                            value: index,
                            groupValue: selectedIndex,
                            onChanged: (value) {
                              if (value != null) {
                                setState(() {
                                  selectedIndex = value;
                                });
                              }
                            },
                          );
                        }).toList(),
                      );
                    },
                  ),
                  onConfirm: () {
                    QuickPopupManager().showSuccessToast(
                      message: 'Selected: ${options[selectedIndex]}',
                    );
                  },
                );
              }),
              _buildButton(
                'Form Sheet',
                Icons.edit,
                Colors.blue,
                () => QuickPopupManager().showBottomSheet(
                  title: 'Enter Details',
                  content: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const TextField(
                        decoration: InputDecoration(
                          labelText: 'Name',
                          border: OutlineInputBorder(),
                        ),
                      ),
                      const SizedBox(height: 16),
                      const TextField(
                        decoration: InputDecoration(
                          labelText: 'Email',
                          border: OutlineInputBorder(),
                        ),
                      ),
                      const SizedBox(height: 16),
                      const TextField(
                        decoration: InputDecoration(
                          labelText: 'Phone',
                          border: OutlineInputBorder(),
                        ),
                      ),
                    ],
                  ),
                  isScrollControlled: true,
                  onConfirm: () {
                    QuickPopupManager().showSuccessToast(
                      message: 'Form submitted!',
                    );
                  },
                ),
              ),
            ],
          ),
          const SizedBox(height: 24),
          _buildSection(
            title: '🎨 Animation Examples',
            description: 'Different animation styles',
            children: [
              _buildButton(
                'Fade Animation',
                Icons.visibility,
                Colors.cyan,
                () => QuickPopupManager().showToast(
                  message: 'Fade animation',
                  animation: const AnimationConfig.fade(),
                ),
              ),
              _buildButton(
                'Slide from Top',
                Icons.arrow_downward,
                Colors.blue,
                () => QuickPopupManager().showToast(
                  message: 'Slides from top',
                  position: PopupPosition.top,
                  animation: const AnimationConfig.slideFromTop(),
                ),
              ),
              _buildButton(
                'Scale Animation',
                Icons.zoom_in,
                Colors.purple,
                () => QuickPopupManager().showDialogPopup(
                  title: 'Scale Dialog',
                  message: 'This dialog uses scale animation',
                  animation: const AnimationConfig.scale(),
                ),
              ),
              _buildButton(
                'Spring Animation',
                Icons.animation,
                Colors.orange,
                () => QuickPopupManager().showToast(
                  message: 'Spring animation!',
                  animation: const AnimationConfig.spring(),
                ),
              ),
            ],
          ),
          const SizedBox(height: 24),
          _buildSection(
            title: '🎯 Preset Styles',
            description: 'Success, Error, Warning, Info with themes',
            children: [
              _buildButton(
                'Success Preset',
                Icons.check_circle,
                Colors.green,
                () => QuickPopupManager().showSnackbar(
                  message: 'Operation successful',
                  style: PopupStyle.success(),
                ),
              ),
              _buildButton(
                'Error Preset',
                Icons.error,
                Colors.red,
                () => QuickPopupManager().showSnackbar(
                  message: 'An error occurred',
                  style: PopupStyle.error(),
                ),
              ),
              _buildButton(
                'Warning Preset',
                Icons.warning,
                Colors.orange,
                () => QuickPopupManager().showSnackbar(
                  message: 'Please be careful',
                  style: PopupStyle.warning(),
                ),
              ),
              _buildButton(
                'Info Preset',
                Icons.info,
                Colors.blue,
                () => QuickPopupManager().showSnackbar(
                  message: 'Here is some information',
                  style: PopupStyle.info(),
                ),
              ),
            ],
          ),
          const SizedBox(height: 32),
          Center(
            child: Text(
              'All popups work without BuildContext!',
              style: Theme.of(context).textTheme.bodySmall?.copyWith(
                fontStyle: FontStyle.italic,
                color: Colors.grey,
              ),
            ),
          ),
          const SizedBox(height: 16),
        ],
      ),
    );
  }

  Widget _buildSection({
    required String title,
    required String description,
    required List<Widget> children,
  }) {
    return Card(
      elevation: 2,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 4),
            Text(
              description,
              style: TextStyle(fontSize: 12, color: Colors.grey[600]),
            ),
            const SizedBox(height: 16),
            ...children,
          ],
        ),
      ),
    );
  }

  Widget _buildButton(
    String label,
    IconData icon,
    Color color,
    VoidCallback onPressed,
  ) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8),
      child: ElevatedButton.icon(
        onPressed: onPressed,
        icon: Icon(icon),
        label: Text(label),
        style: ElevatedButton.styleFrom(
          backgroundColor: color,
          foregroundColor: Colors.white,
          minimumSize: const Size(double.infinity, 48),
        ),
      ),
    );
  }
}
5
likes
155
points
150
downloads

Publisher

verified publishergreelogix.com

Weekly Downloads

Global popup system for Flutter without BuildContext.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on quick_popup_manager