aslan-flutter/lib/chatvibe_features/home/game/at_index_game_page.dart
2026-07-01 18:25:58 +08:00

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,
);
}
}
}