create static method

AutoUpdaterStandaloneUI create({
  1. Color primaryColor = Colors.blue,
  2. AutoUpdaterStrings strings = const AutoUpdaterStrings(),
  3. GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey,
  4. GlobalKey<NavigatorState>? navigatorKey,
})

Creates a default UI configuration using Flutter's built-in widgets.

primaryColor - Color for buttons and progress indicators strings - Custom strings for localization scaffoldMessengerKey - GlobalKey for showing snackbars (optional) navigatorKey - GlobalKey for showing dialogs (optional)

Implementation

static AutoUpdaterStandaloneUI create({
  Color primaryColor = Colors.blue,
  AutoUpdaterStrings strings = const AutoUpdaterStrings(),
  GlobalKey<ScaffoldMessengerState>? scaffoldMessengerKey,
  GlobalKey<NavigatorState>? navigatorKey,
}) {
  void showSnackBar(BuildContext? context, String message, Color bgColor) {
    if (scaffoldMessengerKey?.currentState != null) {
      scaffoldMessengerKey!.currentState!.showSnackBar(
        SnackBar(
          content: Text(message),
          backgroundColor: bgColor,
        ),
      );
    } else if (context != null) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(message),
          backgroundColor: bgColor,
        ),
      );
    }
  }

  Future<T?> showDialogHelper<T>(
    BuildContext? context,
    Widget Function(BuildContext) builder,
  ) {
    if (navigatorKey?.currentState != null) {
      return showDialog<T>(
        context: navigatorKey!.currentState!.context,
        builder: builder,
      );
    } else if (context != null) {
      return showDialog<T>(context: context, builder: builder);
    }
    return Future.value(null);
  }

  return AutoUpdaterStandaloneUI(
    onShowDisabledMessage: (context) {
      showSnackBar(context, strings.updatesDisabled, Colors.orange);
    },

    onShowNoUpdateMessage: (context) {
      showSnackBar(context, strings.noUpdateAvailable, Colors.green);
    },

    onShowError: (context, title, message) {
      showSnackBar(context, '$title: $message', Colors.red);
    },

    onShowUpdateAvailable: (context, info, onDownload) {
      showDialogHelper(
        context,
        (ctx) => AlertDialog(
          title: Text(strings.updateAvailable),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('${strings.version} ${info.displayVersion}'),
              if (info.releaseNotes != null) ...[
                const SizedBox(height: 16),
                Text(strings.releaseNotes, style: const TextStyle(fontWeight: FontWeight.bold)),
                const SizedBox(height: 8),
                Text(info.releaseNotes!, style: const TextStyle(fontSize: 12)),
              ],
            ],
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(ctx).pop(),
              child: Text(strings.later),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.of(ctx).pop();
                onDownload();
              },
              style: ElevatedButton.styleFrom(
                backgroundColor: primaryColor,
                foregroundColor: Colors.white,
              ),
              child: Text(strings.download),
            ),
          ],
        ),
      );
    },

    onShowPermissionDialog: (context) async {
      final result = await showDialogHelper<bool>(
        context,
        (ctx) => AlertDialog(
          title: Text(strings.permissionRequired),
          content: Text(strings.permissionMessage),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(ctx).pop(false),
              child: Text(strings.cancel),
            ),
            ElevatedButton(
              onPressed: () => Navigator.of(ctx).pop(true),
              child: Text(strings.openSettings),
            ),
          ],
        ),
      );
      return result ?? false;
    },

    onShowPermissionDenied: (context) {
      showSnackBar(context, strings.permissionDenied, Colors.red);
    },

    onShowManualInstallRequired: (context, filePath) {
      showDialogHelper(
        context,
        (ctx) => AlertDialog(
          title: Text(strings.manualInstallRequired),
          content: Text(
            'The APK has been downloaded to:\n$filePath\n\n'
            'Please install it manually using your file manager.',
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(ctx).pop(),
              child: Text(strings.ok),
            ),
          ],
        ),
      );
    },

    onShowDownloadProgress: (context, progress, status, isDownloading) {
      // Store the dialog's navigator context
      BuildContext? dialogContext;

      showDialogHelper(
        context,
        (ctx) {
          dialogContext = ctx;
          return PopScope(
            canPop: false,
            child: _DownloadProgressDialog(
              progress: progress,
              status: status,
              isDownloading: isDownloading,
              primaryColor: primaryColor,
              title: strings.downloading,
              closeText: strings.close,
              onClose: () => Navigator.of(ctx).pop(),
            ),
          );
        },
      );

      // Return dismiss callback
      return () {
        if (dialogContext != null && Navigator.of(dialogContext!).canPop()) {
          Navigator.of(dialogContext!).pop();
        }
      };
    },
  );
}