dialog_utils.dart 3.88 KB
import 'dart:async';

import 'package:doublefeel_flutter/app/actions/dialog_action.dart';
import 'package:doublefeel_flutter/app/models/action_result.dart';
import 'package:doublefeel_flutter/app/models/dialog_meta_data.dart';
import 'package:doublefeel_flutter/app/models/input_dialog_meta_data.dart';
import 'package:doublefeel_flutter/app/widget/common_dialog_view.dart';
import 'package:doublefeel_flutter/app/widget/common_input_dialog_view.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class DialogUtils {
  DialogUtils._();

  static Future<ActionResult<A, R>> showDialog<A, R>(
    Widget Function(R?, ValueChanged<ActionResult<A, R>>) viewBuilder,
    R? data, {
    bool needClose = true,
    bool barrierDismissible = true,
    bool? backDismissible,
    Color? barrierColor,
    A? dismissAction,
  }) {
    final completer = Completer<ActionResult<A, R>>();

    void complete(ActionResult<A, R> actionResult) {
      if (!completer.isCompleted) {
        completer.complete(actionResult);
      }
    }

    final dialogView = PopScope(
      canPop: backDismissible ?? barrierDismissible,
      child: viewBuilder(data, (actionResult) {
        complete(actionResult);
        if (needClose && Get.isDialogOpen == true) {
          Get.back<void>();
        }
      }),
    );

    Get.dialog<void>(
      dialogView,
      barrierColor:
          barrierColor ?? const Color(0xFF000000).withValues(alpha: 0.70),
      barrierDismissible: barrierDismissible,
    ).then((_) {
      complete(
        ActionResult<A, R>(
          action: dismissAction,
          data: data,
        ),
      );
    });

    return completer.future;
  }

  static Future<ActionResult<DialogAction, DialogMetaData>> showCommonDialog(
    DialogMetaData dialogMetaData, {
    bool? needClose,
    bool? dismissible,
    bool? barrierDismissible,
    bool? backDismissible,
    Color? barrierColor,
  }) {
    final defaultDismissible = dismissible ?? dialogMetaData.isCancelable;
    final canDismissByBarrier = barrierDismissible ?? defaultDismissible;
    final canDismissByBack = backDismissible ?? defaultDismissible;
    return showDialog<DialogAction, DialogMetaData>(
      (data, callback) {
        return CommonDialogView(
          dialogMetaData: dialogMetaData,
          onAction: callback,
        );
      },
      dialogMetaData,
      needClose: needClose ?? true,
      barrierDismissible: canDismissByBarrier,
      backDismissible: canDismissByBack,
      barrierColor: barrierColor,
      dismissAction: DialogAction.dismiss,
    );
  }

  static Future<ActionResult<DialogAction, String>> showInputDialog(
    InputDialogMetaData dialogMetaData, {
    bool? needClose,
    bool? dismissible,
    bool? barrierDismissible,
    bool? backDismissible,
    Color? barrierColor,
  }) {
    final defaultDismissible = dismissible ?? dialogMetaData.isCancelable;
    final canDismissByBarrier = barrierDismissible ?? defaultDismissible;
    final canDismissByBack = backDismissible ?? defaultDismissible;

    final completer = Completer<ActionResult<DialogAction, String>>();

    void complete(ActionResult<DialogAction, String> actionResult) {
      if (!completer.isCompleted) {
        completer.complete(actionResult);
      }
    }

    final dialogView = PopScope(
      canPop: canDismissByBack,
      child: CommonInputDialogView(
        dialogMetaData: dialogMetaData,
        onAction: (actionResult) {
          complete(actionResult);
          if ((needClose ?? true) && Get.isDialogOpen == true) {
            Get.back<void>();
          }
        },
      ),
    );

    Get.dialog<void>(
      dialogView,
      barrierColor:
          barrierColor ?? const Color(0xFF000000).withValues(alpha: 0.70),
      barrierDismissible: canDismissByBarrier,
    ).then((_) {
      complete(
        const ActionResult(
          action: DialogAction.dismiss,
        ),
      );
    });

    return completer.future;
  }
}