Files
PiliPlus/lib/pages/member_favorite/view.dart
bggRGjQaUbCoE 2d75d89825 feat: space opus
Closes #833

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-05-09 12:32:09 +08:00

162 lines
4.6 KiB
Dart

import 'package:PiliPlus/common/skeleton/video_card_h.dart';
import 'package:PiliPlus/common/widgets/loading_widget/http_error.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:PiliPlus/utils/grid.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);
final theme = Theme.of(context);
return refreshIndicator(
onRefresh: _controller.onRefresh,
child: CustomScrollView(
slivers: [Obx(() => _buildBody(theme, _controller.loadingState.value))],
),
);
}
Widget _buildBody(ThemeData theme, LoadingState loadingState) {
return switch (loadingState) {
Loading() => SliverGrid(
gridDelegate: Grid.videoCardHDelegate(context),
delegate: SliverChildBuilderDelegate(
(context, index) {
return const VideoCardHSkeleton();
},
childCount: 10,
),
),
Success() => (loadingState.response as List?)?.isNotEmpty == true
? SliverMainAxisGroup(
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,
),
),
],
)
: HttpError(
onReload: _controller.onReload,
),
Error() => HttpError(
errMsg: loadingState.errMsg,
onReload: _controller.onReload,
),
};
}
Theme _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: const 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();
}
},
),
),
),
Obx(
() => (isFirst
? _controller.firstEnd.value
: _controller.secondEnd.value)
? const SizedBox.shrink()
: _buildLoadMoreItem(theme, isFirst),
),
],
),
);
}
ListTile _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,
),
),
);
}
}