From 665dd8b92a53e4efda255f33b99582961a6165d1 Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Thu, 28 Nov 2024 20:49:07 +0800 Subject: [PATCH] refactor: history page Signed-off-by: bggRGjQaUbCoE --- lib/http/user.dart | 9 +- lib/models/user/history.dart | 4 +- lib/pages/blacklist/index.dart | 12 +- lib/pages/common/reply_controller.dart | 8 +- lib/pages/dynamics/tab/controller.dart | 11 +- lib/pages/fan/controller.dart | 11 +- lib/pages/fav/controller.dart | 11 +- lib/pages/fav_detail/controller.dart | 14 +- lib/pages/fav_search/view.dart | 1 - lib/pages/history/controller.dart | 126 +++--- lib/pages/history/view.dart | 378 +++++++++--------- lib/pages/history/widgets/item.dart | 86 ++-- lib/pages/later/controller.dart | 11 +- .../member_dynamic/member_dynamic_ctr.dart | 5 +- lib/pages/search_panel/controller.dart | 14 +- 15 files changed, 327 insertions(+), 374 deletions(-) diff --git a/lib/http/user.dart b/lib/http/user.dart index 26af3258..f98675f9 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -166,7 +166,10 @@ class UserHttp { } // 观看历史 - static Future historyList(int? max, int? viewAt) async { + static Future historyList({ + int? max, + int? viewAt, + }) async { var res = await Request().get(Api.historyList, data: { 'type': 'all', 'ps': 20, @@ -174,9 +177,9 @@ class UserHttp { 'view_at': viewAt ?? 0, }); if (res.data['code'] == 0) { - return {'status': true, 'data': HistoryData.fromJson(res.data['data'])}; + return LoadingState.success(HistoryData.fromJson(res.data['data'])); } else { - return {'status': false, 'data': [], 'msg': res.data['message']}; + return LoadingState.error(res.data['message']); } } diff --git a/lib/models/user/history.dart b/lib/models/user/history.dart index fb93bdcf..87781f69 100644 --- a/lib/models/user/history.dart +++ b/lib/models/user/history.dart @@ -85,7 +85,7 @@ class HisListItem { this.kid, this.tagName, this.liveStatus, - this.checked, + required this.checked, }); String? title; @@ -112,7 +112,7 @@ class HisListItem { int? kid; String? tagName; int? liveStatus; - bool? checked; + late bool checked; void isFullScreen; HisListItem.fromJson(Map json) { diff --git a/lib/pages/blacklist/index.dart b/lib/pages/blacklist/index.dart index 9c2510cb..9bbee698 100644 --- a/lib/pages/blacklist/index.dart +++ b/lib/pages/blacklist/index.dart @@ -125,13 +125,11 @@ class BlackListController extends CommonController { @override bool customHandleResponse(Success response) { total.value = response.response.total; - List currentList = loadingState.value is Success - ? (loadingState.value as Success).response - : []; - List dataList = currentPage == 1 - ? response.response.list - : currentList + response.response.list; - loadingState.value = LoadingState.success(dataList); + if (currentPage != 1 && loadingState.value is Success) { + response.response.list + ?.insertAll(0, (loadingState.value as Success).response); + } + loadingState.value = LoadingState.success(response.response.list); return true; } diff --git a/lib/pages/common/reply_controller.dart b/lib/pages/common/reply_controller.dart index dfdf03b4..68c9082f 100644 --- a/lib/pages/common/reply_controller.dart +++ b/lib/pages/common/reply_controller.dart @@ -64,11 +64,9 @@ abstract class ReplyController extends CommonController { } } cursor = replies.cursor; - if (currentPage != 1) { - List list = loadingState.value is Success - ? (loadingState.value as Success).response.replies - : []; - replies.replies.insertAll(0, list); + if (currentPage != 1 && loadingState.value is Success) { + replies.replies + .insertAll(0, (loadingState.value as Success).response.replies); } isEnd = replies.replies.isEmpty || replies.cursor.isEnd || diff --git a/lib/pages/dynamics/tab/controller.dart b/lib/pages/dynamics/tab/controller.dart index 283ee94c..00a480ae 100644 --- a/lib/pages/dynamics/tab/controller.dart +++ b/lib/pages/dynamics/tab/controller.dart @@ -31,13 +31,12 @@ class DynamicsTabController extends CommonController { @override bool customHandleResponse(Success response) { - List currentList = loadingState.value is Success - ? (loadingState.value as Success).response - : []; - loadingState.value = offset == '' - ? LoadingState.success(response.response.items) - : LoadingState.success(currentList + response.response.items); offset = response.response.offset; + if (currentPage != 1 && loadingState.value is Success) { + response.response.items + .insertAll(0, (loadingState.value as Success).response); + } + loadingState.value = LoadingState.success(response.response.items); return true; } diff --git a/lib/pages/fan/controller.dart b/lib/pages/fan/controller.dart index 6711af1f..0fa19d91 100644 --- a/lib/pages/fan/controller.dart +++ b/lib/pages/fan/controller.dart @@ -33,12 +33,11 @@ class FansController extends CommonController { response.response.list.isEmpty) { isEnd = true; } - List currentList = loadingState.value is Success - ? (loadingState.value as Success).response - : []; - loadingState.value = currentPage == 1 - ? LoadingState.success(response.response.list) - : LoadingState.success(currentList + response.response.list); + if (currentPage != 1 && loadingState.value is Success) { + response.response.list + .insertAll(0, (loadingState.value as Success).response); + } + loadingState.value = LoadingState.success(response.response.list); return true; } diff --git a/lib/pages/fav/controller.dart b/lib/pages/fav/controller.dart index 0dbffd89..48806490 100644 --- a/lib/pages/fav/controller.dart +++ b/lib/pages/fav/controller.dart @@ -33,12 +33,11 @@ class FavController extends CommonController { @override bool customHandleResponse(Success response) { hasMore = response.response.hasMore; - List currentList = loadingState.value is Success - ? (loadingState.value as Success).response - : []; - loadingState.value = currentPage == 1 - ? LoadingState.success(response.response.list) - : LoadingState.success(currentList + response.response.list); + if (currentPage != 1 && loadingState.value is Success) { + response.response.list + .insertAll(0, (loadingState.value as Success).response); + } + loadingState.value = LoadingState.success(response.response.list); return true; } diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index b2732898..41f641ec 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -48,14 +48,12 @@ class FavDetailController extends CommonController { isOwner.value = response.response.info.mid == GStorage.userInfo.get('userInfoCache')?.mid; } - List currentList = loadingState.value is Success - ? (loadingState.value as Success).response - : []; - List dataList = currentPage == 1 - ? response.response.medias - : currentList + response.response.medias; - loadingState.value = LoadingState.success(dataList); - if (dataList.length >= response.response.info.mediaCount) { + if (currentPage != 1 && loadingState.value is Success) { + response.response.medias + .insertAll(0, (loadingState.value as Success).response); + } + loadingState.value = LoadingState.success(response.response.medias); + if (response.response.medias.length >= response.response.info.mediaCount) { loadingText.value = '没有更多了'; } return true; diff --git a/lib/pages/fav_search/view.dart b/lib/pages/fav_search/view.dart index 3b13dbbe..8b8f7869 100644 --- a/lib/pages/fav_search/view.dart +++ b/lib/pages/fav_search/view.dart @@ -140,7 +140,6 @@ class _FavSearchPageState extends State { videoItem: loadingState.response[index], ctr: _favSearchCtr, onChoose: null, - onUpdateMultiple: () => null, ); }, childCount: loadingState.response.length, diff --git a/lib/pages/history/controller.dart b/lib/pages/history/controller.dart index dd537a1b..8ce86f79 100644 --- a/lib/pages/history/controller.dart +++ b/lib/pages/history/controller.dart @@ -1,53 +1,47 @@ +import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/common/common_controller.dart'; +import 'package:PiliPalaX/utils/extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -import 'package:hive/hive.dart'; import 'package:PiliPalaX/http/user.dart'; import 'package:PiliPalaX/models/user/history.dart'; import 'package:PiliPalaX/utils/storage.dart'; -class HistoryController extends GetxController { - final ScrollController scrollController = ScrollController(); - RxList historyList = [].obs; - RxBool isLoadingMore = false.obs; +class HistoryController extends CommonController { RxBool pauseStatus = false.obs; - Box localCache = GStorage.localCache; - RxBool isLoading = false.obs; + RxBool enableMultiple = false.obs; RxInt checkedCount = 0.obs; + int? max; + int? viewAt; + @override void onInit() { super.onInit(); historyStatus(); + queryData(); } - Future queryHistoryList({type = 'init'}) async { - int max = 0; - int viewAt = 0; - if (type == 'onload' && historyList.isNotEmpty) { - max = historyList.last.history!.oid!; - viewAt = historyList.last.viewAt!; + @override + Future onRefresh() { + max = null; + viewAt = null; + return super.onRefresh(); + } + + @override + bool customHandleResponse(Success response) { + HistoryData data = response.response; + isEnd = data.list.isNullOrEmpty || data.list!.length < 20; + max = data.list?.lastOrNull?.history?.oid; + viewAt = data.list?.lastOrNull?.viewAt; + if (currentPage != 1 && loadingState.value is Success) { + data.list?.insertAll(0, (loadingState.value as Success).response); } - isLoadingMore.value = true; - var res = await UserHttp.historyList(max, viewAt); - isLoadingMore.value = false; - if (res['status']) { - if (type == 'onload') { - historyList.addAll(res['data'].list); - } else { - historyList.value = res['data'].list; - } - } - return res; - } - - Future onLoad() async { - queryHistoryList(type: 'onload'); - } - - Future onRefresh() async { - queryHistoryList(type: 'onRefresh'); + loadingState.value = LoadingState.success(data.list); + return true; } // 暂停观看历史 @@ -60,7 +54,7 @@ class HistoryController extends GetxController { content: Text(!pauseStatus.value ? '啊叻?你要暂停历史记录功能吗?' : '啊叻?要恢复历史记录功能吗?'), actions: [ - TextButton(onPressed: () => Get.back(), child: const Text('取消')), + TextButton(onPressed: Get.back, child: const Text('取消')), TextButton( onPressed: () async { SmartDialog.showLoading(msg: '请求中'); @@ -70,7 +64,8 @@ class HistoryController extends GetxController { SmartDialog.showToast( !pauseStatus.value ? '暂停观看历史' : '恢复观看历史'); pauseStatus.value = !pauseStatus.value; - localCache.put(LocalCacheKey.historyPause, pauseStatus.value); + GStorage.localCache + .put(LocalCacheKey.historyPause, pauseStatus.value); } Get.back(); }, @@ -87,7 +82,7 @@ class HistoryController extends GetxController { var res = await UserHttp.historyStatus(); if (res['status']) { pauseStatus.value = res['data']; - localCache.put(LocalCacheKey.historyPause, res['data']); + GStorage.localCache.put(LocalCacheKey.historyPause, res['data']); } else { SmartDialog.showToast(res['msg']); } @@ -102,7 +97,7 @@ class HistoryController extends GetxController { title: const Text('提示'), content: const Text('啊叻?你要清空历史记录功能吗?'), actions: [ - TextButton(onPressed: () => Get.back(), child: const Text('取消')), + TextButton(onPressed: Get.back, child: const Text('取消')), TextButton( onPressed: () async { SmartDialog.showLoading(msg: '请求中'); @@ -112,7 +107,7 @@ class HistoryController extends GetxController { SmartDialog.showToast('清空观看历史'); } Get.back(); - historyList.clear(); + loadingState.value = LoadingState.success([]); }, child: const Text('确认清空'), ) @@ -124,48 +119,38 @@ class HistoryController extends GetxController { // 删除某条历史记录 Future delHistory(kid, business) async { - // String resKid = 'archive_$kid'; - // if (business == 'live') { - // resKid = 'live_$kid'; - // } else if (business.contains('article')) { - // resKid = 'article_$kid'; - // } - - // var res = await UserHttp.delHistory(resKid); - // if (res['status']) { - // historyList.removeWhere((e) => e.kid == kid); - // SmartDialog.showToast(res['msg']); - // } - _onDelete(historyList.where((e) => e.kid == kid).toList()); + _onDelete(((loadingState.value as Success).response as List) + .where((e) => e.kid == kid) + .toList()); } // 删除已看历史记录 void onDelHistory() { - List list = - historyList.where((e) => e.progress == -1).toList(); - if (list.isNotEmpty) { - _onDelete(list); - } else { - SmartDialog.showToast('无已看记录'); + if (loadingState.value is Success) { + List list = + ((loadingState.value as Success).response as List) + .where((e) => e.progress == -1) + .toList(); + if (list.isNotEmpty) { + _onDelete(list); + } else { + SmartDialog.showToast('无已看记录'); + } } } void _onDelete(List result) async { SmartDialog.showLoading(msg: '请求中'); List kidList = result.map((item) { - // String tag = 'archive'; - // if (item.history?.business == 'live') { - // tag = 'live'; - // } else if (item.history?.business?.contains('article') == true) { - // tag = 'article-list'; - // } return '${item.history?.business}_${item.kid}'; }).toList(); dynamic response = await UserHttp.delHistory(kidList); if (response['status']) { Set remainList = - historyList.toSet().difference(result.toSet()); - historyList.value = remainList.toList(); + ((loadingState.value as Success).response as List) + .toSet() + .difference(result.toSet()); + loadingState.value = LoadingState.success(remainList.toList()); if (enableMultiple.value) { checkedCount.value = 0; enableMultiple.value = false; @@ -185,7 +170,7 @@ class HistoryController extends GetxController { content: const Text('确认删除所选历史记录吗?'), actions: [ TextButton( - onPressed: () => Get.back(), + onPressed: Get.back, child: Text( '取消', style: TextStyle( @@ -196,7 +181,10 @@ class HistoryController extends GetxController { TextButton( onPressed: () async { Get.back(); - _onDelete(historyList.where((e) => e.checked!).toList()); + _onDelete(((loadingState.value as Success).response + as List) + .where((e) => e.checked) + .toList()); }, child: const Text('确认'), ) @@ -207,8 +195,6 @@ class HistoryController extends GetxController { } @override - void onClose() { - scrollController.dispose(); - super.onClose(); - } + Future customGetData() => + UserHttp.historyList(max: max, viewAt: viewAt); } diff --git a/lib/pages/history/view.dart b/lib/pages/history/view.dart index bd8a1f3c..a294b139 100644 --- a/lib/pages/history/view.dart +++ b/lib/pages/history/view.dart @@ -1,6 +1,9 @@ import 'package:PiliPalaX/common/widgets/http_error.dart'; import 'package:PiliPalaX/common/widgets/refresh_indicator.dart'; +import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/models/user/history.dart'; import 'package:PiliPalaX/pages/fav_search/view.dart' show SearchType; +import 'package:PiliPalaX/utils/extension.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -19,43 +22,35 @@ class HistoryPage extends StatefulWidget { } class _HistoryPageState extends State { - final HistoryController _historyController = Get.put(HistoryController()); - Future? _futureBuilderFuture; + final _historyController = Get.put(HistoryController()); @override void initState() { super.initState(); - _futureBuilderFuture = _historyController.queryHistoryList(); _historyController.scrollController.addListener( () { if (_historyController.scrollController.position.pixels >= _historyController.scrollController.position.maxScrollExtent - 300) { - if (!_historyController.isLoadingMore.value) { - EasyThrottle.throttle('history', const Duration(seconds: 1), () { - _historyController.onLoad(); - }); - } + EasyThrottle.throttle('history', const Duration(seconds: 1), () { + _historyController.onLoadMore(); + }); } }, ); - _historyController.enableMultiple.listen((p0) { - setState(() {}); - }); } // 选中 onChoose(index) { - _historyController.historyList[index].checked = - !_historyController.historyList[index].checked!; + List list = + (_historyController.loadingState.value as Success).response; + list[index].checked = list[index].checked.not; _historyController.checkedCount.value = - _historyController.historyList.where((item) => item.checked!).length; - _historyController.historyList.refresh(); - } - - // 更新多选状态 - onUpdateMultiple() { - setState(() {}); + list.where((item) => item.checked).length; + _historyController.loadingState.value = LoadingState.success(list); + if (_historyController.checkedCount.value == 0) { + _historyController.enableMultiple.value = false; + } } @override @@ -66,194 +61,187 @@ class _HistoryPageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBarWidget( - visible: _historyController.enableMultiple.value, - child1: AppBar( - title: Text('观看记录'), - actions: [ - IconButton( - tooltip: '搜索', - onPressed: () => Get.toNamed('/favSearch', arguments: { - 'searchType': SearchType.history, - }), - icon: const Icon(Icons.search_outlined), + return Obx( + () => PopScope( + canPop: _historyController.enableMultiple.value.not, + onPopInvokedWithResult: (didPop, result) { + if (_historyController.enableMultiple.value) { + _handleSelect(); + } + }, + child: Scaffold( + appBar: AppBarWidget( + visible: _historyController.enableMultiple.value, + child1: AppBar( + title: Text('观看记录'), + actions: [ + IconButton( + tooltip: '搜索', + onPressed: () => Get.toNamed( + '/favSearch', + arguments: { + 'searchType': SearchType.history, + }, + ), + icon: const Icon(Icons.search_outlined), + ), + PopupMenuButton( + onSelected: (String type) { + // 处理菜单项选择的逻辑 + switch (type) { + case 'pause': + _historyController.onPauseHistory(context); + break; + case 'clear': + _historyController.onClearHistory(context); + break; + case 'del': + _historyController.onDelHistory(); + break; + case 'multiple': + _historyController.enableMultiple.value = true; + break; + } + }, + itemBuilder: (BuildContext context) => + >[ + PopupMenuItem( + value: 'pause', + child: Obx( + () => Text( + !_historyController.pauseStatus.value + ? '暂停观看记录' + : '恢复观看记录', + ), + ), + ), + const PopupMenuItem( + value: 'clear', + child: Text('清空观看记录'), + ), + const PopupMenuItem( + value: 'del', + child: Text('删除已看记录'), + ), + const PopupMenuItem( + value: 'multiple', + child: Text('多选删除'), + ), + ], + ), + const SizedBox(width: 6), + ], ), - PopupMenuButton( - onSelected: (String type) { - // 处理菜单项选择的逻辑 - switch (type) { - case 'pause': - _historyController.onPauseHistory(context); - break; - case 'clear': - _historyController.onClearHistory(context); - break; - case 'del': - _historyController.onDelHistory(); - break; - case 'multiple': - _historyController.enableMultiple.value = true; - setState(() {}); - break; - default: - } - }, - itemBuilder: (BuildContext context) => >[ - PopupMenuItem( - value: 'pause', - child: Obx( - () => Text(!_historyController.pauseStatus.value - ? '暂停观看记录' - : '恢复观看记录'), + child2: AppBar( + leading: IconButton( + tooltip: '取消', + onPressed: _handleSelect, + icon: const Icon(Icons.close_outlined), + ), + title: Obx( + () => Text( + '已选择${_historyController.checkedCount.value}项', + ), + ), + actions: [ + TextButton( + onPressed: () => _handleSelect(true), + child: const Text('全选'), + ), + TextButton( + onPressed: () => + _historyController.onDelCheckedHistory(context), + child: Text( + '删除', + style: + TextStyle(color: Theme.of(context).colorScheme.error), ), ), - const PopupMenuItem( - value: 'clear', - child: Text('清空观看记录'), - ), - const PopupMenuItem( - value: 'del', - child: Text('删除已看记录'), - ), - const PopupMenuItem( - value: 'multiple', - child: Text('多选删除'), + const SizedBox(width: 6), + ], + ), + ), + body: refreshIndicator( + onRefresh: () async { + await _historyController.onRefresh(); + }, + child: CustomScrollView( + physics: const AlwaysScrollableScrollPhysics(), + controller: _historyController.scrollController, + slivers: [ + Obx(() => _buildBody(_historyController.loadingState.value)), + SliverToBoxAdapter( + child: SizedBox( + height: MediaQuery.of(context).padding.bottom + 10, + ), ), ], ), - const SizedBox(width: 6), - ], - ), - child2: AppBar( - leading: IconButton( - tooltip: '取消', - onPressed: () { - _historyController.enableMultiple.value = false; - for (var item in _historyController.historyList) { - item.checked = false; - } - _historyController.checkedCount.value = 0; - setState(() {}); - }, - icon: const Icon(Icons.close_outlined), ), - title: Obx( - () => Text( - '已选择${_historyController.checkedCount.value}项', - ), - ), - actions: [ - TextButton( - onPressed: () { - for (var item in _historyController.historyList) { - item.checked = true; - } - _historyController.checkedCount.value = - _historyController.historyList.length; - _historyController.historyList.refresh(); - }, - child: const Text('全选'), - ), - TextButton( - onPressed: () => _historyController.onDelCheckedHistory(context), - child: Text( - '删除', - style: TextStyle(color: Theme.of(context).colorScheme.error), - ), - ), - const SizedBox(width: 6), - ], ), ), - body: refreshIndicator( - onRefresh: () async { - await _historyController.onRefresh(); - return; - }, - child: CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), - controller: _historyController.scrollController, - slivers: [ - FutureBuilder( - future: _futureBuilderFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.data == null) { - return const SliverToBoxAdapter(child: SizedBox()); - } - Map data = snapshot.data; - if (data['status']) { - return Obx( - () => _historyController.historyList.isNotEmpty - ? 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 HistoryItem( - videoItem: - _historyController.historyList[index], - ctr: _historyController, - onChoose: () => onChoose(index), - onUpdateMultiple: () => onUpdateMultiple(), - ); - }, - childCount: - _historyController.historyList.length), - ) - : _historyController.isLoadingMore.value - ? const SliverToBoxAdapter( - child: Center(child: Text('加载中')), - ) - : HttpError( - callback: () => setState(() { - _futureBuilderFuture = - _historyController.queryHistoryList(); - }), - ), - ); - } else { - return HttpError( - errMsg: data['msg'], - callback: () => setState(() { - _futureBuilderFuture = - _historyController.queryHistoryList(); - }), - ); - } - } else { - // 骨架屏 - return 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), + ); + } + + 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, + ), + ), + 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( + (context, index) { + return HistoryItem( + videoItem: loadingState.response[index], + ctr: _historyController, + onChoose: () => onChoose(index), ); - } - }, - ), - SliverToBoxAdapter( - child: SizedBox( - height: MediaQuery.of(context).padding.bottom + 10, + }, + childCount: loadingState.response.length, ), ) - ], + : HttpError( + callback: _historyController.onReload, + ), + Error() => HttpError( + errMsg: loadingState.errMsg, + callback: _historyController.onReload, ), - ), - // bottomNavigationBar: BottomAppBar(), - ); + LoadingState() => throw UnimplementedError(), + }; + } + + void _handleSelect([bool checked = false]) { + List? list = + (_historyController.loadingState.value as Success?)?.response; + if (list.isNullOrEmpty.not) { + _historyController.loadingState.value = LoadingState.success( + list!.map((item) => item..checked = checked).toList()); + _historyController.checkedCount.value = checked ? list.length : 0; + } + if (checked.not) { + _historyController.enableMultiple.value = false; + } } } diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 2d215b6f..ba87a196 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -19,13 +19,11 @@ class HistoryItem extends StatelessWidget { final dynamic videoItem; final dynamic ctr; final Function? onChoose; - final Function? onUpdateMultiple; const HistoryItem({ super.key, required this.videoItem, this.ctr, this.onChoose, - this.onUpdateMultiple, }); @override @@ -159,7 +157,6 @@ class HistoryItem extends StatelessWidget { feedBack(); ctr!.enableMultiple.value = true; onChoose?.call(); - onUpdateMultiple?.call(); } }, child: Column( @@ -190,6 +187,7 @@ class HistoryItem extends StatelessWidget { Hero( tag: heroTag, child: NetworkImgLayer( + radius: 12, src: (videoItem.cover != '' ? videoItem.cover : videoItem.covers.first), @@ -226,51 +224,47 @@ class HistoryItem extends StatelessWidget { }, ), ), - Obx( - () => Positioned.fill( - child: AnimatedOpacity( - opacity: ctr!.enableMultiple.value ? 1 : 0, - duration: const Duration(milliseconds: 200), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - color: Colors.black.withOpacity( - ctr!.enableMultiple.value && - videoItem.checked - ? 0.6 - : 0), - ), - child: Center( - 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 Colors.white - .withOpacity(0.8); - }, - ), - ), - onPressed: () { - feedBack(); - onChoose?.call(); - }, - icon: Icon(Icons.done_all_outlined, - color: Theme.of(context) + Positioned.fill( + child: AnimatedOpacity( + opacity: videoItem.checked ? 1 : 0, + duration: const Duration(milliseconds: 200), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.black.withOpacity(0.6), + ), + child: Center( + 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 - .primary), + .surface + .withOpacity(0.8); + }, + ), ), + onPressed: () { + feedBack(); + onChoose?.call(); + }, + icon: Icon(Icons.done_all_outlined, + color: Theme.of(context) + .colorScheme + .primary), ), ), ), diff --git a/lib/pages/later/controller.dart b/lib/pages/later/controller.dart index e28abb61..99367488 100644 --- a/lib/pages/later/controller.dart +++ b/lib/pages/later/controller.dart @@ -19,12 +19,11 @@ class LaterController extends CommonController { if (currentPage == 1) { count.value = response.response['count']; } - List currentList = loadingState.value is Success - ? (loadingState.value as Success).response - : []; - loadingState.value = currentPage == 1 - ? LoadingState.success(response.response['list']) - : LoadingState.success(currentList + response.response['list']); + if (currentPage != 1 && loadingState.value is Success) { + response.response['list'] + .insertAll(0, (loadingState.value as Success).response); + } + loadingState.value = LoadingState.success(response.response['list']); return true; } diff --git a/lib/pages/member/new/content/member_dynamic/member_dynamic_ctr.dart b/lib/pages/member/new/content/member_dynamic/member_dynamic_ctr.dart index 65f2dcf9..98b98f51 100644 --- a/lib/pages/member/new/content/member_dynamic/member_dynamic_ctr.dart +++ b/lib/pages/member/new/content/member_dynamic/member_dynamic_ctr.dart @@ -13,9 +13,8 @@ class MemberDynamicCtr extends CommonController { bool customHandleResponse(Success response) { DynSpaceRsp res = response.response; isEnd = !res.hasMore; - if (currentPage != 1) { - res.list.insertAll( - 0, (loadingState.value as Success?)?.response ?? []); + if (currentPage != 1 && loadingState.value is Success) { + res.list.insertAll(0, (loadingState.value as Success).response); } loadingState.value = LoadingState.success(res.list); return true; diff --git a/lib/pages/search_panel/controller.dart b/lib/pages/search_panel/controller.dart index b34477e6..539ceb03 100644 --- a/lib/pages/search_panel/controller.dart +++ b/lib/pages/search_panel/controller.dart @@ -36,17 +36,11 @@ class SearchPanelController extends CommonController { searchResultController.count[SearchType.values.indexOf(searchType!)] = response.response.numResults; if (response.response.list != null) { - List currentList = currentPage != 1 && loadingState.value is Success - ? (loadingState.value as Success).response - : []; - List dataList = currentPage == 1 - ? response.response.list - : currentList + response.response.list; - if (dataList.isNotEmpty) { - loadingState.value = LoadingState.success(dataList); - } else { - loadingState.value = LoadingState.success([]); + if (currentPage != 1 && loadingState.value is Success) { + response.response.list + ?.insertAll(0, (loadingState.value as Success).response); } + loadingState.value = LoadingState.success(response.response.list); if (currentPage == 1) { onPushDetail(response.response.list); }