2026-07-01 18:25:58 +08:00

909 lines
48 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:convert';
import 'dart:ui';
import 'dart:ui' as ui;
import 'package:carousel_slider/carousel_slider.dart';
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
import 'package:aslan/chatvibe_features/dynamic/person_dynamic_list_page.dart';
import 'package:aslan/chatvibe_features/index/main_route.dart';
import 'package:provider/provider.dart';
import 'package:aslan/app_localizations.dart';
import 'package:aslan/chatvibe_ui/components/appbar/chatvibe_appbar.dart';
import 'package:aslan/chatvibe_ui/components/at_compontent.dart';
import 'package:aslan/chatvibe_ui/components/text/at_text.dart';
import 'package:aslan/chatvibe_ui/components/at_tts.dart';
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
import 'package:aslan/chatvibe_data/sources/repositories/user_repository_impl.dart';
import 'package:aslan/chatvibe_domain/models/res/login_res.dart';
import 'package:aslan/chatvibe_managers/user_profile_manager.dart';
import 'package:aslan/chatvibe_features/user/profile/profile/profile_page.dart';
import 'package:aslan/chatvibe_features/user/profile/props/props_page.dart';
import 'package:aslan/chatvibe_features/user/profile/relation/relation_ship_page.dart';
import 'package:aslan/chatvibe_core/config/business_logic_strategy.dart';
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
import '../../chatvibe_domain/models/res/at_user_counter_res.dart';
import '../../chatvibe_domain/usecases/at_fixed_width_tabIndicator.dart';
import '../../chatvibe_domain/usecases/at_shining_text.dart';
class MePage extends StatefulWidget {
@override
_MePageState createState() => _MePageState();
}
class _MePageState extends State<MePage> with SingleTickerProviderStateMixin {
late TabController _tabController;
final List<Widget> _pages = [];
final List<Widget> _tabs = [];
Map<String, ATUserCounterRes> counterMap = {};
// 业务逻辑策略访问器
BusinessLogicStrategy get _strategy => ATGlobalConfig.businessLogicStrategy;
// 添加滚动控制器
final ScrollController _scrollController = ScrollController();
double _opacity = 0.0;
@override
void initState() {
super.initState();
// 监听滚动
_scrollController.addListener(() {
if (_scrollController.hasClients) {
final offset = _scrollController.offset;
// 当滚动到一定位置时头像和昵称应该完全显示在AppBar上
// 这里计算透明度,可以根据需要调整
final newOpacity = (offset / _strategy.getMePageScrollOpacityThreshold()).clamp(0.0, 1.0);
if (newOpacity != _opacity) {
setState(() {
_opacity = newOpacity;
});
}
}
});
_pages.add(
PersonDynamicListPage(true,AccountStorage().getCurrentUser()?.userProfile?.id ?? ""),
);
_pages.add(
ProfilePage(true, AccountStorage().getCurrentUser()?.userProfile?.id ?? ""),
);
_pages.add(
PropsPage(true, AccountStorage().getCurrentUser()?.userProfile?.id ?? ""),
);
_pages.add(
RelationShipPage(
true,
AccountStorage().getCurrentUser()?.userProfile?.id ?? "",
),
);
_tabController = TabController(initialIndex: _strategy.getMePageInitialTabIndex(),length: _pages.length, vsync: this);
_tabController.addListener(() {
setState(() {});
}); // 监听切换
Provider.of<ChatVibeUserProfileManager>(context, listen: false).getMyUserInfo();
userCounter("${AccountStorage().getCurrentUser()?.userProfile?.id}");
}
void userCounter(String userId) async {
counterMap.clear();
var userCounterList = await AccountRepository().userCounter(userId);
counterMap = Map.fromEntries(
userCounterList.map(
(counter) => MapEntry(counter.counterType ?? "", counter),
),
);
setState(() {});
}
Widget _buildTab(int index, String text) {
final isSelected = _tabController.index == index;
return isSelected
? Tab(
icon: ATShiningText(
text: text,
fontSize: 15.sp,
shineColor: _strategy.getMePageShineColor(),
),
)
: Tab(text: text);
}
@override
Widget build(BuildContext context) {
_tabs.clear();
_tabs.add(_buildTab(0, ATAppLocalizations.of(context)!.dynamicT));
_tabs.add(_buildTab(1, ATAppLocalizations.of(context)!.profile));
_tabs.add(_buildTab(2, ATAppLocalizations.of(context)!.props));
_tabs.add(_buildTab(3, ATAppLocalizations.of(context)!.relationShip));
return Consumer<ChatVibeUserProfileManager>(
builder: (context, ref, child) {
List<PersonPhoto> backgroundPhotos = [];
backgroundPhotos =
(AccountStorage().getCurrentUser()?.userProfile?.backgroundPhotos ??
[])
.where((t) => t.status == 1)
.toList();
return Directionality(
textDirection:
window.locale.languageCode == "ar"
? TextDirection.rtl
: TextDirection.ltr, // 强制指定为从左到右
child: Stack(
children: [
backgroundPhotos.isNotEmpty
? SizedBox(
height: 300.w,
child: CarouselSlider(
options: CarouselOptions(
height: 300.w,
autoPlay: backgroundPhotos.length > 1,
// 启用自动播放
enlargeCenterPage: false,
// 居中放大当前页面
aspectRatio: 1 / 1,
// 宽高比
enableInfiniteScroll: true,
// 启用无限循环
autoPlayAnimationDuration: Duration(milliseconds: 800),
// 自动播放动画时长
viewportFraction: 1,
// 视口分数
onPageChanged: (index, reason) {
setState(() {});
},
),
items:
backgroundPhotos.map((item) {
return GestureDetector(
child: netImage(
url: item.url ?? "",
width: ScreenUtil().screenWidth,
height: 280.w,
fit: BoxFit.cover,
),
onTap: () {},
);
}).toList(),
),
)
: SizedBox(
height: 300.w,
child: Image.asset(
_strategy.getMePageDefaultBackgroundImage(),
width: ScreenUtil().screenWidth,
height: 300.w,
fit: BoxFit.cover,
),
),
PositionedDirectional(
top: 260.w,
child: Container(
margin: EdgeInsets.only(bottom: 28.w),
child: Image.asset(
_strategy.getMePageGenderBackgroundImage(
AccountStorage().getCurrentUser()?.userProfile?.userSex == 0,
),
height: ScreenUtil().screenHeight,
width: ScreenUtil().screenWidth,
fit: BoxFit.fill,
),
),
),
ClipRRect(
child: BackdropFilter(
filter: ui.ImageFilter.blur(
sigmaX: 15 * _opacity,
sigmaY: 15 * _opacity,
),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: _strategy.getMePageGradientColors(
AccountStorage().getCurrentUser()?.userProfile?.userSex == 0,
).map((color) => color.withOpacity(_opacity)).toList(),
begin: AlignmentDirectional.centerStart,
end: AlignmentDirectional.centerEnd,
),
),
height: ScreenUtil().screenHeight,
width: ScreenUtil().screenWidth,
),
),
),
Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
appBar: ChatVibeStandardAppBar(
backButtonColor: Colors.white,
leading: Container(),
title: "",
actions: [
if (_opacity > _strategy.getMePageOpacityThresholdForAvatarDisplay()) ...[
SizedBox(width: 15.w),
head(
url:
AccountStorage()
.getCurrentUser()
?.userProfile
?.userAvatar ??
"",
width: 50.w,
height: 50.w,
headdress:
AccountStorage()
.getCurrentUser()
?.userProfile
?.getHeaddress()
?.sourceUrl,
),
SizedBox(width: 8.w),
chatvibeNickNameText(
maxWidth: 135.w,
AccountStorage()
.getCurrentUser()
?.userProfile
?.userNickname ??
"",
fontSize: 16.sp,
fontWeight: FontWeight.w600,
type:
AccountStorage()
.getCurrentUser()
?.userProfile
?.getVIP()
?.name ??
"",
needScroll:
( AccountStorage()
.getCurrentUser()
?.userProfile
?.userNickname
?.characters.length ??
0) >
_strategy.getMePageNicknameScrollThreshold(),
),
SizedBox(width: 8.w),
],
Spacer(),
IconButton(
icon: Image.asset(
_strategy.getMePageEditUserInfoIcon(),
width: 22.w,
color: Colors.white,
),
onPressed: () {
ATNavigatorUtils.push(
context,
MainRoute.edit,
replace: false,
);
},
),
],
),
body: ExtendedNestedScrollView(
controller: _scrollController,
onlyOneScrollInBody: true,
headerSliverBuilder: (
BuildContext context,
bool innerBoxIsScrolled,
) {
return [
SliverToBoxAdapter(
child: Container(
color: Colors.transparent,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 145.w), // 给AppBar留出空间
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(width: 15.w),
(AccountStorage()
.getCurrentUser()
?.userProfile
?.cpList
?.isNotEmpty ??
false)
? SizedBox(
height: 100.w,
child: Stack(
alignment: Alignment.center,
children: [
Transform.translate(
offset: Offset(0, -5),
child: Row(
mainAxisSize:
MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment
.center,
children: [
GestureDetector(
child: netImage(
url:
AccountStorage()
.getCurrentUser()
?.userProfile
?.cpList
?.first
.meUserAvatar ??
"",
width: 56.w,
defaultImg:
_strategy.getMePageDefaultAvatarImage(),
shape:
BoxShape.circle,
),
onTap: () {
String
encodedUrls = Uri.encodeComponent(
jsonEncode([
AccountStorage()
.getCurrentUser()
?.userProfile
?.cpList
?.first
.meUserAvatar,
]),
);
ATNavigatorUtils.push(
context,
"${MainRoute.imagePreview}?imageUrls=$encodedUrls&initialIndex=0",
);
},
),
SizedBox(width: 32.w),
GestureDetector(
onTap: () {
ATNavigatorUtils.push(
context,
replace: false,
"${MainRoute.person}?isMe=${AccountStorage().getCurrentUser()?.userProfile?.id == AccountStorage().getCurrentUser()?.userProfile?.cpList?.first.cpUserId}&tageId=${AccountStorage().getCurrentUser()?.userProfile?.cpList?.first.cpUserId}",
);
},
child: netImage(
url:
AccountStorage()
.getCurrentUser()
?.userProfile
?.cpList
?.first
.cpUserAvatar ??
"",
defaultImg:
_strategy.getMePageDefaultAvatarImage(),
width: 56.w,
shape:
BoxShape.circle,
),
),
],
),
),
IgnorePointer(
child: Transform.translate(
offset: Offset(0, -15),
child: Image.asset(
_strategy.getMePageCpDialogHeadImage(),
),
),
),
],
),
)
: GestureDetector(
child: head(
url:
AccountStorage()
.getCurrentUser()
?.userProfile
?.userAvatar ??
"",
width: 88.w,
headdress:
AccountStorage()
.getCurrentUser()
?.userProfile
?.getHeaddress()
?.sourceUrl,
),
onTap: () {
String encodedUrls =
Uri.encodeComponent(
jsonEncode([
AccountStorage()
.getCurrentUser()
?.userProfile
?.userAvatar,
]),
);
ATNavigatorUtils.push(
context,
"${MainRoute.imagePreview}?imageUrls=$encodedUrls&initialIndex=0",
);
},
),
],
),
SizedBox(height: 6.w),
Row(
children: [
SizedBox(width: 25.w),
chatvibeNickNameText(
maxWidth: 135.w,
AccountStorage()
.getCurrentUser()
?.userProfile
?.userNickname ??
"",
fontSize: 18.sp,
fontWeight: FontWeight.w600,
type:
AccountStorage()
.getCurrentUser()
?.userProfile
?.getVIP()
?.name ??
"",
needScroll:
( AccountStorage()
.getCurrentUser()
?.userProfile
?.userNickname
?.characters.length ??
0) >
_strategy.getMePageNicknameScrollThreshold(),
),
SizedBox(width: 3.w),
getVIPBadge(
AccountStorage()
.getCurrentUser()
?.userProfile
?.getVIP()
?.name,
width: 45.w,
height: 25.w,
),
],
),
SizedBox(height: 5.w),
Row(
children: [
SizedBox(width: 15.w),
GestureDetector(
child: Container(
padding: EdgeInsets.symmetric(
vertical: 8.w,
),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
(AccountStorage()
.getCurrentUser()
?.userProfile
?.hasSpecialId() ??
false)
? _strategy.getMePageIdBackgroundImage(true)
: _strategy.getMePageIdBackgroundImage(false),
),
fit: BoxFit.fitWidth,
),
),
child: Row(
textDirection: TextDirection.ltr,
children: [
SizedBox(width: 38.w),
text(
"${AccountStorage().getCurrentUser()?.userProfile?.getID()}",
fontSize: 12.sp,
textColor: Colors.white,
fontWeight: FontWeight.bold,
),
SizedBox(width: 5.w),
Image.asset(
_strategy.getMePageCopyIdIcon(),
width: 12.w,
height: 12.w,
),
SizedBox(width: 8.w),
],
),
),
onTap: () {
Clipboard.setData(
ClipboardData(
text:
AccountStorage()
.getCurrentUser()
?.userProfile
?.getID() ??
"",
),
);
ATTts.show(
ATAppLocalizations.of(
context,
)!.copiedToClipboard,
);
},
),
SizedBox(width: 12.w),
Container(
width: (AccountStorage()
.getCurrentUser()
?.userProfile?.age??0) > _strategy.getMePageAgeDisplayWidthThreshold() ? 58.w : 48.w,
height: 24.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
_strategy.getMePageGenderAgeBackgroundImage(
AccountStorage()
.getCurrentUser()
?.userProfile
?.userSex == 0,
),
),
),
),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
xb(
AccountStorage()
.getCurrentUser()
?.userProfile
?.userSex,
),
text(
"${AccountStorage().getCurrentUser()?.userProfile?.age}",
textColor: Colors.white,
fontSize: 14.sp,
fontWeight: FontWeight.w600,
),
SizedBox(width: 3.w),
],
),
),
SizedBox(width: 8.w),
getWealthLevel(
AccountStorage()
.getCurrentUser()
?.userProfile
?.wealthLevel ??
0,
width: 58.w,
height: 30.w,
),
SizedBox(width: 8.w),
getUserLevel(
AccountStorage()
.getCurrentUser()
?.userProfile
?.charmLevel ??
0,
width: 58.w,
height: 30.w,
),
],
),
SizedBox(height: 5.w),
AccountStorage()
.getCurrentUser()
?.userProfile
?.wearHonor
?.where((item) {
return item.use ?? false;
})
.isNotEmpty ??
false
? Row(
children: [
SizedBox(width: 15.w),
Expanded(
child: Wrap(
runSpacing: 2.w,
spacing: 4.w,
direction: Axis.horizontal,
children:
AccountStorage()
.getCurrentUser()!
.userProfile!
.wearHonor!
.where((item) {
return item.use ??
false;
})
.map((item) {
return netImage(
url:
item.animationUrl ??
"",
height: 28.w,
);
})
.toList(),
),
),
SizedBox(width: 5.w),
],
)
: Container(),
(AccountStorage()
.getCurrentUser()
?.userProfile
?.wearHonor
?.where((item) {
return item.use ?? false;
})
.isNotEmpty ??
false)
? SizedBox(height: 5.w)
: Container(),
Container(
margin: EdgeInsetsDirectional.symmetric(
horizontal: 10.w,
),
alignment: AlignmentDirectional.centerStart,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(width: 5.w),
ref.userProfile?.wearBadge?.where((
item,
) {
return item.use ?? false;
}).isNotEmpty ??
false
? SizedBox(
height: 35.w,
child: ListView.separated(
scrollDirection:
Axis.horizontal,
shrinkWrap: true,
itemCount:
ref.userProfile?.wearBadge
?.where((item) {
return item.use ??
false;
})
.length ??
0,
itemBuilder: (
context,
index,
) {
return netImage(
width: 35.w,
height: 35.w,
url:
ref
.userProfile
?.wearBadge
?.where((item) {
return item
.use ??
false;
})
.toList()[index]
.selectUrl ??
"",
);
},
separatorBuilder: (
BuildContext context,
int index,
) {
return SizedBox(width: 5.w);
},
),
)
: Container(),
SizedBox(width: 5.w),
],
),
),
),
SizedBox(height: 8.w),
Consumer<ChatVibeUserProfileManager>(
builder: (context, ref, child) {
return Container(
height: 72.w,
alignment: AlignmentDirectional.center,
width: ScreenUtil().screenWidth,
margin: EdgeInsets.symmetric(
horizontal: 18.w,
),
padding: EdgeInsets.symmetric(
horizontal: 35.w,
),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
_strategy.getMePageVisitorsFollowFansBackgroundImage(
AccountStorage()
.getCurrentUser()
?.userProfile
?.userSex == 0,
),
),
fit: BoxFit.fill,
),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
text(
ATAppLocalizations.of(
context,
)!.vistors,
fontSize: 14.sp,
fontWeight: FontWeight.w600,
textColor: _strategy.getMePageVisitorsFollowFansTextColor(),
),
text(
"${counterMap["INTERVIEW"]?.quantity ?? 0}",
fontSize: 17.sp,
fontWeight: FontWeight.bold,
),
],
),
onTap: () {
ATNavigatorUtils.push(
context,
MainRoute.vistors,
);
},
),
GestureDetector(
onTap: () {
ATNavigatorUtils.push(
context,
MainRoute.follow,
);
},
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
text(
ATAppLocalizations.of(
context,
)!.follow,
fontSize: 14.sp,
fontWeight: FontWeight.w600,
textColor: _strategy.getMePageVisitorsFollowFansTextColor(),
),
text(
"${counterMap["SUBSCRIPTION"]?.quantity ?? 0}",
fontSize: 17.sp,
fontWeight: FontWeight.bold,
),
],
),
),
GestureDetector(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
text(
ATAppLocalizations.of(
context,
)!.fans,
fontSize: 14.sp,
fontWeight: FontWeight.w600,
textColor: _strategy.getMePageVisitorsFollowFansTextColor(),
),
text(
"${counterMap["FANS"]?.quantity ?? 0}",
fontSize: 17.sp,
fontWeight: FontWeight.bold,
),
],
),
onTap: () {
ATNavigatorUtils.push(
context,
MainRoute.fans,
);
},
),
],
),
);
},
),
SizedBox(height: 6.w),
],
),
],
),
),
),
];
},
body: Container(
padding: EdgeInsets.symmetric(horizontal: 5.w),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: _strategy.getMePageGradientColors(
AccountStorage()
.getCurrentUser()
?.userProfile
?.userSex == 0,
).map((color) => color.withOpacity(_opacity)).toList(),
begin: AlignmentDirectional.topStart,
end: AlignmentDirectional.bottomEnd,
),
),
child: Column(
children: [
TabBar(
tabAlignment: TabAlignment.start,
labelPadding: EdgeInsets.symmetric(horizontal: 12.w),
labelColor: Colors.white,
isScrollable: true,
indicator: ATFixedWidthTabIndicator(
width: 20.w,
height: 4.w,
gradient: LinearGradient(
colors: _strategy.getMePageTabIndicatorGradient(
AccountStorage()
.getCurrentUser()
?.userProfile
?.userSex == 0,
),
),
),
unselectedLabelColor: Colors.white54,
labelStyle: TextStyle(
fontSize: 15.sp,
fontWeight: FontWeight.bold,
),
unselectedLabelStyle: TextStyle(
fontSize: 13.sp,
),
indicatorColor: Colors.transparent,
dividerColor: Colors.transparent,
controller: _tabController,
tabs: _tabs,
),
Expanded(
child: TabBarView(
controller: _tabController,
children: _pages,
),
),
],
),
),
),
),
],
),
);
},
);
}
}