maintenance_manager 0.0.1 copy "maintenance_manager: ^0.0.1" to clipboard
maintenance_manager: ^0.0.1 copied to clipboard

A lightweight, flexible Flutter package for handling remote maintenance mode with built-in UI, custom overrides, and version-based bypass.

example/lib/main.dart

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

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

/// A simple mock source to demonstrate functionality without a real server.
class ExampleMaintenanceSource implements MaintenanceDataSource {
  final bool isMaintained;

  ExampleMaintenanceSource({required this.isMaintained});

  @override
  Future<MaintenanceModel> fetchMaintenanceStatus() async {
    // Simulate network delay
    await Future.delayed(const Duration(seconds: 2));

    return MaintenanceModel(
      isMaintained: isMaintained,
      message:
          "Our team is currently performing scheduled maintenance to improve your experience. We are building the future of AI infrastructure and will return shortly",
      allowedVersions: ["1.2.0"], // Example of a version that is allowed
    );
  }
}

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

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

class _MyAppState extends State<MyApp> {
  // Toggle this to test different states
  bool _mockMaintenanceActive = false;
  bool _useCustomUI = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Maintenance Manager Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.blue),
      builder: (context, child) {
        return MaintenanceMode(
          config: MaintenanceConfig(
            // Use our local mock source
            source: ExampleMaintenanceSource(
              isMaintained: _mockMaintenanceActive,
            ),
            fallbackAllow: true,
            versionException: (version) => version.contains("beta"),
          ),

          // --- Custom Builder Example ---
          // This allows complete control over the layout.
          customBuilder: _useCustomUI
              ? (context, model) {
                  return Scaffold(
                    body: Container(
                      width: double.infinity,
                      decoration: const BoxDecoration(
                        gradient: LinearGradient(
                          colors: [Color(0xFF2C3E50), Color(0xFF000000)],
                          begin: Alignment.topCenter,
                          end: Alignment.bottomCenter,
                        ),
                      ),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          const Icon(
                            Icons.warning_amber_rounded,
                            size: 100,
                            color: Colors.amber,
                          ),
                          const SizedBox(height: 24),
                          const Text(
                            "BRANDED MAINTENANCE",
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 24,
                              letterSpacing: 4,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                          const SizedBox(height: 16),
                          Container(
                            padding: const EdgeInsets.all(16),
                            margin: const EdgeInsets.symmetric(horizontal: 32),
                            decoration: BoxDecoration(
                              color: Colors.white.withValues(alpha: 0.1),
                              borderRadius: BorderRadius.circular(12),
                              border: Border.all(color: Colors.white24),
                            ),
                            child: Text(
                              model.message,
                              textAlign: TextAlign.center,
                              style: const TextStyle(color: Colors.white70),
                            ),
                          ),
                          const SizedBox(height: 40),
                          OutlinedButton(
                            onPressed: () {
                              // In a real app, you would re-trigger a check.
                              // Here we just modify state to let user back in if they toggled the flag.
                              setState(() {
                                // Just trigger a rebuild to re-check source
                              });
                            },
                            style: OutlinedButton.styleFrom(
                              foregroundColor: Colors.amber,
                              side: const BorderSide(color: Colors.amber),
                            ),
                            child: const Text("CHECK STATUS"),
                          ),
                        ],
                      ),
                    ),
                  );
                }
              : null,

          // --- Default Customization Example ---
          defaultTitle: "We'll Be Back Soon",
          defaultRetryLabel: "Refresh",
          onContact: () {
            // Logic to open mail or chat
            debugPrint("Contacting Support...");
          },
          // Mixed font weight can be achieved via RichText or custom builder,
          // but for the default we use the title style.
          defaultTitleStyle: const TextStyle(
            fontSize: 32,
            fontWeight: FontWeight.w900,
            color: Colors.black,
            letterSpacing: -1,
          ),

          child: child!,
        );
      },
      home: MyHomePage(
        title: 'Maintenance Manager Demo',
        onToggleMaintenance: () {
          setState(() {
            _mockMaintenanceActive = !_mockMaintenanceActive;
          });
        },
        onToggleCustomUI: () {
          setState(() {
            _useCustomUI = !_useCustomUI;
          });
        },
        isCustomUiEnabled: _useCustomUI,
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({
    super.key,
    required this.title,
    required this.onToggleMaintenance,
    required this.onToggleCustomUI,
    required this.isCustomUiEnabled,
  });

  final String title;
  final VoidCallback onToggleMaintenance;
  final VoidCallback onToggleCustomUI;
  final bool isCustomUiEnabled;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: [
          IconButton(
            icon: const Icon(Icons.settings),
            tooltip: 'Admin Settings',
            onPressed: () {
              showModalBottomSheet(
                context: context,
                builder: (ctx) => Container(
                  padding: const EdgeInsets.all(24),
                  width: double.infinity,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        "Admin Tools",
                        style: Theme.of(context).textTheme.headlineSmall,
                      ),
                      const SizedBox(height: 16),
                      ListTile(
                        leading: const Icon(
                          Icons.build_circle,
                          color: Colors.orange,
                        ),
                        title: const Text("Simulate Maintenance Mode"),
                        subtitle: const Text(
                          "Toggle the remote flag to true/false",
                        ),
                        onTap: () {
                          Navigator.pop(ctx);
                          widget.onToggleMaintenance();
                          ScaffoldMessenger.of(context).showSnackBar(
                            const SnackBar(
                              content: Text(
                                "Maintenance Flag Toggled! Restart or Rebuild might be required.",
                              ),
                              duration: Duration(seconds: 2),
                            ),
                          );
                        },
                      ),
                      SwitchListTile(
                        secondary: const Icon(
                          Icons.brush,
                          color: Colors.purple,
                        ),
                        title: const Text("Use Custom UI"),
                        subtitle: const Text(
                          "Switch between Default and Custom Builder",
                        ),
                        value: widget.isCustomUiEnabled,
                        onChanged: (val) {
                          Navigator.pop(ctx);
                          // This triggers a setState in MyAppState
                          widget.onToggleCustomUI();
                        },
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          // Banner
          Container(
            padding: const EdgeInsets.all(24),
            decoration: BoxDecoration(
              gradient: const LinearGradient(
                colors: [Colors.blue, Colors.lightBlueAccent],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
              borderRadius: BorderRadius.circular(16),
              boxShadow: [
                BoxShadow(
                  color: Colors.blue.withValues(alpha: 0.3),
                  blurRadius: 12,
                  offset: const Offset(0, 6),
                ),
              ],
            ),
            child: const Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  "Welcome Back!",
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 28,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                SizedBox(height: 8),
                Text(
                  "Everything is running smoothly.",
                  style: TextStyle(color: Colors.white70, fontSize: 16),
                ),
              ],
            ),
          ),
          const SizedBox(height: 24),

          Text(
            "Quick Actions",
            style: Theme.of(
              context,
            ).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 12),

          // Grid of Mock Items
          GridView.count(
            crossAxisCount: 2,
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            crossAxisSpacing: 16,
            mainAxisSpacing: 16,
            children: [
              _buildCard(Icons.analytics, "Analytics", Colors.purple),
              _buildCard(Icons.people, "Users", Colors.orange),
              _buildCard(Icons.shopping_bag, "Orders", Colors.green),
              _buildCard(Icons.message, "Messages", Colors.red),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildCard(IconData icon, String label, Color color) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withValues(alpha: 0.1),
            blurRadius: 8,
            offset: const Offset(0, 4),
          ),
        ],
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          CircleAvatar(
            backgroundColor: color.withValues(alpha: 0.1),
            radius: 30,
            child: Icon(icon, color: color, size: 30),
          ),
          const SizedBox(height: 12),
          Text(
            label,
            style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
          ),
        ],
      ),
    );
  }
}
1
likes
140
points
11
downloads

Documentation

API reference

Publisher

verified publishergreelogix.com

Weekly Downloads

A lightweight, flexible Flutter package for handling remote maintenance mode with built-in UI, custom overrides, and version-based bypass.

Repository (GitHub)
View/report issues

Topics

#maintenance #maintenance-mode #remote-config #utility

License

MIT (license)

Dependencies

flutter, http, package_info_plus

More

Packages that depend on maintenance_manager