import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:yumi/app_localizations.dart'; import 'package:yumi/ui_kit/components/sc_compontent.dart'; import 'package:yumi/ui_kit/components/text/sc_text.dart'; import 'package:yumi/ui_kit/components/sc_tts.dart'; import 'package:yumi/shared/tools/sc_loading_manager.dart'; import 'package:yumi/shared/tools/sc_pick_utils.dart'; import 'package:yumi/shared/data_sources/sources/repositories/sc_user_repository_impl.dart'; import 'package:yumi/services/auth/authentication_manager.dart'; import 'package:provider/provider.dart'; import 'package:yumi/app/constants/sc_screen.dart'; import 'package:yumi/app/routes/sc_routes.dart'; import 'package:yumi/app/routes/sc_fluro_navigator.dart'; import 'package:yumi/shared/tools/sc_date_utils.dart'; import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; import 'package:yumi/shared/business_logic/models/res/login_res.dart'; import 'package:yumi/services/general/sc_app_general_manager.dart'; import 'package:yumi/services/auth/user_profile_manager.dart'; import 'package:yumi/services/audio/rtc_manager.dart'; import 'package:yumi/services/audio/rtm_manager.dart'; import 'package:yumi/app/constants/sc_global_config.dart'; import '../../../shared/business_logic/usecases/sc_custom_filtering_textinput_formatter.dart'; import '../../country/country_route.dart'; ///编辑个人信息 class SCEditProfilePage extends StatefulWidget { const SCEditProfilePage({super.key}); @override _SCEditProfilePageState createState() => _SCEditProfilePageState(); } class _SCEditProfilePageState extends State { ///默认女 int type = 0; DateTime birthdayDate = DateTime(2006); TextEditingController nicknameController = TextEditingController(); SocialChatUserProfileManager? userProvider; @override void initState() { super.initState(); userProvider = Provider.of( context, listen: false, ); Provider.of(context, listen: false).selectCountryInfo = null; } @override void dispose() { userProvider?.resetEditUserData(); super.dispose(); } @override Widget build(BuildContext context) { final businessLogicStrategy = SCGlobalConfig.businessLogicStrategy; return Scaffold( resizeToAvoidBottomInset: false, body: Stack( alignment: Alignment.topCenter, children: [ Image.asset( businessLogicStrategy.getEditProfileBackgroundImage(), width: ScreenUtil().screenWidth, height: ScreenUtil().screenHeight, fit: BoxFit.cover, ), Column( children: [ SizedBox(height: 120.w), GestureDetector( child: Consumer( builder: (_, provider, __) { return provider.editUser != null && provider.editUser!.userAvatar != null ? head( url: provider.editUser!.userAvatar ?? "", width: 75.w, ) : Image.asset( businessLogicStrategy .getEditProfileDefaultAvatarImage(), width: 75.w, height: 75.w, ); }, ), onTap: () { SCPickUtils.pickImage(context, (bool success, String url) { if (success) { userProvider?.updateUserAvatar(url); } }); }, ), SizedBox(height: 15.w), Container( padding: EdgeInsets.only(left: width(12), right: width(12)), alignment: Alignment.center, height: 46.w, width: 300.w, decoration: BoxDecoration( color: businessLogicStrategy .getEditProfileInputBackgroundColor(), borderRadius: BorderRadius.all(Radius.circular(height(8))), ), child: TextField( textAlign: TextAlign.center, controller: nicknameController, onChanged: (text) { setState(() {}); }, inputFormatters: [SCCustomFilteringTextInputFormatter()], maxLength: 38, decoration: InputDecoration( hintText: SCAppLocalizations.of(context)!.enterNickname, hintStyle: TextStyle(color: Colors.white, fontSize: 14.sp), contentPadding: EdgeInsets.only(top: 0.w), counterText: '', isDense: true, filled: false, focusColor: Colors.transparent, hoverColor: Colors.transparent, border: InputBorder.none, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, disabledBorder: InputBorder.none, errorBorder: InputBorder.none, focusedErrorBorder: InputBorder.none, fillColor: Colors.black45, ), style: TextStyle( fontSize: sp(15), color: Colors.white, textBaseline: TextBaseline.alphabetic, ), ), ), SizedBox(height: 15.w), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( child: Container( alignment: Alignment.center, child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( width: 2.w, color: type == 1 ? Color(0xff18F2B1) : Colors.transparent, ), ), child: Image.asset( businessLogicStrategy.getEditProfileGenderIcon( true, ), width: 55.w, height: 55.w, ), ), SizedBox(height: 8.w), text( SCAppLocalizations.of(context)!.male, textColor: type == 1 ? Colors.white : Colors.white, fontWeight: type == 1 ? FontWeight.w600 : FontWeight.w400, fontSize: 13.sp, ), ], ), ), onTap: () { if (type == 0) { setState(() { type = 1; userProvider?.updateUserSex(type); }); } }, ), SizedBox(width: 99.w), GestureDetector( child: Container( alignment: Alignment.center, child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( width: 2.w, color: type == 1 ? Colors.transparent : Color(0xff18F2B1), ), ), child: Image.asset( businessLogicStrategy.getEditProfileGenderIcon( false, ), width: 55.w, height: 55.w, ), ), SizedBox(height: 8.w), text( SCAppLocalizations.of(context)!.female, textColor: type == 1 ? Colors.white : Colors.white, fontWeight: type == 1 ? FontWeight.w400 : FontWeight.w600, fontSize: 13.sp, ), ], ), ), onTap: () { if (type == 1) { setState(() { type = 0; userProvider?.updateUserSex(type); }); } }, ), ], ), SizedBox(height: 12.w), GestureDetector( child: Container( padding: EdgeInsets.only(left: width(12), right: width(12)), alignment: Alignment.center, height: 46.w, width: 300.w, decoration: BoxDecoration( color: businessLogicStrategy .getEditProfileInputBackgroundColor(), borderRadius: BorderRadius.all(Radius.circular(height(12))), ), child: Row( children: [ text( SCAppLocalizations.of(context)!.birthday, fontSize: 15.sp, textColor: Colors.white, ), Spacer(), text( SCMDateUtils.formatDateTime(birthdayDate), textColor: Colors.white54, fontSize: 15.sp, ), Icon( Icons.chevron_right_outlined, color: Colors.white54, size: 20.w, ), ], ), ), onTap: () { _selectDate(); }, ), SizedBox(height: 12.w), GestureDetector( child: Consumer( builder: (_, provider, __) { return Container( padding: EdgeInsets.only( left: width(12), right: width(12), ), alignment: Alignment.center, height: 46.w, width: 300.w, decoration: BoxDecoration( color: businessLogicStrategy .getEditProfileInputBackgroundColor(), borderRadius: BorderRadius.all( Radius.circular(height(12)), ), ), child: provider.selectCountryInfo != null ? Row( mainAxisSize: MainAxisSize.min, children: [ text( SCAppLocalizations.of( context, )!.countryRegion, fontSize: 15.sp, textColor: Colors.white, ), Spacer(), netImage( url: provider .selectCountryInfo! .nationalFlag ?? "", borderRadius: BorderRadius.circular(3), width: 26.w, height: 16.w, ), SizedBox(width: 3.w), text( provider.selectCountryInfo!.aliasName ?? "", textColor: Colors.white54, fontSize: 14.sp, ), Icon( Icons.chevron_right_outlined, color: Colors.white54, size: 20.w, ), ], ) : Row( children: [ text( SCAppLocalizations.of( context, )!.countryRegion, fontSize: 15.sp, textColor: Colors.white, ), Spacer(), text( SCAppLocalizations.of( context, )!.selectYourCountry, textColor: Colors.white54, fontSize: 15.sp, ), Icon( Icons.chevron_right_outlined, color: Colors.white54, size: 20.w, ), ], ), ); }, ), onTap: () { SCNavigatorUtils.push( context, CountryRoute.country, replace: false, ); }, ), SizedBox(height: 45.w), GestureDetector( child: Container( padding: EdgeInsets.only(left: width(12), right: width(12)), alignment: Alignment.center, height: 46.w, width: 270.w, decoration: BoxDecoration( color: businessLogicStrategy .getEditProfileContinueButtonColor(), borderRadius: BorderRadius.all(Radius.circular(height(12))), ), child: text( SCAppLocalizations.of(context)!.conntinue, textColor: Colors.white, fontSize: 15.sp, ), ), onTap: () { _submitUserProfile(); }, ), ], ), ], ), ); } Future _selectDate() async { showCupertinoModalPopup( context: context, builder: (context) => SafeArea( top: false, child: Container( height: 240.w, padding: EdgeInsets.only(top: 6), decoration: BoxDecoration( image: DecorationImage( image: AssetImage( "sc_images/login/sc_icon_login_edit_data_bg.png", ), fit: BoxFit.fill, ), ), child: Column( children: [ SizedBox(height: 10.w), Row( children: [ SizedBox(width: 10.w), GestureDetector( child: Container( alignment: Alignment.topCenter, child: text( SCAppLocalizations.of(context)!.cancel, textColor: Colors.white, fontSize: 15.sp, fontWeight: FontWeight.w600, ), ), onTap: () { Navigator.of(context).pop(); }, ), Spacer(), GestureDetector( child: Container( alignment: Alignment.topCenter, child: text( SCAppLocalizations.of(context)!.confirm, textColor: SCGlobalConfig.businessLogicStrategy .getEditProfileDatePickerConfirmColor(), fontSize: 15.sp, fontWeight: FontWeight.w600, ), ), onTap: () { setState(() {}); Navigator.of(context).pop(); }, ), SizedBox(width: 10.w), ], ), Expanded( child: CupertinoTheme( data: CupertinoThemeData( textTheme: CupertinoTextThemeData( // 在这里设置字体颜色、大小等样式 dateTimePickerTextStyle: TextStyle( color: Colors.white, // 设置字体颜色 fontSize: 16.sp, // 设置字体大小 ), ), ), child: CupertinoDatePicker( mode: CupertinoDatePickerMode.date, initialDateTime: _getBefor18(), maximumDate: _getBefor18(), onDateTimeChanged: (date) => birthdayDate = date, ), ), ), ], ), ), ), ); } DateTime _getBefor18() { DateTime currentDate = DateTime.now(); DateTime eighteenYearsAgo = DateTime( currentDate.year - 18, currentDate.month, currentDate.day, currentDate.hour, currentDate.minute, currentDate.second, currentDate.millisecond, currentDate.microsecond, ); return eighteenYearsAgo; } String? _preferNonEmpty(String? primary, String? fallback) { if (primary != null && primary.isNotEmpty) { return primary; } if (fallback != null && fallback.isNotEmpty) { return fallback; } return primary ?? fallback; } bool _isBrokenLocalMediaUrl(String? url) { return (url ?? "").contains("/external/oss/local/"); } String? _preferUsableAvatar(String? primary, String? fallback) { if (primary != null && primary.isNotEmpty && !_isBrokenLocalMediaUrl(primary)) { return primary; } if (fallback != null && fallback.isNotEmpty && !_isBrokenLocalMediaUrl(fallback)) { return fallback; } return _preferNonEmpty(primary, fallback); } num? _preferNonZero(num? primary, num? fallback) { if (primary != null && primary != 0) { return primary; } if (fallback != null && fallback != 0) { return fallback; } return primary ?? fallback; } ///提交数据 void _submitUserProfile() async { if (nicknameController.text.isEmpty) { SCTts.show(SCAppLocalizations.of(context)!.pleaseEnterNickname); return; } if (userProvider?.editUser?.userAvatar == null) { SCTts.show(SCAppLocalizations.of(context)!.pleaseUploadUserAvatar); return; } if (Provider.of( context, listen: false, ).selectCountryInfo == null) { SCTts.show(SCAppLocalizations.of(context)!.pleaseSelectYourCountry); return; } SCLoadingManager.show(context: context); userProvider?.updateUserNickname(nicknameController.text); userProvider?.updateBornYear(birthdayDate.year); userProvider?.updateBornMonth(birthdayDate.month); userProvider?.updateBornDay(birthdayDate.day); num age = DateTime.now().year - birthdayDate.year; userProvider?.updateAge(age.abs()); String authType = Provider.of( context, listen: false, ).authType; String idToken = Provider.of( context, listen: false, ).uid; SocialChatLoginRes user = await SCAccountRepository().regist( authType, idToken, userProvider!.editUser!, ); final submittedProfile = userProvider?.editUser; if (submittedProfile != null) { final mergedProfile = (user.userProfile ?? SocialChatUserProfile()) .copyWith( userAvatar: _preferUsableAvatar( user.userProfile?.userAvatar, submittedProfile.userAvatar, ), userNickname: _preferNonEmpty( user.userProfile?.userNickname, submittedProfile.userNickname, ), userSex: _preferNonZero( user.userProfile?.userSex, submittedProfile.userSex, ), bornYear: _preferNonZero( user.userProfile?.bornYear, submittedProfile.bornYear, ), bornMonth: _preferNonZero( user.userProfile?.bornMonth, submittedProfile.bornMonth, ), bornDay: _preferNonZero( user.userProfile?.bornDay, submittedProfile.bornDay, ), age: _preferNonZero(user.userProfile?.age, submittedProfile.age), countryCode: _preferNonEmpty( user.userProfile?.countryCode, submittedProfile.countryCode, ), countryId: _preferNonEmpty( user.userProfile?.countryId, submittedProfile.countryId, ), countryName: _preferNonEmpty( user.userProfile?.countryName, submittedProfile.countryName, ), ); user.setUserProfile(mergedProfile); } if (!mounted) { return; } await Provider.of(context, listen: false).resetLocalRoomState( fallbackRtmProvider: Provider.of(context, listen: false), ); if (!mounted) { return; } AccountStorage().setCurrentUser(user); userProvider?.syncCurrentUserProfile(user.userProfile); SCLoadingManager.hide(); SCNavigatorUtils.push(context, SCRoutes.home, clearStack: true); } }