2026-07-10 20:31:52 +08:00

1020 lines
36 KiB
Dart

import 'package:aslan/chatvibe_core/utilities/at_loading_manager.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:aslan/chatvibe_ui/components/at_debounce_widget.dart';
import 'package:marquee/marquee.dart';
import 'package:provider/provider.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import '../../../../app_localizations.dart';
import '../../../../chatvibe_core/constants/at_global_config.dart';
import '../../../../chatvibe_core/routes/at_fluro_navigator.dart';
import '../../../../chatvibe_core/utilities/at_banner_utils.dart';
import '../../../../chatvibe_data/models/enum/at_vip_type.dart';
import '../../../../chatvibe_data/sources/repositories/room_repository_imp.dart';
import '../../../../chatvibe_domain/models/res/at_banner_leaderboard_res.dart';
import '../../../../chatvibe_domain/models/res/at_index_banner_res.dart';
import '../../../../chatvibe_domain/models/res/country_res.dart';
import '../../../../chatvibe_domain/models/res/follow_room_res.dart';
import '../../../../chatvibe_domain/models/res/room_res.dart';
import '../../../../chatvibe_managers/app_general_manager.dart';
import '../../../../chatvibe_managers/rtc_manager.dart';
import '../../../../chatvibe_ui/components/at_compontent.dart';
import '../../../../chatvibe_ui/components/text/at_text.dart';
import '../../../../chatvibe_ui/widgets/country/at_country_flag_image.dart';
import '../../../index/main_route.dart';
class HomePartyPage extends StatefulWidget {
@override
_HomePartyPageState createState() => _HomePartyPageState();
}
class _HomePartyPageState extends State<HomePartyPage>
with SingleTickerProviderStateMixin {
List<FollowRoomRes> historyRooms = [];
String? lastId;
bool isLoading = false;
final RefreshController _refreshController = RefreshController(
initialRefresh: false,
);
List<ChatVibeRoomRes> rooms = [];
int _currentIndex = 0;
final ScrollController _countryTabController = ScrollController();
final List<GlobalKey> _countryTabKeys = [];
List<Country> _countries = [];
Country? _selectedCountry;
int _dataRequestToken = 0;
bool _countryLoading = false;
@override
void initState() {
super.initState();
loadCountries();
loadData();
}
@override
void dispose() {
_countryTabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
SmartRefresher(
enablePullDown: true,
enablePullUp: false,
controller: _refreshController,
onRefresh: () {
loadData();
},
onLoading: () {},
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Selector<AppGeneralManager, List<ATIndexBannerRes>>(
selector:
(_, provider) => List<ATIndexBannerRes>.unmodifiable(
provider.exploreBanners,
),
builder: (context, exploreBanners, child) {
return _banner(exploreBanners);
},
),
Selector<AppGeneralManager, ATBannerLeaderboardRes?>(
selector: (_, provider) => provider.appLeaderResult,
builder: (context, appLeaderResult, child) {
return _banner2(appLeaderResult);
},
),
_buildCountryTabs(),
rooms.isEmpty
? GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
loadData();
},
child:
isLoading
? Center(child: CupertinoActivityIndicator())
: mainEmpty(
msg: ATAppLocalizations.of(context)!.noData,
),
)
: Selector<AppGeneralManager, List<ATIndexBannerRes>>(
selector:
(_, provider) =>
List<ATIndexBannerRes>.unmodifiable(
provider.roomListBanners,
),
builder: (context, roomListBanners, child) {
return ListView.separated(
shrinkWrap: true,
padding: EdgeInsets.symmetric(vertical: 8.w),
physics: const NeverScrollableScrollPhysics(),
itemCount: _partyRoomListItemCount(roomListBanners),
itemBuilder: (context, index) {
if (_isPartyBannerIndex(index, roomListBanners)) {
return _buildPartyBanner(roomListBanners);
}
final roomIndex = _roomIndexForListIndex(
index,
roomListBanners,
);
return _buildItem(rooms[roomIndex], roomIndex);
},
separatorBuilder: (
BuildContext context,
int index,
) {
return SizedBox(height: 4.w);
},
);
},
),
],
),
),
),
],
),
);
}
bool _shouldShowPartyBanner(List<ATIndexBannerRes> roomListBanners) {
return rooms.length >= 3 && roomListBanners.isNotEmpty;
}
int _partyRoomListItemCount(List<ATIndexBannerRes> roomListBanners) {
return rooms.length + (_shouldShowPartyBanner(roomListBanners) ? 1 : 0);
}
bool _isPartyBannerIndex(int index, List<ATIndexBannerRes> roomListBanners) {
return _shouldShowPartyBanner(roomListBanners) && index == 3;
}
int _roomIndexForListIndex(
int index,
List<ATIndexBannerRes> roomListBanners,
) {
return _shouldShowPartyBanner(roomListBanners) && index > 3
? index - 1
: index;
}
Widget _buildPartyBanner(List<ATIndexBannerRes> roomListBanners) {
return SizedBox(
height: 97.w,
child: Container(
margin: EdgeInsetsDirectional.symmetric(horizontal: 17.w),
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12.w)),
child: CarouselSlider(
options: CarouselOptions(
height: 97.w,
autoPlay: false,
enlargeCenterPage: false,
enableInfiniteScroll: roomListBanners.length > 1,
viewportFraction: 1,
),
items:
roomListBanners.map((item) {
return _buildPartyBannerRemoteItem(item);
}).toList(),
),
),
);
}
Widget _buildPartyBannerRemoteItem(ATIndexBannerRes item) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
child: netImage(
url: item.cover ?? "",
width: double.infinity,
height: 97.w,
fit: BoxFit.cover,
borderRadius: BorderRadius.circular(12.w),
),
onTap: () {
ATBannerUtils.openBanner(item, context);
},
);
}
_banner(List<ATIndexBannerRes> exploreBanners) {
return Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
Container(
margin: EdgeInsets.symmetric(horizontal: 17.w),
child: CarouselSlider(
options: CarouselOptions(
height: 98.w,
autoPlay: true,
// 启用自动播放
enlargeCenterPage: false,
// 居中放大当前页面
enableInfiniteScroll: true,
// 启用无限循环
autoPlayAnimationDuration: Duration(milliseconds: 800),
// 自动播放动画时长
viewportFraction: 1,
// 视口分数
onPageChanged: (index, reason) {
_currentIndex = index;
setState(() {});
},
),
items:
exploreBanners.map((item) {
return GestureDetector(
child: netImage(
url: item.cover ?? "",
height: 98.w,
width: ScreenUtil().screenWidth * 0.9,
fit: BoxFit.contain,
borderRadius: BorderRadius.circular(12.w),
),
onTap: () {
print('ads:${item.toJson()}');
ATBannerUtils.openBanner(item, context);
},
);
}).toList(),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children:
exploreBanners.asMap().entries.map((entry) {
return Container(
width: 6.0,
height: 6.0,
margin: EdgeInsets.symmetric(vertical: 15.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color:
_currentIndex == entry.key ? Colors.blue : Colors.white,
),
);
}).toList(),
),
],
);
}
_banner2(ATBannerLeaderboardRes? appLeaderResult) {
String avatarAt(List<LeaderboardUser>? users, int index) {
if (users == null || users.length <= index) return "";
return users[index].avatar ?? "";
}
final roomGiftWeekly = appLeaderResult?.roomGiftsLeaderboard?.weekly;
final wealthWeekly = appLeaderResult?.giftsSendLeaderboard?.weekly;
final charmWeekly = appLeaderResult?.giftsReceivedLeaderboard?.weekly;
final roomGiftOneAvatar = avatarAt(roomGiftWeekly, 0);
final roomGiftTwoAvatar = avatarAt(roomGiftWeekly, 1);
final roomGiftThreeAvatar = avatarAt(roomGiftWeekly, 2);
final wealthOneAvatar = avatarAt(wealthWeekly, 0);
final wealthTwoAvatar = avatarAt(wealthWeekly, 1);
final wealthThreeAvatar = avatarAt(wealthWeekly, 2);
final charmOneAvatar = avatarAt(charmWeekly, 0);
final charmTwoAvatar = avatarAt(charmWeekly, 1);
final charmThreeAvatar = avatarAt(charmWeekly, 2);
return SizedBox(
height: 120.w,
child: Row(
children: [
Expanded(
child: GestureDetector(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
PositionedDirectional(
start: 30.w,
top: 63.w,
child: head(url: wealthTwoAvatar, width: 28.w),
),
Positioned(
top: 35.w,
child: head(url: wealthOneAvatar, width: 36.w),
),
PositionedDirectional(
end: 30.w,
top: 63.w,
child: head(url: wealthThreeAvatar, width: 28.w),
),
Image.asset(
ATGlobalConfig.businessLogicStrategy
.getPopularLeaderboardBackgroundImage('wealth'),
fit: BoxFit.fill,
),
],
),
onTap: () {
ATNavigatorUtils.push(
context,
"${MainRoute.webViewPage}?url=${Uri.encodeComponent(ATGlobalConfig.wealthRankUrl)}&showTitle=false",
replace: false,
);
},
),
),
Expanded(
child: GestureDetector(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
PositionedDirectional(
start: 28.w,
top: 68.w,
child: head(url: roomGiftTwoAvatar, width: 28.w),
),
Positioned(
top: 35.w,
child: head(url: roomGiftOneAvatar, width: 38.w),
),
PositionedDirectional(
end: 29.w,
top: 68.w,
child: head(url: roomGiftThreeAvatar, width: 28.w),
),
Image.asset(
ATGlobalConfig.businessLogicStrategy
.getPopularLeaderboardBackgroundImage('room'),
fit: BoxFit.fill,
),
],
),
onTap: () {
ATNavigatorUtils.push(
context,
"${MainRoute.webViewPage}?url=${Uri.encodeComponent(ATGlobalConfig.roomRankUrl)}&showTitle=false",
replace: false,
);
},
),
),
Expanded(
child: GestureDetector(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
PositionedDirectional(
start: 28.w,
top: 66.w,
child: head(url: charmTwoAvatar, width: 28.w),
),
Positioned(
top: 38.w,
child: head(url: charmOneAvatar, width: 37.w),
),
PositionedDirectional(
end: 31.w,
top: 66.w,
child: head(url: charmThreeAvatar, width: 28.w),
),
Image.asset(
ATGlobalConfig.businessLogicStrategy
.getPopularLeaderboardBackgroundImage('charm'),
fit: BoxFit.fill,
),
],
),
onTap: () {
ATNavigatorUtils.push(
context,
"${MainRoute.webViewPage}?url=${Uri.encodeComponent(ATGlobalConfig.charmRankUrl)}&showTitle=false",
replace: false,
);
},
),
),
],
),
);
}
Widget _buildCountryTabs() {
_syncCountryTabKeys();
return Container(
height: 32.w,
margin: EdgeInsetsDirectional.only(start: 18.w, end: 18.w, top: 4.w),
child: Row(
children: [
Expanded(
child: SingleChildScrollView(
controller: _countryTabController,
scrollDirection: Axis.horizontal,
physics: const BouncingScrollPhysics(),
child: Row(
children: [
KeyedSubtree(key: _countryTabKeys[0], child: _buildHotTab()),
...List.generate(_countries.length, (index) {
final country = _countries[index];
return KeyedSubtree(
key: _countryTabKeys[index + 1],
child: _buildCountryTab(country, index + 1),
);
}),
],
),
),
),
SizedBox(width: 8.w),
ATDebounceWidget(
onTap: _showCountrySheet,
child: Container(
alignment: Alignment.center,
height: 23.w,
width: 23.w,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: const Color(0xff000000), width: 1.w),
),
child: Icon(
Icons.keyboard_arrow_down_rounded,
size: 18.w,
color: const Color(0xff333333),
),
),
),
],
),
);
}
Widget _buildHotTab() {
final isSelected = _selectedCountry == null;
return Padding(
padding: EdgeInsetsDirectional.only(end: 6.w),
child: ATDebounceWidget(
onTap: () => _selectCountry(null, 0),
child: Container(
height: 32.w,
padding: EdgeInsetsDirectional.symmetric(horizontal: 13.w),
decoration: _countryTabDecoration(isSelected),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
"atu_images/index/at_icon_fire_department.png",
height: 19.w,
),
SizedBox(width: 3.w),
text(
ATAppLocalizations.of(context)!.hot,
textColor: const Color(0xff333333),
fontSize: 14.sp,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
lineHeight: 1.1,
),
],
),
),
),
);
}
Widget _buildCountryTab(Country country, int tabIndex) {
final isSelected = _isSameCountry(_selectedCountry, country);
return Padding(
padding: EdgeInsetsDirectional.only(end: 6.w),
child: ATDebounceWidget(
onTap: () => _selectCountry(country, tabIndex),
child: Container(
height: 32.w,
constraints: BoxConstraints(maxWidth: 144.w),
padding: EdgeInsetsDirectional.only(start: 6.w, end: 6.w),
decoration: _countryTabDecoration(isSelected),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
_buildCountryFlag(country, width: 22.w, height: 16.w),
SizedBox(width: 6.w),
Flexible(
child: text(
_countryDisplayName(country),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textColor:
isSelected
? const Color(0xff333333)
: const Color(0xff333333),
fontSize: 14.sp,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
lineHeight: 1.1,
),
),
],
),
),
),
);
}
BoxDecoration _countryTabDecoration(bool isSelected) {
return BoxDecoration(
color: isSelected ? null : const Color(0xffeeeeee),
gradient:
isSelected
? const LinearGradient(
colors: [Color(0xffffd800), Color(0xffff9500)],
begin: AlignmentDirectional.topCenter,
end: AlignmentDirectional.bottomCenter,
)
: null,
borderRadius: BorderRadius.circular(40.w),
);
}
Widget _buildCountryFlag(
Country country, {
required double width,
required double height,
}) {
final flag = country.nationalFlag ?? "";
if (flag.isEmpty) {
return Container(
width: width,
height: height,
decoration: BoxDecoration(
color: const Color(0xffd9d9d9),
borderRadius: BorderRadius.circular(3.w),
),
);
}
return netImage(
url: flag,
width: width,
height: height,
fit: BoxFit.cover,
borderRadius: BorderRadius.circular(3.w),
noDefaultImg: true,
);
}
void _showCountrySheet() {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
barrierColor: const Color(0x73000000),
isScrollControlled: true,
builder: (sheetContext) {
return SafeArea(
top: false,
child: Container(
constraints: BoxConstraints(
maxHeight: ScreenUtil().screenHeight * 0.6,
),
padding: EdgeInsetsDirectional.only(
start: 20.w,
end: 20.w,
top: 20.w,
bottom: MediaQuery.of(sheetContext).padding.bottom + 20.w,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadiusDirectional.vertical(
top: Radius.circular(20.w),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
text(
ATAppLocalizations.of(context)!.selectCountry,
textColor: const Color(0xff333333),
fontWeight: FontWeight.w700,
lineHeight: 1.1,
fontSize: 18.sp,
),
SizedBox(height: 20.w),
Flexible(
child:
_countries.isEmpty
? Center(
child:
_countryLoading
? const CupertinoActivityIndicator()
: mainEmpty(
msg:
ATAppLocalizations.of(
context,
)!.noData,
),
)
: GridView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const BouncingScrollPhysics(),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 12.w,
crossAxisSpacing: 8.w,
childAspectRatio: 111 / 30,
),
itemCount: _countries.length,
itemBuilder: (context, index) {
final country = _countries[index];
return _buildCountrySheetItem(
country,
index + 1,
sheetContext,
);
},
),
),
],
),
),
);
},
);
}
Widget _buildCountrySheetItem(
Country country,
int tabIndex,
BuildContext sheetContext,
) {
final isSelected = _isSameCountry(_selectedCountry, country);
return ATDebounceWidget(
onTap: () {
Navigator.of(sheetContext).pop();
_selectCountry(country, tabIndex);
},
child: Container(
height: 30.w,
padding: EdgeInsetsDirectional.symmetric(horizontal: 10.w),
decoration: BoxDecoration(
color: isSelected ? null : const Color(0xfff2f2f2),
gradient:
isSelected
? const LinearGradient(
colors: [Color(0xffffd800), Color(0xffff9500)],
begin: AlignmentDirectional.topCenter,
end: AlignmentDirectional.bottomCenter,
)
: null,
borderRadius: BorderRadius.circular(8.w),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildCountryFlag(country, width: 18.w, height: 12.w),
SizedBox(width: 6.w),
Flexible(
child: Text(
_countryDisplayName(country),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: const Color(0xff333333),
fontSize: 13.sp,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w500,
decoration: TextDecoration.none,
height: 1.1,
),
),
),
],
),
),
);
}
void _selectCountry(Country? country, int tabIndex) {
if (_isSameCountry(_selectedCountry, country)) {
_scrollCountryTabToIndex(tabIndex);
return;
}
setState(() {
_selectedCountry = country;
rooms = [];
});
_scrollCountryTabToIndex(tabIndex);
loadData();
}
void _scrollCountryTabToIndex(int tabIndex) {
if (tabIndex < 0 || tabIndex >= _countryTabKeys.length) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
final tabContext = _countryTabKeys[tabIndex].currentContext;
if (tabContext == null) return;
Scrollable.ensureVisible(
tabContext,
duration: const Duration(milliseconds: 250),
curve: Curves.easeOut,
alignment: 0.5,
);
});
}
void _syncCountryTabKeys() {
final total = _countries.length + 1;
while (_countryTabKeys.length < total) {
_countryTabKeys.add(GlobalKey());
}
if (_countryTabKeys.length > total) {
_countryTabKeys.removeRange(total, _countryTabKeys.length);
}
}
bool _isSameCountry(Country? left, Country? right) {
if (left == null || right == null) return left == right;
final leftKey = left.id ?? left.alphaTwo ?? left.countryName;
final rightKey = right.id ?? right.alphaTwo ?? right.countryName;
return leftKey == rightKey;
}
String _countryDisplayName(Country country) {
return country.countryName ?? "";
}
void loadCountries() {
_countryLoading = true;
ChatRoomRepository()
.roomLiveVoiceCountry()
.then((values) {
if (!mounted) return;
setState(() {
_countries = values;
_countryLoading = false;
});
})
.catchError((_) {
if (!mounted) return;
setState(() {
_countryLoading = false;
});
});
}
loadData() {
final requestToken = ++_dataRequestToken;
final selectedCountry = _selectedCountry;
setState(() {
isLoading = true;
});
ATLoadingManager.exhibitOperation();
final Future<List<ChatVibeRoomRes>> request =
selectedCountry == null
? ChatRoomRepository().discovery()
: ChatRoomRepository().roomLiveVoiceExplore(
countryCode: selectedCountry.countryCode,
);
request
.then((values) {
if (!mounted || requestToken != _dataRequestToken) return;
rooms = values;
isLoading = false;
_refreshController.refreshCompleted();
_refreshController.loadComplete();
ATLoadingManager.veilRoutine();
if (mounted) setState(() {});
})
.catchError((e) {
if (!mounted || requestToken != _dataRequestToken) return;
_refreshController.loadNoData();
_refreshController.refreshCompleted();
ATLoadingManager.veilRoutine();
isLoading = false;
if (mounted) setState(() {});
});
Provider.of<AppGeneralManager>(context, listen: false).loadMainBanner();
Provider.of<AppGeneralManager>(context, listen: false).appLeaderboard();
}
String getRoomCoverHeaddress(ChatVibeRoomRes roomRes) {
var vip = roomRes.userProfile?.getVIP();
if (vip?.name == ATVIPType.DUKE.name) {
return "atu_images/vip/at_icon_vip4_room_cover_headdress.png";
} else if (vip?.name == ATVIPType.KING.name) {
return "atu_images/vip/at_icon_vip5_room_cover_headdress.png";
} else if (vip?.name == ATVIPType.EMPEROR.name) {
return "atu_images/vip/at_icon_vip6_room_cover_headdress.png";
}
return "";
}
_buildItem(ChatVibeRoomRes res, int index) {
return ATDebounceWidget(
child: SizedBox(
height: 105.w,
child: Stack(
alignment: Alignment.center,
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(13.w),
border:
index < 3
? null
: Border.all(
color:
ATGlobalConfig.businessLogicStrategy
.getExploreRoomBorderColor(),
width:
ATGlobalConfig.businessLogicStrategy
.getExploreRoomBorderWidth()
.w,
),
),
margin: EdgeInsetsDirectional.symmetric(
horizontal: 18.w,
vertical: 5.w,
),
child: Row(
children: [
Stack(
children: [
netImage(
url: res.roomCover ?? "",
fit: BoxFit.cover,
borderRadius: BorderRadius.all(Radius.circular(12.w)),
width: 95.w,
height: 95.w,
),
PositionedDirectional(
top: 3.w,
end: 5.w,
child:
(res.extValues?.roomSetting?.password?.isNotEmpty ??
false)
? Image.asset(
"atu_images/index/at_icon_room_suo.png",
width: 16.w,
height: 16.w,
)
: Container(),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15.w),
Row(
children: [
SizedBox(width: 8.w),
ATCountryFlagImage(
countryName: res.countryName,
width: 25.w,
height: 15.w,
borderRadius: BorderRadius.all(
Radius.circular(3.w),
),
),
SizedBox(width: 5.w),
Container(
constraints: BoxConstraints(
maxHeight: 21.w,
maxWidth: 150.w,
),
child:
(res.roomName?.length ?? 0) >
ATGlobalConfig.businessLogicStrategy
.getExploreRoomNameMarqueeThreshold()
? Marquee(
text: res.roomName ?? "",
style: TextStyle(
fontSize: 15.sp,
color: Colors.black,
decoration: TextDecoration.none,
),
scrollAxis: Axis.horizontal,
crossAxisAlignment:
CrossAxisAlignment.start,
blankSpace: 20.0,
velocity: 40.0,
pauseAfterRound: Duration(seconds: 1),
accelerationDuration: Duration(
seconds: 1,
),
accelerationCurve: Curves.easeOut,
decelerationDuration: Duration(
milliseconds: 500,
),
decelerationCurve: Curves.easeOut,
)
: Text(
res.roomName ?? "",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 15.sp,
color: Colors.black,
decoration: TextDecoration.none,
),
),
),
],
),
SizedBox(height: 3.w),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(width: 8.w),
text(
"ID:${res.userProfile?.getID()}",
fontWeight: FontWeight.w600,
textColor: Colors.black,
fontSize: 15.sp,
),
],
),
SizedBox(height: 3.w),
Container(
constraints: BoxConstraints(maxWidth: 180.w),
margin: EdgeInsetsDirectional.symmetric(
horizontal: 8.w,
),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
spacing: 2.w,
children: List.generate(
(res.onlineUsers?.length ?? 0),
(index) {
return netImage(
url: res.onlineUsers?[index].userAvatar ?? "",
width: 23.w,
height: 23.w,
shape: BoxShape.circle,
);
},
),
),
),
),
],
),
],
),
),
index < 3
? IgnorePointer(
child: Transform.translate(
offset: Offset(0, -3),
child: Image.asset(
ATGlobalConfig.businessLogicStrategy
.getExploreRankIconPattern(false, index + 1),
fit: BoxFit.fill,
),
),
)
: Container(),
PositionedDirectional(
end: 35.w,
bottom: 25.w,
child: Row(
children: [
Image.asset(
"atu_images/index/at_icon_room_flot_ani.gif",
width: 14.w,
height: 14.w,
),
text(
res.extValues?.memberQuantity ?? "0",
textColor: Colors.black38,
fontSize: 11.sp,
),
],
),
),
],
),
),
onTap: () {
Provider.of<RtcProvider>(
context,
listen: false,
).joinRoom(context, res.id ?? "");
},
);
}
}