cancel_subscription_dialog.dart 4.62 KB
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

/// Confirmation dialog for cancelling an OHOS auto-renewing subscription.
class CancelSubscriptionDialog extends StatefulWidget {
  const CancelSubscriptionDialog({
    super.key,
    required this.onConfirm,
  });

  final Future<bool> Function() onConfirm;

  @override
  State<CancelSubscriptionDialog> createState() =>
      _CancelSubscriptionDialogState();
}

class _CancelSubscriptionDialogState extends State<CancelSubscriptionDialog> {
  bool _isSubmitting = false;

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: !_isSubmitting,
      child: Dialog(
        backgroundColor: Colors.transparent,
        insetPadding: EdgeInsets.zero,
        child: Container(
          width: 300.dp,
          padding: EdgeInsets.fromLTRB(24.dp, 24.dp, 24.dp, 20.dp),
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(24.dp),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Image.asset(
                'assets/images/common/ic_warning.png',
                width: 60.dp,
                height: 60.dp,
              ),
              SizedBox(height: 20.dp),
              Column(
                children: [
                  SizedBox(
                    width: 220.dp,
                    child: const Text(
                      '确认取消自动续费?',
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        color: Color(0xFF141414),
                        fontSize: 18,
                        fontWeight: FontWeight.w600,
                        height: 1.2,
                      ),
                    ),
                  ),
                  SizedBox(height: 16.dp),
                  const Text(
                    '取消后,DoubleFeel Pro 会员权益仍可使用至当前订阅周期结束,之后将不再自动续费或扣款。',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      color: Color(0xFF6E6D80),
                      fontSize: 15,
                      fontWeight: FontWeight.w400,
                      height: 1.35,
                    ),
                  ),
                ],
              ),
              SizedBox(height: 20.dp),
              _DialogButton(
                label: '确定',
                backgroundColor: const Color(0xFF845EEE),
                foregroundColor: Colors.white,
                loading: _isSubmitting,
                onTap: _isSubmitting ? null : _confirm,
              ),
              SizedBox(height: 4.dp),
              _DialogButton(
                label: '取消',
                foregroundColor: const Color(0xFF6E6D80),
                onTap: _isSubmitting ? null : Get.back,
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _confirm() async {
    if (_isSubmitting) return;

    setState(() => _isSubmitting = true);
    try {
      final shouldClose = await widget.onConfirm();
      if (shouldClose && mounted && Get.isDialogOpen == true) {
        Get.back<void>();
      }
    } finally {
      if (mounted) setState(() => _isSubmitting = false);
    }
  }
}

class _DialogButton extends StatelessWidget {
  const _DialogButton({
    required this.label,
    required this.foregroundColor,
    required this.onTap,
    this.backgroundColor,
    this.loading = false,
  });

  final String label;
  final Color foregroundColor;
  final Color? backgroundColor;
  final VoidCallback? onTap;
  final bool loading;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      behavior: HitTestBehavior.opaque,
      child: Container(
        width: 220.dp,
        height: 48.dp,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: backgroundColor,
          borderRadius: BorderRadius.circular(24.dp),
        ),
        child: loading
            ? SizedBox(
                width: 18.dp,
                height: 18.dp,
                child: const CircularProgressIndicator(
                  color: Colors.white,
                  strokeWidth: 2,
                ),
              )
            : Text(
                label,
                style: TextStyle(
                  color: foregroundColor,
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                  height: 1.2,
                ),
              ),
      ),
    );
  }
}