skywood/lib/pages/home/cate_page.dart

319 lines
8.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:skywood/global/client/play_client.dart';
import 'package:skywood/main/lib_file.dart';
import 'package:skywood/pages/home/players/page/drama_detail_page.dart';
import 'package:skywood/utils/models/drama/skywood_category.dart';
import 'package:skywood/utils/models/drama/skywood_drama.dart';
import 'package:skywood/utils/tools/sky_time_tool.dart';
import 'package:skywood/utils/tools/widgets/sky_common_widget.dart';
class CatePage extends StatefulWidget {
const CatePage({super.key});
@override
State<CatePage> createState() => _CatePageState();
}
class _CatePageState extends State<CatePage> {
final List<SkywoodCategory> _categories = [];
final List<SkywoodDrama> _dramas = [];
int _selectedIndex = 0;
int? _loadingCategoryId;
bool _loadingCategories = true;
bool _loadingDramas = false;
@override
void initState() {
super.initState();
_loadCategories();
}
Future<void> _loadCategories() async {
List<SkywoodCategory> categories = [];
try {
categories = await PlayClient.getCategoriesList();
} catch (_) {
if (!mounted) return;
}
setState(() {
_categories
..clear()
..addAll(categories);
_loadingCategories = false;
});
if (categories.isNotEmpty) {
_loadCategoryDetail(categories.first.id);
}
}
Future<void> _loadCategoryDetail(int categoryId) async {
_loadingCategoryId = categoryId;
setState(() {
_loadingDramas = true;
_dramas.clear();
});
List<SkywoodDrama> dramas = [];
try {
dramas = await PlayClient.getCategoriesDetail(categoryId: categoryId);
} catch (_) {
if (!mounted || _loadingCategoryId != categoryId) return;
}
if (!mounted || _loadingCategoryId != categoryId) return;
setState(() {
_dramas.addAll(dramas);
_loadingDramas = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
bottom: false,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildCategoryList(),
Expanded(child: _buildDramaList()),
],
),
),
],
),
),
);
}
Widget _buildHeader() {
return SizedBox(
height: 49.h,
child: Stack(
children: [
Positioned(
left: 13.w,
top: 16.h,
child: HelpImg.asset(
ConstImg.back,
width: 24.w,
height: 24.w,
).addInkWell(onTap: () => HelpNav.back()),
),
Positioned(
left: 94.w,
top: 22.h,
child: SkyText(
text: 'Explore Genres',
color: CommonColor.black,
fontSize: 14,
fontWeight: FontWeight.w800,
),
),
],
),
);
}
Widget _buildCategoryList() {
return Container(
width: 86.w,
height: double.infinity,
padding: EdgeInsets.only(top: 12.h, bottom: 18.h),
decoration: BoxDecoration(
color: const Color(0xFFF2FFF0),
borderRadius: BorderRadius.only(topRight: Radius.circular(8.r)),
),
child: _loadingCategories
? const SizedBox.shrink()
: ListView.builder(
padding: EdgeInsets.zero,
itemCount: _categories.length,
itemBuilder: (context, index) {
return _buildCategoryItem(index);
},
),
);
}
Widget _buildCategoryItem(int index) {
final category = _categories[index];
final selected = index == _selectedIndex;
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
if (selected) return;
setState(() {
_selectedIndex = index;
});
_loadCategoryDetail(category.id);
},
child: SizedBox(
height: 47.h,
child: Stack(
alignment: Alignment.center,
children: [
if (selected)
Positioned(
left: 0,
top: 0,
bottom: 0,
child: HelpImg.asset(
ConstImg.cateSelLeft,
width: 20.w,
height: 50.h,
fit: BoxFit.fill,
),
),
if (selected)
Positioned(
right: 0,
top: 0,
bottom: 0,
child: HelpImg.asset(
ConstImg.cateSelRight,
width: 20.w,
height: 50.h,
fit: BoxFit.fill,
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.w),
child: SkyText(
text: category.name,
color: selected
? CommonColor.primacyColor
: Colors.black.withAlpha(100),
fontSize: 11,
fontWeight: selected ? FontWeight.w700 : FontWeight.w500,
textAlign: TextAlign.center,
maxLines: 2,
lineHeight: 1.05,
),
),
],
),
),
);
}
Widget _buildDramaList() {
if (_loadingDramas) {
return const Center(
child: CircularProgressIndicator(color: CommonColor.primacyColor),
);
}
if (_dramas.isEmpty) {
return Center(
child: SkyText(
text: 'No Data',
color: Colors.black.withAlpha(100),
fontSize: 13,
),
);
}
return ListView.separated(
padding: EdgeInsets.only(left: 8.w, right: 10.w, bottom: 24.h),
itemCount: _dramas.length,
separatorBuilder: (context, index) => SizedBox(height: 10.h),
itemBuilder: (context, index) {
return _DramaItem(drama: _dramas[index]);
},
);
}
}
class _DramaItem extends StatelessWidget {
const _DramaItem({required this.drama});
final SkywoodDrama drama;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 80.h,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
HelpImg.networkRadius(
drama.imageUrl,
width: 64.w,
height: 80.h,
fit: BoxFit.cover,
borderRadius: BorderRadius.circular(4.r),
),
SizedBox(width: 8.w),
Expanded(
child: Padding(
padding: EdgeInsets.only(top: 2.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SkyText(
text: drama.name,
color: CommonColor.black,
fontSize: 11,
fontWeight: FontWeight.w700,
maxLines: 2,
lineHeight: 1.08,
),
SizedBox(height: 7.h),
SkyText(
text: drama.description,
color: Colors.black.withAlpha(92),
fontSize: 9,
maxLines: 2,
lineHeight: 1.2,
),
const Spacer(),
Row(
children: [
_TipView(icon: ConstImg.star, text: '10.0'),
SizedBox(width: 12.w),
_TipView(
icon: ConstImg.look,
text: SkyTimeTool.formatNum(drama.watchTotal),
),
],
),
],
),
),
),
],
),
).addInkWell(onTap: () => HelpNav.to(DramaDetailPage(dramaBean: drama)));
}
}
class _TipView extends StatelessWidget {
const _TipView({required this.icon, required this.text});
final String icon;
final String text;
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
HelpImg.asset(icon, width: 8.w, height: 8.w),
SizedBox(width: 2.w),
SkyText(text: text, color: Colors.black.withAlpha(110), fontSize: 8),
],
);
}
}