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 with SingleTickerProviderStateMixin { late TabController _tabController; final List _pages = []; final List _tabs = []; Map 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(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( builder: (context, ref, child) { List 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( 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, ), ), ], ), ), ), ), ], ), ); }, ); } }