add_friend_view.dart 10.7 KB
import 'package:doublefeel_flutter/app/ext/font_ext.dart';
import 'package:doublefeel_flutter/core/theme/app_colors.dart';
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:doublefeel_flutter/r.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../controllers/add_friend_controller.dart';
import '../widgets/primary_button.dart';

class AddFriendView extends GetView<AddFriendController> {
  const AddFriendView({super.key});

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        _buildGradientBackground(),
        Scaffold(
          backgroundColor: Colors.transparent,
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            toolbarHeight: 44.dp,
            centerTitle: true,
            title: Text(
              '',
              style: TextStyle(
                fontSize: 16,
                color: Color(0xFF000000),
                fontWeight: FontWeight.w500,
              ),
            ),
            leading: IconButton(
              highlightColor: Colors.transparent,
              padding: EdgeInsets.zero,
              onPressed: () {
                controller.executeBackLogic();
              },
              icon: Image(
                width: 24.w,
                height: 24.w,
                alignment: Alignment.centerLeft,
                image: AssetImage(R.assetsImagesNavBackIcon),
              ),
            ),
          ),
          body: PopScope(
            canPop: false,
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: _dismissKeyboard,
              child: _buildContentView(),
            ),
          ),
        ),
      ],
    );
  }

  /// 渐变背景
  Widget _buildGradientBackground() {
    return Positioned.fill(
      child: Container(
        decoration: const BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            stops: [0.0, 0.25, 0.75, 1.0],
            colors: [
              Color(0xFFE6DBFF),
              Color(0xFFEDE4FF),
              Color(0xFFEEE6FF),
              Color(0xFFF9F6FF),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildContentView() {
    return LayoutBuilder(
      builder: (context, constraints) {
        return SingleChildScrollView(
          keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
          physics: const ClampingScrollPhysics(),
          child: ConstrainedBox(
            constraints: BoxConstraints(minHeight: constraints.maxHeight),
            child: Column(
              children: [
                SizedBox(height: 4),
                Text(
                  context.l10n.bindPartnerTitle,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: Color(0xFF141414),
                    fontSize: 20,
                    fontWeight: FontWeight.w600,
                    height: 1.3,
                  ),
                ),
                _buildFriendAddCard(),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildFriendAddCard() {
    return SizedBox(
      height: 546.dp,
      child: Stack(
        clipBehavior: Clip.none,
        children: [
          Positioned(
            top: 28.dp,
            left: 24.dp,
            right: 24.dp,
            child: _buildFriendInviteCard(),
          ),
          Positioned(
            top: 0.dp,
            left: 11.dp,
            child: Image(
              width: 87.dp,
              height: 108.dp,
              fit: BoxFit.contain,
              image: AssetImage(R.assetsImagesFriendsFriendAddMeIllustration),
            ),
          ),
          Positioned(
            right: 0,
            bottom: 0,
            child: Image(
              width: 173.dp,
              height: 105.dp,
              fit: BoxFit.contain,
              image:
                  AssetImage(R.assetsImagesFriendsFriendAddOtherIllustration),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildFriendInviteCard() {
    return SizedBox(
      width: double.infinity,
      height: 460.dp,
      child: Stack(
        children: [
          Image(
            width: double.infinity,
            height: double.infinity,
            fit: BoxFit.fill,
            image: AssetImage(R.assetsImagesFriendsFriendAddSubtractBg),
          ),
          Column(
            children: [
              SizedBox(
                height: 230,
                child: _buildMeInviteCard(),
              ),
              SizedBox(
                height: 230,
                child: _buildOtherInviteCard(),
              ),
            ],
          ),
          _buildCardDivider(),
        ],
      ),
    );
  }

  Widget _buildMeInviteCard() {
    return Padding(
      padding: EdgeInsets.fromLTRB(32.dp, 28, 32.dp, 0),
      child: Column(
        children: [
          Text(
            l10n.bindPartnerMyId,
            textAlign: TextAlign.center,
            style: TextStyle(
              color: AppColors.textPrimary,
              fontSize: 14,
              fontWeight: FontWeight.w400,
            ),
          ),
          SizedBox(height: 13),
          _MyInviteCode(controller: controller),
          SizedBox(height: 26),
          PrimaryButton(
            label: l10n.bindPartnerShareMyCode,
            enabled: true,
            loading: false,
            onTap: controller.copyMyInviteCode,
          ),
        ],
      ),
    );
  }

  Widget _buildOtherInviteCard() {
    return Padding(
      padding: EdgeInsets.fromLTRB(32.dp, 46, 32.dp, 0),
      child: Column(
        children: [
          Text(
            l10n.bindPartnerContactId,
            textAlign: TextAlign.center,
            style: TextStyle(
              color: Color(0xFF141414),
              fontSize: 14,
              fontWeight: FontWeight.w400,
              height: 1.4,
            ),
          ),
          SizedBox(height: 18),
          _FriendIdInput(controller: controller),
          SizedBox(height: 16),
          Obx(
            () => PrimaryButton(
              label: l10n.friendsAddAction,
              enabled: controller.canSubmit && !controller.isSubmitting.value,
              loading: controller.isSubmitting.value,
              backgroundColor: const Color(0xFFFF916A),
              disabledColor: const Color(0xFFFF916A).withValues(alpha: 0.45),
              onTap: () {
                _handleSubmit();
              },
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildCardDivider() {
    return Positioned(
      top: 230.h,
      left: 51.dp,
      right: 51.dp,
      child: Stack(
        clipBehavior: Clip.none,
        alignment: Alignment.center,
        children: [
          Image(
            height: 2,
            fit: BoxFit.fill,
            image: AssetImage(R.assetsImagesFriendsFriendAddVectorIcon),
          ),
          Positioned(
            top: -18.dp,
            child: Container(
              width: 36.dp,
              height: 36.dp,
              alignment: Alignment.center,
              decoration: const BoxDecoration(
                color: Color(0xFFE8DDFF),
                shape: BoxShape.circle,
              ),
              child: Text(
                l10n.bindPartnerOr,
                style: TextStyle(
                  color: AppColors.primary,
                  fontSize: 14,
                  fontWeight: FontWeight.w400,
                  height: 1.2,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Future<void> _handleSubmit() async {
    final context = Get.context;
    final hasKeyboard =
        context != null && MediaQuery.of(context).viewInsets.bottom > 0;

    controller.friendCodeFocusNode.canRequestFocus = false;
    _dismissKeyboard();
    if (hasKeyboard) {
      await Future.delayed(const Duration(milliseconds: 120));
    }

    final didAddFriend = await controller.submitFriendCode();
    if (!didAddFriend) {
      controller.friendCodeFocusNode.canRequestFocus = true;
    }
  }

  void _dismissKeyboard() {
    controller.friendCodeFocusNode.unfocus();
    FocusManager.instance.primaryFocus?.unfocus();
  }
}

class _MyInviteCode extends StatelessWidget {
  const _MyInviteCode({required this.controller});

  final AddFriendController controller;

  @override
  Widget build(BuildContext context) {
    return Obx(
      () => Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            controller.myInviteCode.value,
            style: const TextStyle(
              color: AppColors.primary,
              fontSize: 30,
              fontWeight: FontWeight.w600,
              height: 1.2,
            ),
          ),
          SizedBox(width: 8.dp),
          GestureDetector(
            onTap: controller.copyMyInviteCode,
            behavior: HitTestBehavior.opaque,
            child: Container(
              width: 20.dp,
              height: 20.dp,
              decoration: BoxDecoration(
                color: Color(0xFFF0F0F6),
                borderRadius: BorderRadius.all(Radius.circular(6)),
              ),
              alignment: Alignment.center,
              child: Image(
                  width: 14.dp,
                  height: 14.dp,
                  fit: BoxFit.contain,
                  image: AssetImage(R.assetsImagesCopyPurple)),
            ),
          ),
        ],
      ),
    );
  }
}

class _FriendIdInput extends StatelessWidget {
  const _FriendIdInput({required this.controller});

  final AddFriendController controller;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 52.dp,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(26.dp),
        border: Border.all(color: AppColors.border),
      ),
      padding: EdgeInsets.symmetric(horizontal: 20.dp),
      alignment: Alignment.center,
      child: TextField(
        controller: controller.friendCodeController,
        focusNode: controller.friendCodeFocusNode,
        keyboardType: TextInputType.text,
        textInputAction: TextInputAction.done,
        textAlign: TextAlign.center,
        minLines: 1,
        maxLines: 1,
        decoration: InputDecoration(
          border: InputBorder.none,
          hintText: context.l10n.friendsEnterId,
          hintStyle: const TextStyle(
            color: AppColors.disabled,
            fontSize: 26,
            fontWeight: FontWeightExt.medium,
          ),
        ),
        style: const TextStyle(
          color: Color(0xFF141414),
          fontSize: 26,
          fontWeight: FontWeightExt.medium,
        ),
      ),
    );
  }
}