454 lines
15 KiB
Dart
454 lines
15 KiB
Dart
import 'dart:ui' as ui;
|
|
|
|
import 'package:aslan/app_localizations.dart';
|
|
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
|
|
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
|
|
import 'package:aslan/chatvibe_core/utilities/at_banner_utils.dart';
|
|
import 'package:aslan/chatvibe_core/utilities/at_loading_manager.dart';
|
|
import 'package:aslan/chatvibe_data/sources/repositories/config_repository_imp.dart';
|
|
import 'package:aslan/chatvibe_domain/models/res/at_get_list_game_config_res.dart';
|
|
import 'package:aslan/chatvibe_domain/models/res/at_index_banner_res.dart';
|
|
import 'package:aslan/chatvibe_features/index/main_route.dart';
|
|
import 'package:aslan/chatvibe_managers/app_general_manager.dart';
|
|
import 'package:aslan/chatvibe_ui/components/appbar/chatvibe_appbar.dart';
|
|
import 'package:aslan/chatvibe_ui/components/at_compontent.dart';
|
|
import 'package:carousel_slider/carousel_slider.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
|
|
|
import '../../../chatvibe_data/models/enum/at_game_origin_type.dart';
|
|
import '../../../chatvibe_data/sources/repositories/room_repository_imp.dart';
|
|
import '../../../chatvibe_domain/models/res/at_game_ranking_res.dart';
|
|
|
|
/// Game页面
|
|
class ATIndexGamePage extends StatefulWidget {
|
|
const ATIndexGamePage({super.key});
|
|
|
|
@override
|
|
State<ATIndexGamePage> createState() => _ATIndexGamePageState();
|
|
}
|
|
|
|
class _ATIndexGamePageState extends State<ATIndexGamePage> {
|
|
static const Color _panelBorderColor = Color(0xffEDB745);
|
|
static const Color _titleTextColor = Color(0xcc000000);
|
|
|
|
List<Records> games = [];
|
|
int _currentIndex = 0;
|
|
final RefreshController _refreshController = RefreshController(
|
|
initialRefresh: false,
|
|
);
|
|
List<ATGetListGameConfigRes> gameRecords = [];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
loadGames();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_refreshController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Stack(
|
|
children: [
|
|
Scaffold(
|
|
resizeToAvoidBottomInset: false,
|
|
backgroundColor: Colors.transparent,
|
|
appBar: ChatVibeStandardAppBar(
|
|
title: ATAppLocalizations.of(context)!.game,
|
|
actions: [],
|
|
showBackButton: false,
|
|
// leading: Transform.translate(
|
|
// offset: Offset(ATGlobalConfig.lang == "ar" ? -22.w : 22.w, 0),
|
|
// child: Transform.scale(
|
|
// scale: 1.43,
|
|
// child: GestureDetector(
|
|
// child: Consumer<ChatVibeUserProfileManager>(
|
|
// builder: (context, ref, child) {
|
|
// return netImage(
|
|
// url:
|
|
// AccountStorage()
|
|
// .getCurrentUser()
|
|
// ?.userProfile
|
|
// ?.userAvatar ??
|
|
// "",
|
|
// defaultImg:
|
|
// ATGlobalConfig.businessLogicStrategy
|
|
// .getMePageDefaultAvatarImage(),
|
|
// width: 32.w,
|
|
// height: 32.w,
|
|
// shape: BoxShape.circle,
|
|
// );
|
|
// },
|
|
// ),
|
|
// onTap: () {
|
|
// ATNavigatorUtils.push(
|
|
// context,
|
|
// "${MainRoute.person}?isMe=true&tageId=${AccountStorage().getCurrentUser()?.userProfile?.id}",
|
|
// );
|
|
// },
|
|
// ),
|
|
// ),
|
|
// ),
|
|
),
|
|
body: SmartRefresher(
|
|
enablePullDown: true,
|
|
enablePullUp: false,
|
|
controller: _refreshController,
|
|
onRefresh: () {
|
|
loadGames();
|
|
},
|
|
onLoading: () {},
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Selector<AppGeneralManager, List<ATIndexBannerRes>>(
|
|
selector:
|
|
(_, provider) => List<ATIndexBannerRes>.unmodifiable(
|
|
provider.gameBanners,
|
|
),
|
|
builder: (context, gameBanners, child) {
|
|
return _banner(gameBanners);
|
|
},
|
|
),
|
|
SizedBox(height: 5.w),
|
|
_buildPlayLogSection(context),
|
|
SizedBox(height: 12.w),
|
|
_buildAllGamesSection(context),
|
|
SizedBox(height: 20.w),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildPlayLogSection(BuildContext context) {
|
|
return _buildPanel(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
_buildSectionHeader(ATAppLocalizations.of(context)!.playLog),
|
|
SizedBox(height: 10.w),
|
|
Container(
|
|
height: 50.w,
|
|
padding: EdgeInsets.symmetric(horizontal: 12.w),
|
|
child:
|
|
gameRecords.isEmpty
|
|
? _buildCompactEmpty(context)
|
|
: LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
return SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
child: ConstrainedBox(
|
|
constraints: BoxConstraints(
|
|
minWidth: constraints.maxWidth,
|
|
),
|
|
child: Row(
|
|
spacing: 5.w,
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: List.generate(gameRecords.length, (
|
|
index,
|
|
) {
|
|
return _buildPlayLogItem(gameRecords[index]);
|
|
}),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
SizedBox(height: 10.w),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAllGamesSection(BuildContext context) {
|
|
return _buildPanel(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
_buildSectionHeader(
|
|
ATAppLocalizations.of(context)!.allGames,
|
|
showIndicator: true,
|
|
),
|
|
SizedBox(height: 10.w),
|
|
games.isEmpty
|
|
? Padding(
|
|
padding: EdgeInsets.only(bottom: 10.w),
|
|
child: _buildCompactEmpty(context),
|
|
)
|
|
: GridView.builder(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
padding: EdgeInsets.fromLTRB(10.w, 0, 10.w, 10.w),
|
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
|
crossAxisCount: 3,
|
|
childAspectRatio: 1,
|
|
mainAxisSpacing: 5.w,
|
|
crossAxisSpacing: 5.w,
|
|
),
|
|
itemCount: games.length,
|
|
itemBuilder: (context, index) {
|
|
return _buildGameGridItem(games[index]);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPanel({required Widget child}) {
|
|
return Container(
|
|
width: double.infinity,
|
|
margin: EdgeInsets.symmetric(horizontal: 10.w),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
border: Border.all(color: _panelBorderColor, width: 1.w),
|
|
borderRadius: BorderRadius.circular(12.w),
|
|
),
|
|
child: ClipRRect(borderRadius: BorderRadius.circular(1.w), child: child),
|
|
);
|
|
}
|
|
|
|
Widget _buildSectionHeader(String title, {bool showIndicator = false}) {
|
|
return Container(
|
|
height: 31.w,
|
|
width: double.infinity,
|
|
padding: EdgeInsets.symmetric(horizontal: 10.w),
|
|
child: Stack(
|
|
alignment: AlignmentDirectional.centerStart,
|
|
children: [
|
|
Text(
|
|
title,
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: TextStyle(
|
|
color: _titleTextColor,
|
|
fontSize: 16.sp,
|
|
fontWeight: FontWeight.w600,
|
|
decoration: TextDecoration.none,
|
|
),
|
|
),
|
|
if (showIndicator)
|
|
PositionedDirectional(
|
|
start: 31.w,
|
|
bottom: 1.w,
|
|
child: Container(
|
|
width: 15.w,
|
|
height: 3.w,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(22.w),
|
|
color: const Color(0xffFF9500),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPlayLogItem(ATGetListGameConfigRes game) {
|
|
return GestureDetector(
|
|
onTap: () {
|
|
openGame(game.gameOrigin ?? "", game.gameCode ?? "", game.id ?? "");
|
|
},
|
|
child: netImage(
|
|
url: game.cover ?? "",
|
|
width: 50.w,
|
|
height: 50.w,
|
|
fit: BoxFit.cover,
|
|
borderRadius: BorderRadius.circular(7.w),
|
|
border: Border.all(color: _panelBorderColor, width: 1.w),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildGameGridItem(Records game) {
|
|
return GestureDetector(
|
|
onTap: () {
|
|
openGame(game.gameOrigin ?? "", game.gameUrl ?? "", game.gameId ?? "");
|
|
},
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
SizedBox(
|
|
width: 105.w,
|
|
height: 105.w,
|
|
child: Stack(
|
|
fit: StackFit.expand,
|
|
clipBehavior: Clip.none,
|
|
children: [
|
|
netImage(
|
|
url: game.gameCover ?? "",
|
|
fit: BoxFit.cover,
|
|
borderRadius: BorderRadius.circular(14.w),
|
|
border: Border.all(color: _panelBorderColor, width: 2.w),
|
|
),
|
|
if (game.latest ?? false)
|
|
PositionedDirectional(
|
|
start: 4.w,
|
|
bottom: 2.w,
|
|
child: Image.asset(
|
|
ATGlobalConfig.businessLogicStrategy.getGameNewTagImage(),
|
|
height: 22.w,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildCompactEmpty(BuildContext context) {
|
|
return Center(
|
|
child: Text(
|
|
ATAppLocalizations.of(context)!.noData,
|
|
style: TextStyle(
|
|
color: Colors.black38,
|
|
fontSize: 12.sp,
|
|
fontWeight: FontWeight.w500,
|
|
decoration: TextDecoration.none,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
_banner(List<ATIndexBannerRes> gameBanners) {
|
|
return gameBanners.isEmpty
|
|
? Container()
|
|
: 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:
|
|
gameBanners.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:
|
|
gameBanners.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(),
|
|
),
|
|
],
|
|
);
|
|
;
|
|
}
|
|
|
|
void loadGames() {
|
|
ATLoadingManager.exhibitOperation();
|
|
games.clear();
|
|
gameRecords.clear();
|
|
Future.wait([
|
|
ChatRoomRepository().gameLudoHistoryRecent("OUT_ROOM"),
|
|
ConfigRepositoryImp().gameRanking(1, "WEEK", size: 110),
|
|
])
|
|
.then((result) {
|
|
gameRecords = result[0] as List<ATGetListGameConfigRes> ?? [];
|
|
games = (result[1] as ATGameRankingRes).records ?? [];
|
|
_refreshController.refreshCompleted();
|
|
_refreshController.loadComplete();
|
|
if (mounted) setState(() {});
|
|
ATLoadingManager.veilRoutine();
|
|
})
|
|
.catchError((e) {
|
|
_refreshController.loadNoData();
|
|
_refreshController.refreshCompleted();
|
|
if (mounted) setState(() {});
|
|
ATLoadingManager.veilRoutine();
|
|
});
|
|
Provider.of<AppGeneralManager>(context, listen: false).loadMainBanner();
|
|
}
|
|
|
|
void openGame(String gameOrigin, String gameUrl, String gameId) {
|
|
if (gameOrigin == ATGameOriginType.LINGXIAN.name) {
|
|
ATNavigatorUtils.push(
|
|
context,
|
|
"${MainRoute.gameLxWebviewPage}?url=${Uri.encodeComponent(gameUrl)}&gameId=$gameId&height=-1&width=-1",
|
|
replace: false,
|
|
);
|
|
} else if (gameOrigin == ATGameOriginType.BAISHUN.name) {
|
|
ATNavigatorUtils.push(
|
|
context,
|
|
"${MainRoute.gameBsWebviewPage}?url=${Uri.encodeComponent(gameUrl)}&gameId=$gameId&height=-1&width=-1",
|
|
replace: false,
|
|
);
|
|
} else if (gameOrigin == ATGameOriginType.HOTGAME.name) {
|
|
ATNavigatorUtils.push(
|
|
context,
|
|
"${MainRoute.gameRyWebviewPage}?url=${Uri.encodeComponent(gameUrl)}&gameId=$gameId&height=-1&width=-1",
|
|
replace: false,
|
|
);
|
|
} else if (gameOrigin == ATGameOriginType.YOMI.name) {
|
|
ATNavigatorUtils.push(
|
|
context,
|
|
"${MainRoute.gameYmWebviewPage}?url=${Uri.encodeComponent(gameUrl)}&gameId=$gameId&height=-1&width=-1",
|
|
replace: false,
|
|
);
|
|
}
|
|
}
|
|
}
|