maintenance_manager

A lightweight, reusable Flutter package for handling remote maintenance mode with a default UI and custom overrides.

Features

  • 🌍 Remote Control: Enable/disable maintenance mode via remote JSON.
  • 📱 Default UI: Ready-to-use maintenance screen with customization limits.
  • 🎨 Customizable: Override default styles or provide your own complete UI builder.
  • 🛡️ Fail-Safe: Configurable fallback behavior if the remote source is unreachable.
  • 🚦 Version Management: Whitelist specific app versions to bypass maintenance.

Getting Started

Add the dependency to your pubspec.yaml:

dependencies:
  maintenance_manager: ^0.0.1

Or run:

flutter pub add maintenance_manager

Usage

The recommended way to use MaintenanceMode is inside the builder property of your MaterialApp (or CupertinoApp). This ensures that the maintenance screen has access to the correct Theme and Directionality settings.

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      builder: (context, child) {
        return MaintenanceMode(
          config: MaintenanceConfig(
            // URL to your JSON configuration
            source: MaintenanceHttpSource(maintenanceUrl: Uri.parse("https://api.example.com/maintenance_config")),
            
            // If the server is down, should we block access (true) or allow (false)?
            fallbackAllow: true, 
            
            // Optional: Bypass logic (e.g. for beta testers)
            versionException: (version) => version.contains("beta"),
          ),
          
          // Optional: Style the default screen
          defaultTitle: "Under Maintenance",
          defaultTitleStyle: TextStyle(color: Colors.red, fontSize: 30),
          
          child: child!,
        );
      },
      home: const MyHomePage(),
    );
  }
}

Flexible Data Sources

This package supports any data source by implementing the MaintenanceDataSource interface.

1. HTTP JSON (Default)

Use the built-in MaintenanceHttpSource to fetch from a URL.

config: MaintenanceConfig(
  source: MaintenanceHttpSource(maintenanceUrl: Uri.parse("...")),
  // ...
),

2. Firebase Remote Config

To use Firebase, implement a custom source in your app (no need to add heavy dependencies to this package).

class FirebaseMaintenanceSource implements MaintenanceDataSource {
  final FirebaseRemoteConfig remoteConfig; // Your instance

  FirebaseMaintenanceSource(this.remoteConfig);

  @override
  Future<MaintenanceModel> fetchMaintenanceStatus() async {
    // 1. Fetch
    await remoteConfig.fetchAndActivate();

    // 2. Parse (using your keys)
    return MaintenanceModel(
      isMaintained: remoteConfig.getBool('is_maintenance'),
      message: remoteConfig.getString('maintenance_message'),
      allowedVersions: _parseList(remoteConfig.getString('allowed_versions')), // Custom parsing logic
    );
  }
}

Then pass it to the widget:

config: MaintenanceConfig(
  source: FirebaseMaintenanceSource(FirebaseRemoteConfig.instance),
  //...
),

Remote JSON Schema (HTTP Source)

If you use MaintenanceHttpSource, your backend should return:

{
  "maintenance": true,
  "message": "We are upgrading our servers. Please try again in 15 minutes.",
  "start_time": "2024-01-01T10:00:00Z",
  "end_time": "2024-01-01T12:00:00Z",
  "allowed_versions": ["1.2.0", "1.2.1"]
}
  • maintenance (bool): true blocks access, false allows access.
  • message (string): The message to display to the user.
  • start_time (string, optional): ISO8601 date string. Maintenance will automatically start at this time even if maintenance is false.
  • end_time (string, optional): ISO8601 date string. Maintenance screen will show "Estimated back at" with this time.
  • allowed_versions (array

FAQ

Q: What if the backend is down? A: You can configure fallbackAllow in MaintenanceConfig. If true (default), the app opens normally. If false, it shows a default "Service Unavailable" screen.

Q: Does this block navigation? A: Yes, MaintenanceMode sits at the top of the widget tree (above MaterialApp usually), so it replaces the entire view when active.

License

MIT