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,110 @@
import 'package:PiliPlus/http/api.dart';
import 'package:PiliPlus/http/init.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/member.dart';
import 'package:PiliPlus/models/space_fav/datum.dart';
import 'package:PiliPlus/models/space_fav/list.dart';
import 'package:PiliPlus/pages/common/common_data_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
class MemberFavoriteCtr extends CommonDataController {
MemberFavoriteCtr({
required this.mid,
});
final int mid;
Rx<SpaceFavData> first = SpaceFavData().obs;
Rx<SpaceFavData> second = SpaceFavData().obs;
RxBool firstEnd = true.obs;
RxBool secondEnd = true.obs;
late int page = 2;
late int page1 = 2;
@override
void onInit() {
super.onInit();
queryData();
}
@override
Future onRefresh() {
page = 2;
page1 = 2;
return super.onRefresh();
}
@override
bool customHandleResponse(bool isRefresh, Success response) {
try {
List<SpaceFavData> res = response.response;
first.value = res.first;
second.value = res[1];
firstEnd.value = (res.first.mediaListResponse?.count ?? -1) <=
(res.first.mediaListResponse?.list?.length ?? -1);
secondEnd.value = (res[1].mediaListResponse?.count ?? -1) <=
(res[1].mediaListResponse?.list?.length ?? -1);
} catch (e) {
debugPrint(e.toString());
}
loadingState.value = response;
return true;
}
Future userfavFolder() async {
var res = await Request().get(Api.userFavFolder, queryParameters: {
'pn': page,
'ps': 20,
'up_mid': mid,
});
if (res.data['code'] == 0) {
page++;
firstEnd.value = res.data['data']['has_more'] == false;
if (res.data['data'] != null) {
List<FavList> list = (res.data['data']['list'] as List<dynamic>?)
?.map((item) => FavList.fromJson(item))
.toList() ??
<FavList>[];
first.value.mediaListResponse?.list?.addAll(list);
first.refresh();
} else {
firstEnd.value = true;
}
} else {
SmartDialog.showToast(res.data['message'] ?? '账号未登录');
}
}
Future userSubFolder() async {
var res = await Request().get(Api.userSubFolder, queryParameters: {
'up_mid': mid,
'ps': 20,
'pn': page1,
'platform': 'web',
});
if (res.data['code'] == 0) {
page++;
secondEnd.value = res.data['data']['has_more'] == false;
if (res.data['data'] != null) {
List<FavList> list = (res.data['data']['list'] as List<dynamic>?)
?.map((item) => FavList.fromJson(item))
.toList() ??
<FavList>[];
second.value.mediaListResponse?.list?.addAll(list);
second.refresh();
} else {
secondEnd.value = true;
}
} else {
SmartDialog.showToast(res.data['message'] ?? '账号未登录');
}
}
@override
Future<LoadingState> customGetData() => MemberHttp.spaceFav(mid: mid);
}

View File

