diff --git a/lib/pages/search_panel/view.dart b/lib/pages/search_panel/view.dart index d7600ae78..efb785f55 100644 --- a/lib/pages/search_panel/view.dart +++ b/lib/pages/search_panel/view.dart @@ -1,5 +1,6 @@ import 'package:PiliPalaX/common/widgets/refresh_indicator.dart'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/search_panel/widgets/video_panel.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -14,7 +15,6 @@ import 'widgets/article_panel.dart'; import 'widgets/live_panel.dart'; import 'widgets/media_bangumi_panel.dart'; import 'widgets/user_panel.dart'; -import 'widgets/video_panel.dart'; class SearchPanel extends StatefulWidget { final String? keyword; @@ -112,9 +112,10 @@ class _SearchPanelState extends State } else { switch (widget.searchType) { case SearchType.video: - return SearchVideoPanel( - ctr: _searchPanelController, - loadingState: loadingState, + return searchVideoPanel( + context, + _searchPanelController, + loadingState, ); case SearchType.media_bangumi: return searchBangumiPanel( diff --git a/lib/pages/search_panel/widgets/article_panel.dart b/lib/pages/search_panel/widgets/article_panel.dart index a88986c22..0e561ad3f 100644 --- a/lib/pages/search_panel/widgets/article_panel.dart +++ b/lib/pages/search_panel/widgets/article_panel.dart @@ -1,4 +1,5 @@ import 'package:PiliPalaX/common/widgets/http_error.dart'; +import 'package:PiliPalaX/common/widgets/loading_widget.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/pages/search/widgets/search_text.dart'; import 'package:PiliPalaX/pages/search_panel/controller.dart'; @@ -13,7 +14,7 @@ import 'package:PiliPalaX/utils/utils.dart'; import '../../../utils/grid.dart'; -Widget searchArticlePanel(BuildContext context, searchPanelCtr, loadingState) { +Widget searchArticlePanel(context, searchPanelCtr, LoadingState loadingState) { TextStyle textStyle = TextStyle( fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, color: Theme.of(context).colorScheme.outline); @@ -73,141 +74,151 @@ Widget searchArticlePanel(BuildContext context, searchPanelCtr, loadingState) { ), ), ), - loadingState is Success - ? SliverPadding( - padding: EdgeInsets.only( - bottom: StyleString.safeSpace + - MediaQuery.of(context).padding.bottom, - ), - sliver: SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.safeSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0, + switch (loadingState) { + Loading() => errorWidget(), + Success() => (loadingState.response as List?)?.isNotEmpty == true + ? SliverPadding( + padding: EdgeInsets.only( + bottom: StyleString.safeSpace + + MediaQuery.of(context).padding.bottom, ), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return InkWell( - onTap: () { - Get.toNamed('/htmlRender', parameters: { - 'url': - 'www.bilibili.com/read/cv${loadingState.response[index].id}', - 'title': loadingState.response[index].subTitle, - 'id': 'cv${loadingState.response[index].id}', - 'dynamicType': 'read' - }); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: StyleString.safeSpace), - child: LayoutBuilder( - builder: (context, boxConstraints) { - final double width = (boxConstraints.maxWidth - - StyleString.cardSpace * - 6 / - MediaQuery.textScalerOf(context) - .scale(1.0)) / - 2; - return Container( - constraints: const BoxConstraints(minHeight: 88), - height: width / StyleString.aspectRatio, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (loadingState.response[index].imageUrls != - null && - loadingState - .response[index].imageUrls.isNotEmpty) - AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder( - builder: (context, boxConstraints) { - double maxWidth = - boxConstraints.maxWidth; - double maxHeight = - boxConstraints.maxHeight; - return NetworkImgLayer( - width: maxWidth, - height: maxHeight, - src: loadingState - .response[index].imageUrls.first, - ); - }), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.fromLTRB( - 10, 2, 6, 0), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - RichText( - maxLines: 2, - text: TextSpan( - children: [ - for (var i in loadingState - .response[index].title) ...[ - TextSpan( - text: i['text'], - style: TextStyle( - fontWeight: - FontWeight.w400, - letterSpacing: 0.3, - color: i['type'] == 'em' - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .onSurface, + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.safeSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return InkWell( + onTap: () { + Get.toNamed('/htmlRender', parameters: { + 'url': + 'www.bilibili.com/read/cv${loadingState.response[index].id}', + 'title': loadingState.response[index].subTitle, + 'id': 'cv${loadingState.response[index].id}', + 'dynamicType': 'read' + }); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace), + child: LayoutBuilder( + builder: (context, boxConstraints) { + final double width = (boxConstraints.maxWidth - + StyleString.cardSpace * + 6 / + MediaQuery.textScalerOf(context) + .scale(1.0)) / + 2; + return Container( + constraints: + const BoxConstraints(minHeight: 88), + height: width / StyleString.aspectRatio, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (loadingState + .response[index].imageUrls != + null && + loadingState.response[index].imageUrls + .isNotEmpty) + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder( + builder: (context, boxConstraints) { + double maxWidth = + boxConstraints.maxWidth; + double maxHeight = + boxConstraints.maxHeight; + return NetworkImgLayer( + width: maxWidth, + height: maxHeight, + src: loadingState.response[index] + .imageUrls.first, + ); + }), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.fromLTRB( + 10, 2, 6, 0), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + RichText( + maxLines: 2, + text: TextSpan( + children: [ + for (var i in loadingState + .response[index] + .title) ...[ + TextSpan( + text: i['text'], + style: TextStyle( + fontWeight: + FontWeight.w400, + letterSpacing: 0.3, + color: i['type'] == 'em' + ? Theme.of(context) + .colorScheme + .primary + : Theme.of(context) + .colorScheme + .onSurface, + ), ), - ), - ] + ] + ], + ), + ), + const Spacer(), + Text( + Utils.dateFormat( + loadingState.response[index] + .pubTime, + formatType: 'detail'), + style: textStyle), + Row( + children: [ + Text( + '${loadingState.response[index].view}浏览', + style: textStyle), + Text(' • ', style: textStyle), + Text( + '${loadingState.response[index].reply}评论', + style: textStyle), ], ), - ), - const Spacer(), - Text( - Utils.dateFormat( - loadingState - .response[index].pubTime, - formatType: 'detail'), - style: textStyle), - Row( - children: [ - Text( - '${loadingState.response[index].view}浏览', - style: textStyle), - Text(' • ', style: textStyle), - Text( - '${loadingState.response[index].reply}评论', - style: textStyle), - ], - ), - ], + ], + ), ), ), - ), - ], - ), - ); - }, + ], + ), + ); + }, + ), ), - ), - ); - }, - childCount: loadingState.response.length, + ); + }, + childCount: loadingState.response.length, + ), ), + ) + : HttpError( + callback: searchPanelCtr.onReload, ), - ) - : HttpError( - errMsg: loadingState is Error ? loadingState.errMsg : '没有相关数据', - callback: searchPanelCtr.onReload, - ), + Error() => HttpError( + errMsg: loadingState.errMsg, + callback: searchPanelCtr.onReload, + ), + LoadingState() => throw UnimplementedError(), + }, ], ); } diff --git a/lib/pages/search_panel/widgets/live_panel.dart b/lib/pages/search_panel/widgets/live_panel.dart index d4f5ae081..58232d58c 100644 --- a/lib/pages/search_panel/widgets/live_panel.dart +++ b/lib/pages/search_panel/widgets/live_panel.dart @@ -75,14 +75,11 @@ class LiveItem extends StatelessWidget { double maxHeight = boxConstraints.maxHeight; return Stack( children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: liveItem.cover, - type: 'emote', - width: maxWidth, - height: maxHeight, - ), + NetworkImgLayer( + src: liveItem.cover, + type: 'emote', + width: maxWidth, + height: maxHeight, ), Positioned( left: 0, diff --git a/lib/pages/search_panel/widgets/media_bangumi_panel.dart b/lib/pages/search_panel/widgets/media_bangumi_panel.dart index b59f99063..7feb3efc6 100644 --- a/lib/pages/search_panel/widgets/media_bangumi_panel.dart +++ b/lib/pages/search_panel/widgets/media_bangumi_panel.dart @@ -1,4 +1,4 @@ -import 'package:PiliPalaX/common/widgets/http_error.dart'; +import 'package:PiliPalaX/common/widgets/loading_widget.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:flutter/material.dart'; import 'package:PiliPalaX/common/constants.dart'; @@ -8,135 +8,144 @@ import 'package:PiliPalaX/utils/utils.dart'; import '../../../utils/grid.dart'; -Widget searchBangumiPanel(BuildContext context, ctr, loadingState) { +Widget searchBangumiPanel(context, ctr, LoadingState loadingState) { TextStyle style = TextStyle(fontSize: Theme.of(context).textTheme.labelMedium!.fontSize); - return CustomScrollView( - controller: ctr.scrollController, - slivers: [ - loadingState is Success - ? SliverPadding( - padding: EdgeInsets.only( - bottom: StyleString.safeSpace + - MediaQuery.of(context).padding.bottom, - ), - sliver: SliverGrid( - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - mainAxisSpacing: StyleString.safeSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - mainAxisExtent: 160, + return switch (loadingState) { + Loading() => loadingWidget, + Success() => (loadingState.response as List?)?.isNotEmpty == true + ? CustomScrollView( + controller: ctr.scrollController, + slivers: [ + SliverPadding( + padding: EdgeInsets.only( + bottom: StyleString.safeSpace + + MediaQuery.of(context).padding.bottom, ), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - var i = loadingState.response[index]; - return InkWell( - onTap: () { - Utils.viewBangumi(seasonId: i.seasonId); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: StyleString.safeSpace, - vertical: StyleString.cardSpace, - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack( - children: [ - NetworkImgLayer( - width: 111, - height: 148, - src: i.cover, - ), - PBadge( - text: i.mediaType == 1 ? '番剧' : '国创', - top: 6.0, - right: 4.0, - bottom: null, - left: null, - ) - ], - ), - const SizedBox(width: 10), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: StyleString.safeSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + mainAxisExtent: 160, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + var i = loadingState.response[index]; + return InkWell( + onTap: () { + Utils.viewBangumi(seasonId: i.seasonId); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: StyleString.cardSpace, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( children: [ - const SizedBox(height: 4), - RichText( - maxLines: 1, - overflow: TextOverflow.ellipsis, - text: TextSpan( - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface), - children: [ - for (var i in i.title) ...[ - TextSpan( - text: i['text'], - style: TextStyle( - fontSize: MediaQuery.textScalerOf( - context) - .scale(Theme.of(context) - .textTheme - .titleSmall! - .fontSize!), - fontWeight: FontWeight.bold, - color: i['type'] == 'em' - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .onSurface, - ), - ), - ], - ], - ), - ), - const SizedBox(height: 12), - Text('评分:${i.mediaScore['score'].toString()}', - style: style), - Row( - children: [ - Text(i.areas, style: style), - const SizedBox(width: 3), - const Text('·'), - const SizedBox(width: 3), - Text( - Utils.dateFormat(i.pubtime) - .toString(), - style: style), - ], - ), - Row( - children: [ - Text(i.styles, style: style), - const SizedBox(width: 3), - const Text('·'), - const SizedBox(width: 3), - Text(i.indexShow, style: style), - ], + NetworkImgLayer( + width: 111, + height: 148, + src: i.cover, ), + PBadge( + text: i.mediaType == 1 ? '番剧' : '国创', + top: 6.0, + right: 4.0, + bottom: null, + left: null, + ) ], ), - ), - ], + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 4), + RichText( + maxLines: 1, + overflow: TextOverflow.ellipsis, + text: TextSpan( + style: TextStyle( + color: Theme.of(context) + .colorScheme + .onSurface), + children: [ + for (var i in i.title) ...[ + TextSpan( + text: i['text'], + style: TextStyle( + fontSize: + MediaQuery.textScalerOf( + context) + .scale(Theme.of(context) + .textTheme + .titleSmall! + .fontSize!), + fontWeight: FontWeight.bold, + color: i['type'] == 'em' + ? Theme.of(context) + .colorScheme + .primary + : Theme.of(context) + .colorScheme + .onSurface, + ), + ), + ], + ], + ), + ), + const SizedBox(height: 12), + Text( + '评分:${i.mediaScore['score'].toString()}', + style: style), + Row( + children: [ + Text(i.areas, style: style), + const SizedBox(width: 3), + const Text('·'), + const SizedBox(width: 3), + Text( + Utils.dateFormat(i.pubtime) + .toString(), + style: style), + ], + ), + Row( + children: [ + Text(i.styles, style: style), + const SizedBox(width: 3), + const Text('·'), + const SizedBox(width: 3), + Text(i.indexShow, style: style), + ], + ), + ], + ), + ), + ], + ), ), - ), - ); - }, - childCount: loadingState.response.length, + ); + }, + childCount: loadingState.response.length, + ), ), ), - ) - : HttpError( - errMsg: loadingState is Error ? loadingState.errMsg : '没有相关数据', - callback: ctr.onReload, - ), - ], - ); + ], + ) + : errorWidget( + callback: ctr.onReload, + ), + Error() => errorWidget( + errMsg: loadingState.errMsg, + callback: ctr.onReload, + ), + LoadingState() => throw UnimplementedError(), + }; } diff --git a/lib/pages/search_panel/widgets/user_panel.dart b/lib/pages/search_panel/widgets/user_panel.dart index d44a8b346..0ece85ef4 100644 --- a/lib/pages/search_panel/widgets/user_panel.dart +++ b/lib/pages/search_panel/widgets/user_panel.dart @@ -1,4 +1,5 @@ import 'package:PiliPalaX/common/widgets/http_error.dart'; +import 'package:PiliPalaX/common/widgets/loading_widget.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/pages/search/widgets/search_text.dart'; import 'package:PiliPalaX/pages/search_panel/controller.dart'; @@ -13,7 +14,7 @@ import 'package:PiliPalaX/utils/utils.dart'; import '../../../common/constants.dart'; import '../../../utils/grid.dart'; -Widget searchUserPanel(BuildContext context, searchPanelCtr, loadingState) { +Widget searchUserPanel(context, searchPanelCtr, LoadingState loadingState) { TextStyle style = TextStyle( fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, color: Theme.of(context).colorScheme.outline); @@ -73,85 +74,89 @@ Widget searchUserPanel(BuildContext context, searchPanelCtr, loadingState) { ), ), ), - loadingState is Success - ? SliverPadding( - padding: EdgeInsets.only( - bottom: StyleString.safeSpace + - MediaQuery.of(context).padding.bottom, - ), - sliver: SliverGrid( - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - mainAxisExtent: 56, + switch (loadingState) { + Loading() => errorWidget(), + Success() => (loadingState.response as List?)?.isNotEmpty == true + ? SliverPadding( + padding: EdgeInsets.only( + bottom: StyleString.safeSpace + + MediaQuery.of(context).padding.bottom, ), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - var i = loadingState.response[index]; - String heroTag = Utils.makeHeroTag(i!.mid); - return InkWell( - onTap: () => Get.toNamed('/member?mid=${i.mid}', - arguments: {'heroTag': heroTag, 'face': i.upic}), - child: Row( - children: [ - const SizedBox(width: 15), - Hero( - tag: heroTag, - child: NetworkImgLayer( + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + mainAxisExtent: 56, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + var i = loadingState.response[index]; + String heroTag = Utils.makeHeroTag(i!.mid); + return InkWell( + onTap: () => Get.toNamed('/member?mid=${i.mid}', + arguments: {'heroTag': heroTag, 'face': i.upic}), + child: Row( + children: [ + const SizedBox(width: 15), + NetworkImgLayer( width: 42, height: 42, src: i.upic, type: 'avatar', ), - ), - const SizedBox(width: 10), - Column( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - children: [ - Text( - i!.uname, - style: const TextStyle( - fontSize: 14, + const SizedBox(width: 10), + Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + children: [ + Text( + i!.uname, + style: const TextStyle( + fontSize: 14, + ), ), - ), - const SizedBox(width: 6), - Image.asset( - 'assets/images/lv/lv${i!.level}.png', - height: 11, - semanticLabel: '等级${i.level}', - ), - ], - ), - Row( - children: [ - Text('粉丝:${i.fans} ', style: style), - Text(' 视频:${i.videos}', style: style) - ], - ), - if (i.officialVerify['desc'] != '') - Text( - i.officialVerify['desc'], - style: style, + const SizedBox(width: 6), + Image.asset( + 'assets/images/lv/lv${i!.level}.png', + height: 11, + semanticLabel: '等级${i.level}', + ), + ], ), - ], - ) - ], - ), - ); - }, - childCount: loadingState.response.length, + Row( + children: [ + Text('粉丝:${i.fans} ', style: style), + Text(' 视频:${i.videos}', style: style) + ], + ), + if (i.officialVerify['desc'] != '') + Text( + i.officialVerify['desc'], + style: style, + ), + ], + ) + ], + ), + ); + }, + childCount: loadingState.response.length, + ), ), + ) + : HttpError( + callback: searchPanelCtr.onReload, ), - ) - : HttpError( - errMsg: loadingState is Error ? loadingState.errMsg : '没有相关数据', - callback: searchPanelCtr.onReload, - ) + Error() => HttpError( + errMsg: loadingState.errMsg, + callback: searchPanelCtr.onReload, + ), + LoadingState() => throw UnimplementedError(), + }, ], ); } diff --git a/lib/pages/search_panel/widgets/video_panel.dart b/lib/pages/search_panel/widgets/video_panel.dart index 757d539e1..8e21bb66a 100644 --- a/lib/pages/search_panel/widgets/video_panel.dart +++ b/lib/pages/search_panel/widgets/video_panel.dart @@ -1,4 +1,5 @@ import 'package:PiliPalaX/common/widgets/http_error.dart'; +import 'package:PiliPalaX/common/widgets/loading_widget.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/pages/search/widgets/search_text.dart'; import 'package:PiliPalaX/pages/video/detail/reply/view.dart' @@ -14,87 +15,76 @@ import 'package:intl/intl.dart'; import '../../../common/constants.dart'; import '../../../utils/grid.dart'; -class SearchVideoPanel extends StatelessWidget { - SearchVideoPanel({ - required this.ctr, - required this.loadingState, - super.key, - }); - - final SearchPanelController ctr; - final dynamic loadingState; - - final VideoPanelController controller = Get.put(VideoPanelController()); - - @override - Widget build(BuildContext context) { - return CustomScrollView( - controller: ctr.scrollController, - slivers: [ - SliverPersistentHeader( - pinned: false, - floating: true, - delegate: MySliverPersistentHeaderDelegate( - child: Container( - width: context.width, - height: 34, - color: Theme.of(context).colorScheme.surface, - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Row( - children: [ - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Obx( - () => Wrap( - // spacing: , - children: [ - for (var i in controller.filterList) ...[ - CustomFilterChip( - label: i['label'], - type: i['type'], - selectedType: controller.selectedType.value, - callFn: (bool selected) async { - debugPrint('selected: $selected'); - controller.selectedType.value = i['type']; - ctr.order.value = - i['type'].toString().split('.').last; - SmartDialog.showLoading(msg: 'loading'); - await ctr.onRefresh(); - SmartDialog.dismiss(); - }, - ), - ] - ], - ), +Widget searchVideoPanel(context, ctr, LoadingState loadingState) { + final controller = Get.put(VideoPanelController()); + return CustomScrollView( + controller: ctr.scrollController, + slivers: [ + SliverPersistentHeader( + pinned: false, + floating: true, + delegate: MySliverPersistentHeaderDelegate( + child: Container( + height: 34, + color: Theme.of(context).colorScheme.surface, + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Obx( + () => Wrap( + // spacing: , + children: [ + for (var i in controller.filterList) ...[ + CustomFilterChip( + label: i['label'], + type: i['type'], + selectedType: controller.selectedType.value, + callFn: (bool selected) async { + debugPrint('selected: $selected'); + controller.selectedType.value = i['type']; + ctr.order.value = + i['type'].toString().split('.').last; + SmartDialog.showLoading(msg: 'loading'); + await ctr.onRefresh(); + SmartDialog.dismiss(); + }, + ), + ] + ], ), ), ), - const VerticalDivider(indent: 7, endIndent: 8), - const SizedBox(width: 3), - SizedBox( - width: 32, - height: 32, - child: IconButton( - tooltip: '筛选', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () => - controller.onShowFilterDialog(context, ctr), - icon: Icon( - Icons.filter_list_outlined, - size: 18, - color: Theme.of(context).colorScheme.primary, - ), + ), + const VerticalDivider(indent: 7, endIndent: 8), + const SizedBox(width: 3), + SizedBox( + width: 32, + height: 32, + child: IconButton( + tooltip: '筛选', + style: ButtonStyle( + padding: WidgetStateProperty.all(EdgeInsets.zero), + ), + onPressed: () => + controller.onShowFilterDialog(context, ctr), + icon: Icon( + Icons.filter_list_outlined, + size: 18, + color: Theme.of(context).colorScheme.primary, ), ), - ], - ), + ), + ], ), ), ), - loadingState is Success + ), + switch (loadingState) { + Loading() => errorWidget(), + Success() => (loadingState.response as List?)?.isNotEmpty == true ? SliverPadding( padding: EdgeInsets.only( left: StyleString.safeSpace, @@ -122,12 +112,16 @@ class SearchVideoPanel extends StatelessWidget { ), ) : HttpError( - errMsg: loadingState is Error ? loadingState.errMsg : '没有相关数据', callback: ctr.onReload, ), - ], - ); - } + Error() => HttpError( + errMsg: loadingState.errMsg, + callback: ctr.onReload, + ), + _ => throw UnimplementedError(), + }, + ], + ); } class CustomFilterChip extends StatelessWidget { diff --git a/lib/pages/video/detail/related/view.dart b/lib/pages/video/detail/related/view.dart index a6d5b97d9..c0d7f5d4c 100644 --- a/lib/pages/video/detail/related/view.dart +++ b/lib/pages/video/detail/related/view.dart @@ -87,9 +87,7 @@ class _RelatedVideoPanelState extends State } }, childCount: loadingState.response.length + 1), ) - : HttpError( - callback: _relatedController.onReload, - ), + : SliverToBoxAdapter(), Error() => HttpError( errMsg: loadingState.errMsg, callback: _relatedController.onReload,