mod: 我的收藏
This commit is contained in:
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/widgets/http_error.dart';
|
import 'package:pilipala/common/widgets/http_error.dart';
|
||||||
import 'package:pilipala/pages/fav/index.dart';
|
import 'package:pilipala/pages/fav/index.dart';
|
||||||
|
import 'package:pilipala/pages/fav/widgets/item.dart';
|
||||||
|
|
||||||
class FavPage extends StatefulWidget {
|
class FavPage extends StatefulWidget {
|
||||||
const FavPage({super.key});
|
const FavPage({super.key});
|
||||||
@ -18,7 +19,11 @@ class _FavPageState extends State<FavPage> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: const Text('我的收藏'),
|
titleSpacing: 0,
|
||||||
|
title: Text(
|
||||||
|
'我的收藏',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: FutureBuilder(
|
body: FutureBuilder(
|
||||||
future: _favController.queryFavFolder(),
|
future: _favController.queryFavFolder(),
|
||||||
@ -30,31 +35,9 @@ class _FavPageState extends State<FavPage> {
|
|||||||
() => ListView.builder(
|
() => ListView.builder(
|
||||||
itemCount: _favController.favFolderData.value.list!.length,
|
itemCount: _favController.favFolderData.value.list!.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
return FavItem(
|
||||||
onTap: () => Get.toNamed(
|
favFolderItem:
|
||||||
'/favDetail',
|
_favController.favFolderData.value.list![index]);
|
||||||
arguments:
|
|
||||||
_favController.favFolderData.value.list![index],
|
|
||||||
parameters: {
|
|
||||||
'mediaId': _favController
|
|
||||||
.favFolderData.value.list![index].id
|
|
||||||
.toString(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
leading: const Icon(Icons.folder_special_outlined),
|
|
||||||
minLeadingWidth: 0,
|
|
||||||
title: Text(_favController
|
|
||||||
.favFolderData.value.list![index].title!),
|
|
||||||
subtitle: Text(
|
|
||||||
'${_favController.favFolderData.value.list![index].mediaCount}个内容',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
fontSize: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.labelSmall!
|
|
||||||
.fontSize),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
96
lib/pages/fav/widgets/item.dart
Normal file
96
lib/pages/fav/widgets/item.dart
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:pilipala/common/constants.dart';
|
||||||
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
|
class FavItem extends StatelessWidget {
|
||||||
|
var favFolderItem;
|
||||||
|
FavItem({super.key, required this.favFolderItem});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String heroTag = Utils.makeHeroTag(favFolderItem.fid);
|
||||||
|
return InkWell(
|
||||||
|
onTap: () => Get.toNamed(
|
||||||
|
'/favDetail',
|
||||||
|
arguments: favFolderItem,
|
||||||
|
parameters: {
|
||||||
|
'heroTag': heroTag,
|
||||||
|
'mediaId': favFolderItem.id.toString(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(12, 7, 12, 7),
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, boxConstraints) {
|
||||||
|
double width =
|
||||||
|
(boxConstraints.maxWidth - StyleString.cardSpace * 6) / 2;
|
||||||
|
return SizedBox(
|
||||||
|
height: width / StyleString.aspectRatio,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
AspectRatio(
|
||||||
|
aspectRatio: StyleString.aspectRatio,
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, boxConstraints) {
|
||||||
|
double maxWidth = boxConstraints.maxWidth;
|
||||||
|
double maxHeight = boxConstraints.maxHeight;
|
||||||
|
double PR = MediaQuery.of(context).devicePixelRatio;
|
||||||
|
return Hero(
|
||||||
|
tag: heroTag,
|
||||||
|
child: NetworkImgLayer(
|
||||||
|
src: favFolderItem.cover + '@.webp',
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
VideoContent(favFolderItem: favFolderItem)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VideoContent extends StatelessWidget {
|
||||||
|
final favFolderItem;
|
||||||
|
const VideoContent({super.key, required this.favFolderItem});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 2, 6, 0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
favFolderItem.title,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context).textTheme.titleSmall!.fontSize,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${favFolderItem.mediaCount}个内容',
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,30 +4,42 @@ import 'package:pilipala/http/user.dart';
|
|||||||
import 'package:pilipala/http/video.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/user/fav_detail.dart';
|
import 'package:pilipala/models/user/fav_detail.dart';
|
||||||
import 'package:pilipala/models/user/fav_folder.dart';
|
import 'package:pilipala/models/user/fav_folder.dart';
|
||||||
import 'package:pilipala/utils/id_utils.dart';
|
|
||||||
|
|
||||||
class FavDetailController extends GetxController {
|
class FavDetailController extends GetxController {
|
||||||
FavFolderItemData? item;
|
FavFolderItemData? item;
|
||||||
Rx<FavDetailData> favDetailData = FavDetailData().obs;
|
Rx<FavDetailData> favDetailData = FavDetailData().obs;
|
||||||
|
|
||||||
int? mediaId;
|
int? mediaId;
|
||||||
|
late String heroTag;
|
||||||
|
int currentPage = 1;
|
||||||
|
bool isLoadingMore = false;
|
||||||
|
RxMap favInfo = {}.obs;
|
||||||
|
RxList<FavDetailItemData> favList = [FavDetailItemData()].obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
item = Get.arguments;
|
item = Get.arguments;
|
||||||
if (Get.parameters.keys.isNotEmpty) {
|
if (Get.parameters.keys.isNotEmpty) {
|
||||||
mediaId = int.parse(Get.parameters['mediaId']!);
|
mediaId = int.parse(Get.parameters['mediaId']!);
|
||||||
|
heroTag = Get.parameters['heroTag']!;
|
||||||
}
|
}
|
||||||
super.onInit();
|
super.onInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<dynamic> queryUserFavFolderDetail() async {
|
Future<dynamic> queryUserFavFolderDetail({type = 'init'}) async {
|
||||||
print('🐯🐯虎');
|
|
||||||
var res = await await UserHttp.userFavFolderDetail(
|
var res = await await UserHttp.userFavFolderDetail(
|
||||||
pn: 1,
|
pn: currentPage,
|
||||||
ps: 15,
|
ps: 20,
|
||||||
mediaId: mediaId!,
|
mediaId: mediaId!,
|
||||||
);
|
);
|
||||||
favDetailData.value = res['data'];
|
if (res['status']) {
|
||||||
|
favInfo.value = res['data'].info;
|
||||||
|
if (currentPage == 1 && type == 'init') {
|
||||||
|
favList.value = res['data'].medias;
|
||||||
|
} else if (type == 'onload') {
|
||||||
|
favList.addAll(res['data'].medias);
|
||||||
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,4 +61,8 @@ class FavDetailController extends GetxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
queryUserFavFolderDetail(type: 'onload');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,14 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
} else if (_controller.offset <= 160) {
|
} else if (_controller.offset <= 160) {
|
||||||
titleStreamC.add(false);
|
titleStreamC.add(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_controller.position.pixels >=
|
||||||
|
_controller.position.maxScrollExtent - 200) {
|
||||||
|
if (!_favDetailController.isLoadingMore) {
|
||||||
|
_favDetailController.isLoadingMore = true;
|
||||||
|
_favDetailController.onLoad();
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -109,9 +117,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
// mainAxisAlignment: MainAxisAlignment.center,
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
Hero(
|
||||||
width: 180,
|
tag: _favDetailController.heroTag,
|
||||||
height: 110,
|
|
||||||
child: NetworkImgLayer(
|
child: NetworkImgLayer(
|
||||||
width: 180,
|
width: 180,
|
||||||
height: 110,
|
height: 110,
|
||||||
@ -156,7 +163,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14),
|
padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14),
|
||||||
child: Obx(
|
child: Obx(
|
||||||
() => Text(
|
() => Text(
|
||||||
'共${_favDetailController.favDetailData.value.medias != null ? _favDetailController.favDetailData.value.medias!.length : '-'}条视频',
|
'共${_favDetailController.favInfo['media_count'] ?? '-'}条视频',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize:
|
fontSize:
|
||||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
@ -184,12 +191,9 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
() => SliverList(
|
() => SliverList(
|
||||||
delegate: SliverChildBuilderDelegate((context, index) {
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
return FavVideoCardH(
|
return FavVideoCardH(
|
||||||
videoItem: _favDetailController
|
videoItem: _favDetailController.favList[index],
|
||||||
.favDetailData.value.medias![index],
|
|
||||||
);
|
);
|
||||||
},
|
}, childCount: _favDetailController.favList.length),
|
||||||
childCount: _favDetailController
|
|
||||||
.favDetailData.value.medias!.length),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import 'package:get/get.dart';
|
|||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/models/user/fav_folder.dart';
|
import 'package:pilipala/models/user/fav_folder.dart';
|
||||||
import 'package:pilipala/pages/media/index.dart';
|
import 'package:pilipala/pages/media/index.dart';
|
||||||
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
class MediaPage extends StatelessWidget {
|
class MediaPage extends StatelessWidget {
|
||||||
const MediaPage({super.key});
|
const MediaPage({super.key});
|
||||||
@ -169,12 +170,14 @@ class FavFolderItem extends StatelessWidget {
|
|||||||
int? index;
|
int? index;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
String heroTag = Utils.makeHeroTag(item!.fid);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.only(left: index == 0 ? 20 : 0, right: 14),
|
margin: EdgeInsets.only(left: index == 0 ? 20 : 0, right: 14),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => Get.toNamed('/favDetail', arguments: item, parameters: {
|
onTap: () => Get.toNamed('/favDetail',
|
||||||
'mediaId': item!.id.toString(),
|
arguments: item,
|
||||||
}),
|
parameters: {'mediaId': item!.id.toString(), 'heroTag': heroTag}),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -199,10 +202,13 @@ class FavFolderItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (context, BoxConstraints box) {
|
builder: (context, BoxConstraints box) {
|
||||||
return NetworkImgLayer(
|
return Hero(
|
||||||
src: item!.cover,
|
tag: heroTag,
|
||||||
width: box.maxWidth,
|
child: NetworkImgLayer(
|
||||||
height: box.maxHeight,
|
src: item!.cover,
|
||||||
|
width: box.maxWidth,
|
||||||
|
height: box.maxHeight,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user