skywood/lib/pages/home/players/page/drama_esp_page.dart

227 lines
6.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:skywood/main/lib_file.dart';
import 'package:skywood/utils/models/drama/skywood_detail.dart';
import 'package:skywood/utils/models/drama/skywood_drama.dart';
import 'package:skywood/utils/models/drama/skywood_episode.dart';
import 'package:skywood/utils/tools/widgets/sky_common_widget.dart';
class DramaEspPage extends StatefulWidget {
const DramaEspPage({super.key,
required this.detail,
this.currentEpisode,
this.onSelectedEpisode,
});
final SkywoodDetail detail;
final int? currentEpisode;
final Function(int)? onSelectedEpisode;
@override
State<StatefulWidget> createState() {
return _DramaEspPageState();
}
}
class _DramaEspPageState extends State<DramaEspPage> {
late int _selectedEpisode;
SkywoodDrama? get _drama =>
widget.detail.shortPlayInfo ?? widget.detail.videoInfo;
List<SkywoodEpisode> get _episodes => widget.detail.episodeList;
@override
void initState() {
super.initState();
_selectedEpisode = widget.currentEpisode ?? _drama?.episode ?? 1;
}
@override
Widget build(BuildContext context) {
final double height = 520;
return SizedBox(
width: AppScreen.screenWidth,
height: 520,
child: Stack(
children: [
HelpImg.asset(
ConstImg.espBg,
width: AppScreen.screenWidth,
height: height,
fit: BoxFit.fill,
),
Positioned.fill(
child: Padding(
padding: EdgeInsets.fromLTRB(22.w, 31.h, 22.w, 54.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildDramaInfo(),
SizedBox(height: 12),
Divider(
height: 1,
thickness: 0.5,
color: Colors.black.withAlpha(18),
),
SizedBox(height: 12),
SkyText(
text: '$_episodeTotal EP',
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.w500,
),
SizedBox(height: 8),
Expanded(child: _buildEpisodeGrid()),
],
),
),
),
],
),
);
}
Widget _buildDramaInfo() {
final SkywoodDrama? drama = _drama;
final SkywoodDrama? info = widget.detail.videoInfo;
final String imageUrl = drama?.imageUrl ?? '';
return SizedBox(
height: 130.h,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
HelpImg.networkRadius(
imageUrl,
width: 96.w,
height: 130.h,
fit: BoxFit.cover,
borderRadius: BorderRadius.circular(2),
),
SizedBox(width: 16.w),
Expanded(
child: Padding(
padding: EdgeInsets.only(top: 7.h),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SkyText(
text: drama?.name ?? '',
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w700,
maxLines: 2,
lineHeight: 1.12,
),
SizedBox(height: 10.h),
SkyText(
text: info?.description ?? '',
color: Colors.black.withAlpha(118),
fontSize: 14,
maxLines: 2,
lineHeight: 1.45,
),
SizedBox(height: 13.h),
_buildTag(),
],
),
),
),
],
),
);
}
Widget _buildTag() {
final String name = _drama?.categoryList?.isNotEmpty == true
? _drama!.categoryList!.first.name
: (_drama?.tagType ?? '');
if (name.isEmpty) return const SizedBox.shrink();
return Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 3.h),
decoration: BoxDecoration(
color: const Color(0xFFE7FFE5),
border: Border.all(color: const Color(0xFF86D57A), width: 1),
),
child: SkyText(
text: name,
color: Colors.black,
fontSize: 14,
overflow: TextOverflow.visible,
),
);
}
Widget _buildEpisodeGrid() {
if (_episodes.isEmpty) {
return const SizedBox.shrink();
}
return GridView.builder(
padding: EdgeInsets.zero,
physics: const BouncingScrollPhysics(),
itemCount: _episodes.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 5,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 61 / 50,
),
itemBuilder: (context, index) {
return _buildEpisodeItem(_episodes[index]);
},
);
}
Widget _buildEpisodeItem(SkywoodEpisode episode) {
final bool selected = episode.episode == _selectedEpisode;
final bool selectedPlayable = selected && !episode.isLock;
final bool selectedLocked = selected && episode.isLock;
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() {
_selectedEpisode = episode.episode;
});
widget.onSelectedEpisode?.call(_selectedEpisode);
},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: selectedPlayable
? const Color(0xFF91F476)
: const Color(0xFFF8F8F8),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: selectedPlayable
? Colors.black
: (selectedLocked
? CommonColor.primacyColor
: Colors.transparent),
width: selected ? 1 : 0,
),
),
child: Center(
child: SkyText(
text: episode.episode.toString(),
color: Colors.black.withAlpha(220),
fontSize: 20,
fontWeight: selected ? FontWeight.w700 : FontWeight.w400,
),
),
),
);
}
int get _episodeTotal {
if (_drama?.episodeTotal != null && _drama!.episodeTotal > 0) {
return _drama!.episodeTotal;
}
return _episodes.length;
}
}