@@ -0,0 +1,157 @@
import 'package:PiliPlus/common/widgets/loading_widget.dart';
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/space_fav/datum.dart';
import 'package:PiliPlus/models/space_fav/list.dart';
import 'package:PiliPlus/pages/member_favorite/controller.dart';
import 'package:PiliPlus/pages/member_favorite/widget/item.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class MemberFavorite extends StatefulWidget {
const MemberFavorite({
super.key,
required this.heroTag,
required this.mid,
});
final String? heroTag;
final int mid;
@override
State<MemberFavorite> createState() => _MemberFavoriteState();
}
class _MemberFavoriteState extends State<MemberFavorite>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
late final _controller = Get.put(
MemberFavoriteCtr(mid: widget.mid),
tag: widget.heroTag,
);
@override
Widget build(BuildContext context) {
super.build(context);
return Obx(() => _buildBody(_controller.loadingState.value));
}
_buildBody(LoadingState loadingState) {
final theme = Theme.of(context);
return switch (loadingState) {
Loading() => loadingWidget,
Success() => (loadingState.response as List?)?.isNotEmpty == true
? refreshIndicator(
onRefresh: () async {
await _controller.onRefresh();
},
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Obx(
() => _buildItem(theme, _controller.first.value, true),
),
),
SliverToBoxAdapter(
child: Obx(
() => _buildItem(theme, _controller.second.value, false),
),
),
SliverToBoxAdapter(
child: SizedBox(
height: 80 + MediaQuery.of(context).padding.bottom,
),
)
],
),
)
: scrollErrorWidget(
onReload: _controller.onReload,
),
Error() => scrollErrorWidget(
errMsg: loadingState.errMsg,
onReload: _controller.onReload,
),
};
}
_buildItem(ThemeData theme, SpaceFavData data, bool isFirst) {
return Theme(
data: theme.copyWith(
dividerColor: Colors.transparent,
),
child: ExpansionTile(
dense: true,
initiallyExpanded: true,
title: Text.rich(
TextSpan(
children: [
TextSpan(
text: data.name,
style: TextStyle(fontSize: 14),
),
TextSpan(
text: ' ${data.mediaListResponse?.count}',
style: TextStyle(
fontSize: 13,
color: theme.colorScheme.outline,
),
),
],
),
),
controlAffinity: ListTileControlAffinity.leading,
children: [
...(data.mediaListResponse?.list as List<FavList>).map(
(item) => SizedBox(
height: 98,
child: MemberFavItem(
item: item,
callback: (res) {
if (res == true) {
_controller.first.value.mediaListResponse?.list
?.remove(item);
_controller.first.refresh();
} else {
Future.delayed(const Duration(milliseconds: 100), () {
_controller.onRefresh();
});
}
},
),
),
),
Obx(
() => (isFirst
? _controller.firstEnd.value
: _controller.secondEnd.value)
? const SizedBox.shrink()
: _buildLoadMoreItem(theme, isFirst),
),
],
),
);
}
_buildLoadMoreItem(ThemeData theme, bool isFirst) {
return ListTile(
dense: true,
onTap: () {
if (isFirst) {
_controller.userfavFolder();
} else {
_controller.userSubFolder();
}
},
title: Text(
'查看更多内容',
textAlign: TextAlign.center,
style: TextStyle(
color: theme.colorScheme.primary,
),
),
);
}
}

View File

@@ -0,0 +1,151 @@
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/models/space_fav/list.dart';
import 'package:PiliPlus/models/user/sub_folder.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class MemberFavItem extends StatelessWidget {
const MemberFavItem({super.key, required this.item, this.callback});
final FavList item;
final ValueChanged<bool?>? callback;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () async {
if (item.state == 1) {
// invalid
return;
}
if (item.type == 0) {
dynamic res = await Get.toNamed(
'/favDetail',
parameters: {
'mediaId': item.id.toString(),
'heroTag': Utils.makeHeroTag(item.id),
},
);
callback?.call(res);
} else {
Get.toNamed(
'/subDetail',
arguments: SubFolderItemData(
type: item.type,
title: item.title,
cover: item.cover,
upper: Upper(
mid: item.upper?.mid,
name: item.upper?.name,
face: item.upper?.face,
),
mediaCount: item.mediaCount,
viewCount: item.viewCount,
),
parameters: {
'id': item.id.toString(),
'heroTag': Utils.makeHeroTag(item.id),
},
);
}
},
onLongPress: () {
imageSaveDialog(
title: item.title,
cover: item.cover,
);
},
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: (context, boxConstraints) {
return Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
src: item.cover,
width: boxConstraints.maxWidth,
height: boxConstraints.maxHeight,
),
if (item.type == 21)
PBadge(
right: 3,
bottom: 3,
text: '合集',
bold: false,
size: 'small',
)
else if (item.type == 0 || item.type == 11)
Positioned(
right: 3,
bottom: 3,
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: theme.colorScheme.primary,
),
child: Icon(
Icons.video_library_outlined,
size: 12,
color: theme.colorScheme.onPrimary,
),
),
),
],
);
},
),
),
const SizedBox(width: 10),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.title ?? '',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
const Spacer(),
Text(
item.type == 0
? '${item.mediaCount}个内容 · ${Utils.isPublicFavText(item.attr ?? 0)}'
: item.type == 11
? '${item.mediaCount}个内容 · ${item.upper?.name}'
: item.type == 21
? '创建者: ${item.upper?.name}\n${item.mediaCount}个视频 · ${Utils.numFormat(item.viewCount)}播放'
: '${item.mediaCount}个内容',
style: TextStyle(
fontSize: 12,
color: theme.colorScheme.outline,
),
),
],
),
),
],
),
),
),
);
}
}