From bafda1f0bdc09ee7ed1dc67542dd7f2c98138de7 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 23 Jul 2023 23:43:51 +0800 Subject: [PATCH] =?UTF-8?q?mod:=20=E6=88=91=E7=9A=84=E6=94=B6=E8=97=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/fav/view.dart | 35 +++-------- lib/pages/fav/widgets/item.dart | 96 +++++++++++++++++++++++++++++ lib/pages/favDetail/controller.dart | 28 +++++++-- lib/pages/favDetail/view.dart | 22 ++++--- lib/pages/media/view.dart | 20 +++--- 5 files changed, 153 insertions(+), 48 deletions(-) create mode 100644 lib/pages/fav/widgets/item.dart diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index 7a6b147c..f190bc85 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/pages/fav/index.dart'; +import 'package:pilipala/pages/fav/widgets/item.dart'; class FavPage extends StatefulWidget { const FavPage({super.key}); @@ -18,7 +19,11 @@ class _FavPageState extends State { return Scaffold( appBar: AppBar( centerTitle: false, - title: const Text('我的收藏'), + titleSpacing: 0, + title: Text( + '我的收藏', + style: Theme.of(context).textTheme.titleMedium, + ), ), body: FutureBuilder( future: _favController.queryFavFolder(), @@ -30,31 +35,9 @@ class _FavPageState extends State { () => ListView.builder( itemCount: _favController.favFolderData.value.list!.length, itemBuilder: (context, index) { - return ListTile( - onTap: () => Get.toNamed( - '/favDetail', - 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), - ), - ); + return FavItem( + favFolderItem: + _favController.favFolderData.value.list![index]); }, ), ); diff --git a/lib/pages/fav/widgets/item.dart b/lib/pages/fav/widgets/item.dart new file mode 100644 index 00000000..2a92eede --- /dev/null +++ b/lib/pages/fav/widgets/item.dart @@ -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, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/favDetail/controller.dart b/lib/pages/favDetail/controller.dart index 52ddebc8..24ecf3e3 100644 --- a/lib/pages/favDetail/controller.dart +++ b/lib/pages/favDetail/controller.dart @@ -4,30 +4,42 @@ import 'package:pilipala/http/user.dart'; import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/user/fav_detail.dart'; import 'package:pilipala/models/user/fav_folder.dart'; -import 'package:pilipala/utils/id_utils.dart'; class FavDetailController extends GetxController { FavFolderItemData? item; Rx favDetailData = FavDetailData().obs; + int? mediaId; + late String heroTag; + int currentPage = 1; + bool isLoadingMore = false; + RxMap favInfo = {}.obs; + RxList favList = [FavDetailItemData()].obs; @override void onInit() { item = Get.arguments; if (Get.parameters.keys.isNotEmpty) { mediaId = int.parse(Get.parameters['mediaId']!); + heroTag = Get.parameters['heroTag']!; } super.onInit(); } - Future queryUserFavFolderDetail() async { - print('🐯🐯虎'); + Future queryUserFavFolderDetail({type = 'init'}) async { var res = await await UserHttp.userFavFolderDetail( - pn: 1, - ps: 15, + pn: currentPage, + ps: 20, 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; } @@ -49,4 +61,8 @@ class FavDetailController extends GetxController { } } } + + onLoad() { + queryUserFavFolderDetail(type: 'onload'); + } } diff --git a/lib/pages/favDetail/view.dart b/lib/pages/favDetail/view.dart index ad7cdb99..88c2cb5f 100644 --- a/lib/pages/favDetail/view.dart +++ b/lib/pages/favDetail/view.dart @@ -34,6 +34,14 @@ class _FavDetailPageState extends State { } else if (_controller.offset <= 160) { 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 { // mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - width: 180, - height: 110, + Hero( + tag: _favDetailController.heroTag, child: NetworkImgLayer( width: 180, height: 110, @@ -156,7 +163,7 @@ class _FavDetailPageState extends State { padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14), child: Obx( () => Text( - '共${_favDetailController.favDetailData.value.medias != null ? _favDetailController.favDetailData.value.medias!.length : '-'}条视频', + '共${_favDetailController.favInfo['media_count'] ?? '-'}条视频', style: TextStyle( fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, @@ -184,12 +191,9 @@ class _FavDetailPageState extends State { () => SliverList( delegate: SliverChildBuilderDelegate((context, index) { return FavVideoCardH( - videoItem: _favDetailController - .favDetailData.value.medias![index], + videoItem: _favDetailController.favList[index], ); - }, - childCount: _favDetailController - .favDetailData.value.medias!.length), + }, childCount: _favDetailController.favList.length), ), ); } diff --git a/lib/pages/media/view.dart b/lib/pages/media/view.dart index 0860ddb9..43fa8ab0 100644 --- a/lib/pages/media/view.dart +++ b/lib/pages/media/view.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/user/fav_folder.dart'; import 'package:pilipala/pages/media/index.dart'; +import 'package:pilipala/utils/utils.dart'; class MediaPage extends StatelessWidget { const MediaPage({super.key}); @@ -169,12 +170,14 @@ class FavFolderItem extends StatelessWidget { int? index; @override Widget build(BuildContext context) { + String heroTag = Utils.makeHeroTag(item!.fid); + return Container( margin: EdgeInsets.only(left: index == 0 ? 20 : 0, right: 14), child: GestureDetector( - onTap: () => Get.toNamed('/favDetail', arguments: item, parameters: { - 'mediaId': item!.id.toString(), - }), + onTap: () => Get.toNamed('/favDetail', + arguments: item, + parameters: {'mediaId': item!.id.toString(), 'heroTag': heroTag}), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, @@ -199,10 +202,13 @@ class FavFolderItem extends StatelessWidget { ), child: LayoutBuilder( builder: (context, BoxConstraints box) { - return NetworkImgLayer( - src: item!.cover, - width: box.maxWidth, - height: box.maxHeight, + return Hero( + tag: heroTag, + child: NetworkImgLayer( + src: item!.cover, + width: box.maxWidth, + height: box.maxHeight, + ), ); }, ),