refa: dir

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-05-03 13:57:47 +08:00
parent 57fa8b4f3e
commit 7f70ee5045
260 changed files with 748 additions and 967 deletions

View File

@@ -0,0 +1,40 @@
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/member.dart';
import 'package:PiliPlus/pages/common/common_list_controller.dart';
class SeasonSeriesController extends CommonListController {
SeasonSeriesController(this.mid);
final int mid;
int? count;
@override
void onInit() {
super.onInit();
queryData();
}
@override
List? getDataList(response) {
return ((response['seasons_list'] as List?) ?? []) +
((response['series_list'] as List?) ?? []);
}
@override
void checkIsEnd(int length) {
if (count != null && length >= count!) {
isEnd = true;
}
}
@override
bool customHandleResponse(bool isRefresh, Success response) {
count = response.response['page']?['total'];
return false;
}
@override
Future<LoadingState> customGetData() => MemberHttp.seasonSeriesList(
mid: mid,
pn: currentPage,
);
}

View File

@@ -0,0 +1,111 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/loading_widget.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/pages/member_season_series/controller.dart';
import 'package:PiliPlus/pages/member_season_series/widget/season_series_card.dart';
import 'package:PiliPlus/pages/member_video/view.dart';
import 'package:PiliPlus/pages/member_contribute/view.dart';
import 'package:PiliPlus/utils/grid.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class SeasonSeriesPage extends StatefulWidget {
const SeasonSeriesPage({
super.key,
required this.mid,
this.heroTag,
});
final int mid;
final String? heroTag;
@override
State<SeasonSeriesPage> createState() => _SeasonSeriesPageState();
}
class _SeasonSeriesPageState extends State<SeasonSeriesPage>
with AutomaticKeepAliveClientMixin {
late final _controller = Get.put(
SeasonSeriesController(widget.mid),
tag: widget.heroTag,
);
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
return Obx(() => _buildBody(_controller.loadingState.value));
}
Widget _buildBody(LoadingState<List<dynamic>?> loadingState) {
return switch (loadingState) {
Loading() => loadingWidget,
Success() => loadingState.response?.isNotEmpty == true
? CustomScrollView(
slivers: [
SliverPadding(
padding: EdgeInsets.only(
top: StyleString.safeSpace - 5,
bottom: MediaQuery.paddingOf(context).bottom + 80,
),
sliver: SliverGrid(
gridDelegate: Grid.videoCardHDelegate(context),
delegate: SliverChildBuilderDelegate(
(context, index) {
if (index == loadingState.response!.length - 1) {
_controller.onLoadMore();
}
dynamic item = loadingState.response![index];
return SeasonSeriesCard(
item: item,
onTap: () {
bool isSeason = item['meta']['season_id'] != null;
dynamic id = isSeason
? item['meta']['season_id']
: item['meta']['series_id'];
Get.to(
Scaffold(
appBar: AppBar(
title: Text(item['meta']['name']),
),
body: SafeArea(
top: false,
bottom: false,
child: MemberVideo(
type: isSeason
? ContributeType.season
: ContributeType.series,
heroTag: widget.heroTag,
mid: widget.mid,
seasonId: isSeason ? id : null,
seriesId: isSeason ? null : id,
title: item['meta']['name'],
),
),
),
);
},
);
},
childCount: loadingState.response!.length,
),
),
),
],
)
: scrollErrorWidget(
onReload: () {
_controller.onReload();
},
),
Error() => scrollErrorWidget(
errMsg: loadingState.errMsg,
onReload: () {
_controller.onReload();
},
),
};
}
}

View File

@@ -0,0 +1,102 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/badge.dart';
import 'package:PiliPlus/common/widgets/image_save.dart';
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart';
class SeasonSeriesCard extends StatelessWidget {
const SeasonSeriesCard({
super.key,
required this.item,
required this.onTap,
});
final dynamic item;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return InkWell(
onLongPress: () {
imageSaveDialog(
title: item['meta']['name'],
cover: item['meta']['cover'],
);
},
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: StyleString.safeSpace,
vertical: 5,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: StyleString.aspectRatio,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight;
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: item['meta']['cover'],
width: maxWidth,
height: maxHeight,
),
PBadge(
text:
'${item['meta']['season_id'] != null ? '合集' : '列表'}: ${item['meta']['total']}',
bottom: 6.0,
right: 6.0,
),
],
);
},
),
),
const SizedBox(width: 10),
videoContent(context),
],
),
),
);
}
Widget videoContent(context) {
final theme = Theme.of(context);
return Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item['meta']['name'],
textAlign: TextAlign.start,
style: TextStyle(
fontSize: theme.textTheme.bodyMedium!.fontSize,
height: 1.42,
letterSpacing: 0.3,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
const Spacer(),
Text(
Utils.dateFormat(item['meta']['ptime']),
maxLines: 1,
style: TextStyle(
fontSize: 12,
height: 1,
color: theme.colorScheme.outline,
overflow: TextOverflow.clip,
),
),
const Spacer(),
],
),
);
}
}