diff --git a/lib/http/user.dart b/lib/http/user.dart index 93b693c2..22421766 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -374,24 +374,25 @@ class UserHttp { } // 我的订阅 - static Future userSubFolder({ + static Future userSubFolder({ required int mid, required int pn, required int ps, }) async { - var res = await Request().get(Api.userSubFolder, queryParameters: { - 'up_mid': mid, - 'ps': ps, - 'pn': pn, - 'platform': 'web', - }); + var res = await Request().get( + Api.userSubFolder, + queryParameters: { + 'up_mid': mid, + 'ps': ps, + 'pn': pn, + 'platform': 'web', + }, + ); if (res.data['code'] == 0 && res.data['data'] is Map) { - return { - 'status': true, - 'data': SubFolderModelData.fromJson(res.data['data']) - }; + return LoadingState.success( + SubFolderModelData.fromJson(res.data['data']).list); } else { - return {'status': false, 'msg': res.data['message']}; + return LoadingState.error(res.data['message']); } } diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index 26fd5eba..f831188e 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -82,18 +82,23 @@ class _FavPageState extends State { Widget _buildBody(LoadingState loadingState) { return switch (loadingState) { - Loading() => SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( + Loading() => SliverPadding( + padding: + const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( mainAxisSpacing: StyleString.cardSpace, crossAxisSpacing: StyleString.safeSpace, maxCrossAxisExtent: Grid.maxRowWidth * 2, childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return const VideoCardHSkeleton(); - }, - childCount: 10, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return const VideoCardHSkeleton(); + }, + childCount: 10, + ), ), ), Success() => (loadingState.response as List?)?.isNotEmpty == true diff --git a/lib/pages/fav_detail/view.dart b/lib/pages/fav_detail/view.dart index e3611b4d..c739dee7 100644 --- a/lib/pages/fav_detail/view.dart +++ b/lib/pages/fav_detail/view.dart @@ -289,19 +289,23 @@ class _FavDetailPageState extends State { Widget _buildBody(LoadingState loadingState) { return switch (loadingState) { - Loading() => SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0, - ), - delegate: SliverChildBuilderDelegate( - (context, index) { - return const VideoCardHSkeleton(); - }, - childCount: 10, + Loading() => SliverPadding( + padding: + const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return const VideoCardHSkeleton(); + }, + childCount: 10, + ), ), ), Success() => (loadingState.response as List?)?.isNotEmpty == true @@ -356,9 +360,9 @@ class _FavDetailPageState extends State { }, ), Positioned( - top: 0, + top: 8, left: 12, - bottom: 0, + bottom: 8, child: IgnorePointer( child: LayoutBuilder( builder: (context, constraints) => diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index 10aad38d..d5ec1772 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -74,65 +74,63 @@ class FavVideoCardH extends StatelessWidget { }); }, onLongPress: onLongPress, - child: Column( - children: [ - Padding( - padding: - const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), - 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; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: videoItem.pic, - width: maxWidth, - height: maxHeight, - ), - ), - PBadge( - text: Utils.timeFormat(videoItem.duration!), - right: 6.0, - bottom: 6.0, - type: 'gray', - ), - if (videoItem.ogv != null) ...[ - PBadge( - text: videoItem.ogv['type_name'], - top: 6.0, - right: 6.0, - bottom: null, - left: null, - ), - ], - ], - ); - }, - ), - ), - videoContent(context) - ], + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: StyleString.cardSpace, + ), + 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; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: videoItem.pic, + width: maxWidth, + height: maxHeight, + ), + ), + PBadge( + text: Utils.timeFormat(videoItem.duration!), + right: 6.0, + bottom: 6.0, + type: 'gray', + ), + if (videoItem.ogv != null) ...[ + PBadge( + text: videoItem.ogv['type_name'], + top: 6.0, + right: 6.0, + bottom: null, + left: null, + ), + ], + ], + ); + }, + ), ), - ); - }, - ), - ), - ], + videoContent(context) + ], + ), + ); + }, + ), ), ); } diff --git a/lib/pages/history/view.dart b/lib/pages/history/view.dart index 5a9816ee..e5b5631c 100644 --- a/lib/pages/history/view.dart +++ b/lib/pages/history/view.dart @@ -148,19 +148,24 @@ class _HistoryPageState extends State { Widget _buildBody(LoadingState loadingState) { return switch (loadingState) { - Loading() => SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0, + Loading() => SliverPadding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, ), - delegate: SliverChildBuilderDelegate( - (context, index) { - return const VideoCardHSkeleton(); - }, - childCount: 10, + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return const VideoCardHSkeleton(); + }, + childCount: 10, + ), ), ), Success() => (loadingState.response as List?)?.isNotEmpty == true diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index c068be63..fe1c7578 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -160,148 +160,143 @@ class HistoryItem extends StatelessWidget { onChoose?.call(); } }, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.fromLTRB( - StyleString.safeSpace, 0, StyleString.safeSpace, 0), - 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, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: StyleString.cardSpace, + ), + 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: [ + Stack( children: [ - Stack( - children: [ - AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder( - builder: (context, boxConstraints) { - double maxWidth = boxConstraints.maxWidth; - double maxHeight = boxConstraints.maxHeight; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - radius: 12, - src: (videoItem.cover != '' - ? videoItem.cover - : videoItem.covers.first), - width: maxWidth, - height: maxHeight, - ), - ), - if (!BusinessType - .hiddenDurationType.hiddenDurationType - .contains(videoItem.history.business)) - PBadge( - text: videoItem.progress == -1 - ? '已看完' - : '${Utils.timeFormat(videoItem.progress!)}/${Utils.timeFormat(videoItem.duration!)}', - right: 6.0, - bottom: 8.0, - type: 'gray', - ), - // 右上角 - if (BusinessType.showBadge.showBadge - .contains( - videoItem.history.business) || - videoItem.history.business == - BusinessType.live.type) - PBadge( - text: videoItem.badge, - top: 6.0, - right: 6.0, - bottom: null, - left: null, - ), - ], - ); - }, - ), - ), - Positioned.fill( - child: AnimatedOpacity( - opacity: videoItem.checked ? 1 : 0, - duration: const Duration(milliseconds: 200), - child: Container( - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.black.withOpacity(0.6), - ), - child: SizedBox( - width: 34, - height: 34, - child: AnimatedScale( - scale: videoItem.checked ? 1 : 0, - duration: const Duration(milliseconds: 250), - curve: Curves.easeInOut, - child: IconButton( - tooltip: '取消选择', - style: ButtonStyle( - padding: WidgetStateProperty.all( - EdgeInsets.zero), - backgroundColor: - WidgetStateProperty.resolveWith( - (states) { - return Theme.of(context) - .colorScheme - .surface - .withOpacity(0.8); - }, - ), - ), - onPressed: () { - feedBack(); - onChoose?.call(); - }, - icon: Icon(Icons.done_all_outlined, - color: Theme.of(context) - .colorScheme - .primary), - ), + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder( + builder: (context, boxConstraints) { + double maxWidth = boxConstraints.maxWidth; + double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + radius: 12, + src: (videoItem.cover != '' + ? videoItem.cover + : videoItem.covers.first), + width: maxWidth, + height: maxHeight, ), ), + if (!BusinessType + .hiddenDurationType.hiddenDurationType + .contains(videoItem.history.business)) + PBadge( + text: videoItem.progress == -1 + ? '已看完' + : '${Utils.timeFormat(videoItem.progress!)}/${Utils.timeFormat(videoItem.duration!)}', + right: 6.0, + bottom: 8.0, + type: 'gray', + ), + // 右上角 + if (BusinessType.showBadge.showBadge + .contains(videoItem.history.business) || + videoItem.history.business == + BusinessType.live.type) + PBadge( + text: videoItem.badge, + top: 6.0, + right: 6.0, + bottom: null, + left: null, + ), + ], + ); + }, + ), + ), + Positioned.fill( + child: AnimatedOpacity( + opacity: videoItem.checked ? 1 : 0, + duration: const Duration(milliseconds: 200), + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.black.withOpacity(0.6), + ), + child: SizedBox( + width: 34, + height: 34, + child: AnimatedScale( + scale: videoItem.checked ? 1 : 0, + duration: const Duration(milliseconds: 250), + curve: Curves.easeInOut, + child: IconButton( + tooltip: '取消选择', + style: ButtonStyle( + padding: WidgetStateProperty.all( + EdgeInsets.zero), + backgroundColor: + WidgetStateProperty.resolveWith( + (states) { + return Theme.of(context) + .colorScheme + .surface + .withOpacity(0.8); + }, + ), + ), + onPressed: () { + feedBack(); + onChoose?.call(); + }, + icon: Icon(Icons.done_all_outlined, + color: Theme.of(context) + .colorScheme + .primary), + ), ), ), ), - if (videoItem.duration != null && - videoItem.duration != 0 && - videoItem.progress != 0) - Positioned( - left: 3, - right: 3, - bottom: 0, - child: ClipRRect( - borderRadius: BorderRadius.only( - bottomLeft: - Radius.circular(StyleString.imgRadius.x), - bottomRight: - Radius.circular(StyleString.imgRadius.x), - ), - child: LinearProgressIndicator( - value: videoItem.progress == -1 - ? 100 - : videoItem.progress / videoItem.duration, - ), - ), - ) - ], + ), ), - videoContent(context) + if (videoItem.duration != null && + videoItem.duration != 0 && + videoItem.progress != 0) + Positioned( + left: 4, + right: 4, + bottom: 0, + child: ClipRRect( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + child: LinearProgressIndicator( + value: videoItem.progress == -1 + ? 100 + : videoItem.progress / videoItem.duration, + ), + ), + ) ], ), - ); - }, - ), - ), - ], + videoContent(context) + ], + ), + ); + }, + ), ), ); } diff --git a/lib/pages/later/view.dart b/lib/pages/later/view.dart index a9062103..3f19d6a0 100644 --- a/lib/pages/later/view.dart +++ b/lib/pages/later/view.dart @@ -112,7 +112,7 @@ class _LaterPageState extends State { padding: EdgeInsets.only( left: StyleString.safeSpace, right: StyleString.safeSpace, - bottom: MediaQuery.of(context).padding.bottom + 81, + bottom: MediaQuery.of(context).padding.bottom + 85, ), sliver: Obx( () => _buildBody(_laterController.loadingState.value), diff --git a/lib/pages/subscription/controller.dart b/lib/pages/subscription/controller.dart index db843074..23481830 100644 --- a/lib/pages/subscription/controller.dart +++ b/lib/pages/subscription/controller.dart @@ -1,48 +1,30 @@ +import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/common/common_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/http/user.dart'; -import 'package:PiliPalaX/models/user/info.dart'; import 'package:PiliPalaX/utils/storage.dart'; import '../../models/user/sub_folder.dart'; -class SubController extends GetxController { - final ScrollController scrollController = ScrollController(); - Rx subFolderData = SubFolderModelData().obs; - UserInfoData? userInfo; - int currentPage = 1; - int pageSize = 20; - RxBool hasMore = true.obs; +class SubController extends CommonController { + dynamic mid; - Future querySubFolder({type = 'init'}) async { - userInfo = GStorage.userInfo.get('userInfoCache'); - if (userInfo == null) { - return {'status': false, 'msg': '账号未登录'}; - } - var res = await UserHttp.userSubFolder( - pn: currentPage, - ps: pageSize, - mid: userInfo!.mid!, - ); - if (res['status']) { - if (type == 'init') { - subFolderData.value = res['data']; - } else { - if (res['data'].list.isNotEmpty) { - subFolderData.value.list!.addAll(res['data'].list); - subFolderData.update((val) {}); - } - } - currentPage++; - } else { - SmartDialog.showToast(res['msg']); - } - return res; + @override + void onInit() { + super.onInit(); + mid = GStorage.userInfo.get('userInfoCache')?.mid; + queryData(); } - Future onLoad() async { - querySubFolder(type: 'onload'); + @override + Future queryData([bool isRefresh = true]) { + if (mid == null) { + loadingState.value = LoadingState.error('账号未登录'); + return Future.value(); + } + return super.queryData(isRefresh); } // 取消订阅 @@ -67,8 +49,9 @@ class SubController extends GetxController { var res = await UserHttp.cancelSub( id: subFolderItem.id!, type: subFolderItem.type!); if (res['status']) { - subFolderData.value.list!.remove(subFolderItem); - subFolderData.update((val) {}); + List list = (loadingState.value as Success).response; + list.remove(subFolderItem); + loadingState.value = LoadingState.success(list); SmartDialog.showToast('取消订阅成功'); } else { SmartDialog.showToast(res['msg']); @@ -83,8 +66,9 @@ class SubController extends GetxController { } @override - void onClose() { - scrollController.dispose(); - super.onClose(); - } + Future customGetData() => UserHttp.userSubFolder( + pn: currentPage, + ps: 20, + mid: mid, + ); } diff --git a/lib/pages/subscription/view.dart b/lib/pages/subscription/view.dart index f0c8dbcc..ad2f2a32 100644 --- a/lib/pages/subscription/view.dart +++ b/lib/pages/subscription/view.dart @@ -1,11 +1,12 @@ -import 'package:easy_debounce/easy_throttle.dart'; +import 'package:PiliPalaX/common/constants.dart'; +import 'package:PiliPalaX/common/skeleton/video_card_h.dart'; +import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/subscription/widgets/item.dart'; +import 'package:PiliPalaX/utils/grid.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/common/widgets/http_error.dart'; -import '../../common/constants.dart'; -import '../../utils/grid.dart'; import 'controller.dart'; -import 'widgets/item.dart'; class SubPage extends StatefulWidget { const SubPage({super.key}); @@ -16,81 +17,73 @@ class SubPage extends StatefulWidget { class _SubPageState extends State { final SubController _subController = Get.put(SubController()); - late Future _futureBuilderFuture; - - @override - void dispose() { - _subController.scrollController.removeListener(() {}); - super.dispose(); - } - - @override - void initState() { - super.initState(); - _futureBuilderFuture = _subController.querySubFolder(); - _subController.scrollController.addListener( - () { - if (_subController.scrollController.position.pixels >= - _subController.scrollController.position.maxScrollExtent - 300) { - EasyThrottle.throttle('history', const Duration(seconds: 1), () { - _subController.onLoad(); - }); - } - }, - ); - } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('我的订阅')), - body: FutureBuilder( - future: _futureBuilderFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - // TODO: refactor - Map? data = snapshot.data; - if (data != null && data['status']) { - return Obx(() => CustomScrollView( - controller: _subController.scrollController, - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0), - delegate: SliverChildBuilderDelegate( - childCount: - _subController.subFolderData.value.list!.length, - (BuildContext context, int index) { - return SubItem( - subFolderItem: _subController - .subFolderData.value.list![index], - cancelSub: _subController.cancelSub); - }, - ), - ) - ])); - } else { - return CustomScrollView( - physics: const NeverScrollableScrollPhysics(), - slivers: [ - HttpError( - errMsg: data?['msg'], - callback: () => setState(() {}), - ), - ], - ); - } - } else { - // 骨架屏 - return const Text('请求中'); - } - }, + body: CustomScrollView( + slivers: [ + Obx(() => _buildBody(_subController.loadingState.value)), + SliverToBoxAdapter( + child: SizedBox( + height: MediaQuery.of(context).padding.bottom + 10, + ), + ), + ], ), ); } + + Widget _buildBody(LoadingState loadingState) { + return switch (loadingState) { + Loading() => SliverPadding( + padding: + const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + (context, index) => const VideoCardHSkeleton(), + childCount: 10, + ), + ), + ), + Success() => (loadingState.response as List?)?.isNotEmpty == true + ? SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + childCount: loadingState.response.length, + (BuildContext context, int index) { + if (index == loadingState.response.length - 1) { + _subController.onLoadMore(); + } + return SubItem( + subFolderItem: loadingState.response[index], + cancelSub: _subController.cancelSub, + ); + }, + ), + ) + : HttpError( + callback: _subController.onReload, + ), + Error() => HttpError( + errMsg: loadingState.errMsg, + callback: _subController.onReload, + ), + LoadingState() => throw UnimplementedError(), + }; + } } diff --git a/lib/pages/subscription_detail/view.dart b/lib/pages/subscription_detail/view.dart index 52285d06..fc245acb 100644 --- a/lib/pages/subscription_detail/view.dart +++ b/lib/pages/subscription_detail/view.dart @@ -1,5 +1,7 @@ import 'dart:async'; +import 'package:PiliPalaX/common/constants.dart'; +import 'package:PiliPalaX/utils/grid.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -225,13 +227,23 @@ class _SubDetailPageState extends State { return Obx( () => subList.isEmpty ? const SliverToBoxAdapter(child: SizedBox()) - : SliverList( - delegate: - SliverChildBuilderDelegate((context, index) { - return SubVideoCardH( - videoItem: subList[index], - ); - }, childCount: subList.length), + : SliverGrid( + gridDelegate: + SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + childCount: subList.length, + (BuildContext context, int index) { + return SubVideoCardH( + videoItem: subList[index], + ); + }, + ), ), ); } @@ -246,10 +258,22 @@ class _SubDetailPageState extends State { } } else { // 骨架屏 - return SliverList( - delegate: SliverChildBuilderDelegate((context, index) { - return const VideoCardHSkeleton(); - }, childCount: 10), + return SliverPadding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + (context, index) => const VideoCardHSkeleton(), + childCount: 10, + ), + ), ); } }, diff --git a/lib/pages/subscription_detail/widget/sub_video_card.dart b/lib/pages/subscription_detail/widget/sub_video_card.dart index 00963c93..4bad5a08 100644 --- a/lib/pages/subscription_detail/widget/sub_video_card.dart +++ b/lib/pages/subscription_detail/widget/sub_video_card.dart @@ -40,65 +40,61 @@ class SubVideoCardH extends StatelessWidget { 'videoType': SearchType.video, }); }, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.fromLTRB( - StyleString.safeSpace, 5, StyleString.safeSpace, 5), - 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; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: videoItem.cover, - width: maxWidth, - height: maxHeight, - ), - ), - PBadge( - text: Utils.timeFormat(videoItem.duration!), - right: 6.0, - bottom: 6.0, - type: 'gray', - ), - // if (videoItem.ogv != null) ...[ - // PBadge( - // text: videoItem.ogv['type_name'], - // top: 6.0, - // right: 6.0, - // bottom: null, - // left: null, - // ), - // ], - ], - ); - }, - ), - ), - videoContent(context) - ], + child: Padding( + padding: const EdgeInsets.fromLTRB( + StyleString.safeSpace, 5, StyleString.safeSpace, 5), + 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; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: videoItem.cover, + width: maxWidth, + height: maxHeight, + ), + ), + PBadge( + text: Utils.timeFormat(videoItem.duration!), + right: 6.0, + bottom: 6.0, + type: 'gray', + ), + // if (videoItem.ogv != null) ...[ + // PBadge( + // text: videoItem.ogv['type_name'], + // top: 6.0, + // right: 6.0, + // bottom: null, + // left: null, + // ), + // ], + ], + ); + }, + ), ), - ); - }, - ), - ), - ], + videoContent(context) + ], + ), + ); + }, + ), ), ); } diff --git a/pubspec.lock b/pubspec.lock index b29e7303..06cd6323 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,23 +5,23 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" + sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 url: "https://pub.dev" source: hosted - version: "76.0.0" + version: "72.0.0" _macros: dependency: transitive description: dart source: sdk - version: "0.3.3" + version: "0.3.2" analyzer: dependency: transitive description: name: analyzer - sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" + sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 url: "https://pub.dev" source: hosted - version: "6.11.0" + version: "6.7.0" animations: dependency: "direct main" description: @@ -317,10 +317,10 @@ packages: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.18.0" connectivity_plus: dependency: "direct main" description: @@ -1042,18 +1042,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -1098,10 +1098,10 @@ packages: dependency: transitive description: name: macros - sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" + sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" url: "https://pub.dev" source: hosted - version: "0.1.3-main.0" + version: "0.1.2-main.4" mailer: dependency: transitive description: @@ -1659,7 +1659,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.0" + version: "0.0.99" source_gen: dependency: transitive description: @@ -1736,10 +1736,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.11.1" status_bar_control: dependency: "direct main" description: @@ -1768,10 +1768,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.2.0" synchronized: dependency: transitive description: @@ -1800,10 +1800,10 @@ packages: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.2" timing: dependency: transitive description: @@ -1960,10 +1960,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "14.2.5" volume_controller: dependency: transitive description: