chatapp3-flutter/lib/modules/auth/edit/sc_edit_profile_page.dart
NIGGER SLAYER 37a04d5ad7 bug
2026-04-14 19:21:53 +08:00

640 lines
24 KiB
Dart

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<SCEditProfilePage> {
///默认女
int type = 0;
DateTime birthdayDate = DateTime(2006);
TextEditingController nicknameController = TextEditingController();
SocialChatUserProfileManager? userProvider;
@override
void initState() {
super.initState();
userProvider = Provider.of<SocialChatUserProfileManager>(
context,
listen: false,
);
Provider.of<SCAppGeneralManager>(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<SocialChatUserProfileManager>(
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<SCAppGeneralManager>(
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<void> _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<SCAppGeneralManager>(
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<SocialChatAuthenticationManager>(
context,
listen: false,
).authType;
String idToken =
Provider.of<SocialChatAuthenticationManager>(
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<RtcProvider>(context, listen: false).resetLocalRoomState(
fallbackRtmProvider: Provider.of<RtmProvider>(context, listen: false),
);
if (!mounted) {
return;
}
AccountStorage().setCurrentUser(user);
userProvider?.syncCurrentUserProfile(user.userProfile);
SCLoadingManager.hide();
SCNavigatorUtils.push(context, SCRoutes.home, clearStack: true);
}
}