diff --git a/lib/common/widgets/image/network_img_layer.dart b/lib/common/widgets/image/network_img_layer.dart index f1623ba7..4c9dbb0d 100644 --- a/lib/common/widgets/image/network_img_layer.dart +++ b/lib/common/widgets/image/network_img_layer.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; @@ -10,7 +11,7 @@ class NetworkImgLayer extends StatelessWidget { this.src, required this.width, this.height, - this.type, + this.type = ImageType.def, this.fadeOutDuration, this.fadeInDuration, // 图片质量 默认1% @@ -27,7 +28,7 @@ class NetworkImgLayer extends StatelessWidget { final String? src; final double width; final double? height; - final String? type; + final ImageType type; final Duration? fadeOutDuration; final Duration? fadeInDuration; final int? quality; @@ -42,9 +43,9 @@ class NetworkImgLayer extends StatelessWidget { @override Widget build(BuildContext context) { return src.isNullOrEmpty.not - ? type == 'avatar' + ? type == ImageType.avatar ? ClipOval(child: _buildImage(context)) - : radius == 0 || type == 'emote' + : radius == 0 || type == ImageType.emote ? _buildImage(context) : ClipRRect( borderRadius: radius != null @@ -86,19 +87,20 @@ class NetworkImgLayer extends StatelessWidget { height: height, clipBehavior: Clip.antiAlias, decoration: BoxDecoration( - shape: type == 'avatar' ? BoxShape.circle : BoxShape.rectangle, + shape: type == ImageType.avatar ? BoxShape.circle : BoxShape.rectangle, color: Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.4), - borderRadius: type == 'avatar' || type == 'emote' || radius == 0 - ? null - : radius != null - ? BorderRadius.circular(radius!) - : StyleString.mdRadius, + borderRadius: + type == ImageType.avatar || type == ImageType.emote || radius == 0 + ? null + : radius != null + ? BorderRadius.circular(radius!) + : StyleString.mdRadius, ), child: type == 'bg' ? const SizedBox.shrink() : Center( child: Image.asset( - type == 'avatar' + type == ImageType.avatar ? 'assets/images/noface.jpeg' : 'assets/images/loading.png', width: width, diff --git a/lib/common/widgets/pendant_avatar.dart b/lib/common/widgets/pendant_avatar.dart index 8836b19f..2e3b8add 100644 --- a/lib/common/widgets/pendant_avatar.dart +++ b/lib/common/widgets/pendant_avatar.dart @@ -1,5 +1,6 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/models/common/avatar_badge_type.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -120,7 +121,7 @@ class PendantAvatar extends StatelessWidget { src: avatar, width: size, height: size, - type: 'avatar', + type: ImageType.avatar, ), ), ) @@ -128,7 +129,7 @@ class PendantAvatar extends StatelessWidget { src: avatar, width: size, height: size, - type: 'avatar', + type: ImageType.avatar, ); Widget _buildBadge(ColorScheme colorScheme) { diff --git a/lib/models/common/image_type.dart b/lib/models/common/image_type.dart new file mode 100644 index 00000000..464508b1 --- /dev/null +++ b/lib/models/common/image_type.dart @@ -0,0 +1 @@ +enum ImageType { avatar, emote, def } diff --git a/lib/pages/article/view.dart b/lib/pages/article/view.dart index 89e4b476..3da6d1d9 100644 --- a/lib/pages/article/view.dart +++ b/lib/pages/article/view.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; import 'package:PiliPlus/models/common/image_preview_type.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/common/reply/reply_sort_type.dart'; import 'package:PiliPlus/models/common/reply/reply_type.dart'; import 'package:PiliPlus/models/dynamics/result.dart' show DynamicStat; @@ -486,7 +487,7 @@ class _ArticlePageState extends State // TODO Avatar width: 40, height: 40, - type: 'avatar', + type: ImageType.avatar, src: _articleCtr.summary.author?.face, ), const SizedBox(width: 10), diff --git a/lib/pages/article_list/controller.dart b/lib/pages/article_list/controller.dart index 7c24b99d..6f615106 100644 --- a/lib/pages/article_list/controller.dart +++ b/lib/pages/article_list/controller.dart @@ -17,12 +17,12 @@ class ArticleListController queryData(); } - ArticleList? list; + Rx list = Rx(null); Author? author; @override List
? getDataList(ArticleListData response) { - list = response.list; + list.value = response.list; author = response.author; return response.articles; } diff --git a/lib/pages/article_list/view.dart b/lib/pages/article_list/view.dart index 35b85810..cc58c3c8 100644 --- a/lib/pages/article_list/view.dart +++ b/lib/pages/article_list/view.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/dynamics/article_list/article.dart'; import 'package:PiliPlus/models/dynamics/article_list/list.dart'; import 'package:PiliPlus/pages/article_list/controller.dart'; @@ -35,6 +36,7 @@ class _ArticleListPageState extends State { onRefresh: _controller.onRefresh, child: CustomScrollView( slivers: [ + Obx(() => _buildHeader(theme, _controller.list.value)), SliverPadding( padding: EdgeInsets.only( bottom: MediaQuery.paddingOf(context).bottom + 80), @@ -64,31 +66,24 @@ class _ArticleListPageState extends State { ), ), ), - Success() => SliverMainAxisGroup( - slivers: [ - if (_controller.list != null) - _buildHeader(theme, _controller.list!), - if (loadingState.response?.isNotEmpty == true) - SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: 2, - maxCrossAxisExtent: Grid.smallCardWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.6, - minHeight: MediaQuery.textScalerOf(context).scale(90), - ), - delegate: SliverChildBuilderDelegate( - (context, index) { - return ArticleListItem( - item: loadingState.response![index], - ); - }, - childCount: loadingState.response!.length, - ), - ) - else - HttpError(onReload: _controller.onReload), - ], - ), + Success() => loadingState.response?.isNotEmpty == true + ? SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: 2, + maxCrossAxisExtent: Grid.smallCardWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.6, + minHeight: MediaQuery.textScalerOf(context).scale(90), + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return ArticleListItem( + item: loadingState.response![index], + ); + }, + childCount: loadingState.response!.length, + ), + ) + : HttpError(onReload: _controller.onReload), Error() => HttpError( errMsg: loadingState.errMsg, onReload: _controller.onReload, @@ -96,7 +91,10 @@ class _ArticleListPageState extends State { }; } - Widget _buildHeader(ThemeData theme, ArticleList item) { + Widget _buildHeader(ThemeData theme, ArticleList? item) { + if (item == null) { + return const SliverToBoxAdapter(); + } late final style = TextStyle(color: theme.colorScheme.onSurfaceVariant); late final divider = TextSpan( text: ' | ', @@ -105,6 +103,7 @@ class _ArticleListPageState extends State { final padding = MediaQuery.paddingOf(context).top + kToolbarHeight; return SliverAppBar.medium( title: Text(item.name!), + pinned: true, expandedHeight: kToolbarHeight + 130, flexibleSpace: FlexibleSpaceBar( background: Container( @@ -117,14 +116,15 @@ class _ArticleListPageState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (item.imageUrl?.isNotEmpty == true) + if (item.imageUrl?.isNotEmpty == true) ...[ NetworkImgLayer( width: 91, height: 120, src: item.imageUrl, radius: 6, ), - const SizedBox(width: 10), + const SizedBox(width: 10), + ], Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -149,6 +149,7 @@ class _ArticleListPageState extends State { width: 30, height: 30, src: _controller.author!.face, + type: ImageType.avatar, ), const SizedBox(width: 10), Text(_controller.author!.name!), @@ -162,9 +163,9 @@ class _ArticleListPageState extends State { children: [ TextSpan(text: '${item.articlesCount}篇专栏'), divider, - TextSpan(text: '${item.words}个字'), + TextSpan(text: '${Utils.numFormat(item.words)}个字'), divider, - TextSpan(text: '${item.read}次阅读'), + TextSpan(text: '${Utils.numFormat(item.read)}次阅读'), ], style: style, ), diff --git a/lib/pages/blacklist/view.dart b/lib/pages/blacklist/view.dart index 20444d04..a6b8ee02 100644 --- a/lib/pages/blacklist/view.dart +++ b/lib/pages/blacklist/view.dart @@ -3,6 +3,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/user/black.dart'; import 'package:PiliPlus/pages/blacklist/controller.dart'; import 'package:PiliPlus/utils/storage.dart'; @@ -75,7 +76,7 @@ class _BlackListPageState extends State { leading: NetworkImgLayer( width: 45, height: 45, - type: 'avatar', + type: ImageType.avatar, src: item.face, ), title: Text( diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index 3b94e5e5..9f0b6de8 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -3,6 +3,7 @@ import 'package:PiliPlus/common/widgets/badge.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/image_view.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/pages/article/widgets/opus_content.dart'; import 'package:PiliPlus/pages/dynamics/widgets/additional_panel.dart'; @@ -332,7 +333,6 @@ Widget forWard( child: Row( children: [ NetworkImgLayer( - type: 'cover', radius: 8, width: 45, height: 45, @@ -382,7 +382,6 @@ Widget forWard( child: Row( children: [ NetworkImgLayer( - type: 'cover', radius: 8, width: 45, height: 45, @@ -432,7 +431,7 @@ Widget forWard( NetworkImgLayer( width: 28, height: 28, - type: 'avatar', + type: ImageType.avatar, src: item.modules.moduleAuthor!.face, ), const SizedBox(width: 10), diff --git a/lib/pages/dynamics/widgets/rich_node_panel.dart b/lib/pages/dynamics/widgets/rich_node_panel.dart index 0651fb2f..b7b9244e 100644 --- a/lib/pages/dynamics/widgets/rich_node_panel.dart +++ b/lib/pages/dynamics/widgets/rich_node_panel.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/common/widgets/image/image_view.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/http/search.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/pages/dynamics/widgets/vote.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; @@ -136,7 +137,7 @@ TextSpan? richNode( WidgetSpan( child: NetworkImgLayer( src: i.emoji!.webpUrl ?? i.emoji!.gifUrl ?? i.emoji!.iconUrl, - type: 'emote', + type: ImageType.emote, width: (i.emoji!.size ?? 1) * 20, height: (i.emoji!.size ?? 1) * 20, ), diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index e0e5c197..2f34d426 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/dynamics/up.dart'; import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/utils/extension.dart'; @@ -150,7 +151,7 @@ class _UpPanelState extends State { width: 38, height: 38, src: data.face, - type: 'avatar', + type: ImageType.avatar, ) : const CircleAvatar( backgroundColor: Color(0xFF5CB67B), diff --git a/lib/pages/emote/view.dart b/lib/pages/emote/view.dart index 6f8d05de..759988fd 100644 --- a/lib/pages/emote/view.dart +++ b/lib/pages/emote/view.dart @@ -2,6 +2,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/video/reply/emote.dart'; import 'package:PiliPlus/pages/emote/controller.dart'; import 'package:flutter/material.dart'; @@ -78,7 +79,7 @@ class _EmotePanelState extends State width: size * 38, height: size * 38, semanticsLabel: e.emote![index].text!, - type: 'emote', + type: ImageType.emote, boxFit: BoxFit.contain, ), ), @@ -107,7 +108,7 @@ class _EmotePanelState extends State child: NetworkImgLayer( width: 24, height: 24, - type: 'emote', + type: ImageType.emote, src: e.url, ), ), diff --git a/lib/pages/fan/view.dart b/lib/pages/fan/view.dart index d3375e19..3da452c4 100644 --- a/lib/pages/fan/view.dart +++ b/lib/pages/fan/view.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/fans/result.dart'; import 'package:PiliPlus/pages/fan/controller.dart'; import 'package:PiliPlus/pages/share/view.dart' show UserModel; @@ -132,7 +133,7 @@ class _FansPageState extends State { child: NetworkImgLayer( width: 45, height: 45, - type: 'avatar', + type: ImageType.avatar, src: item.face, ), ), diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index 4da58cfc..66fb8387 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -18,7 +18,6 @@ class FavDetailController late int mediaId; late String heroTag; RxBool isOwner = false.obs; - RxBool titleCtr = false.obs; dynamic mid; diff --git a/lib/pages/fav_detail/view.dart b/lib/pages/fav_detail/view.dart index 41325753..b5162e5e 100644 --- a/lib/pages/fav_detail/view.dart +++ b/lib/pages/fav_detail/view.dart @@ -36,18 +36,6 @@ class _FavDetailPageState extends State { void initState() { super.initState(); mediaId = Get.parameters['mediaId']!; - _favDetailController.scrollController.addListener(listener); - } - - void listener() { - _favDetailController.titleCtr.value = - _favDetailController.scrollController.offset >= 130; - } - - @override - void dispose() { - _favDetailController.scrollController.removeListener(listener); - super.dispose(); } @override @@ -81,323 +69,280 @@ class _FavDetailPageState extends State { physics: const AlwaysScrollableScrollPhysics(), controller: _favDetailController.scrollController, slivers: [ - SliverAppBar( - leading: _favDetailController.enableMultiSelect.value - ? IconButton( - tooltip: '取消', - onPressed: _favDetailController.handleSelect, - icon: const Icon(Icons.close_outlined), - ) - : null, - expandedHeight: kToolbarHeight + 130, - pinned: true, - title: _favDetailController.enableMultiSelect.value - ? Text( - '已选: ${_favDetailController.checkedCount.value}', - ) - : Obx( - () => AnimatedOpacity( - opacity: - _favDetailController.titleCtr.value ? 1 : 0, - curve: Curves.easeOut, - duration: const Duration(milliseconds: 500), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _favDetailController.item.value.title ?? '', - style: theme.textTheme.titleMedium, - ), - Text( - '共${_favDetailController.item.value.mediaCount}条视频', - style: theme.textTheme.labelMedium, - ) - ], - ), - ), + _buildHeader(theme), + Obx(() => _buildBody( + theme, _favDetailController.loadingState.value)), + ], + ), + ), + ), + ), + ), + ); + } + + Widget _buildHeader(ThemeData theme) { + return SliverAppBar.medium( + leading: _favDetailController.enableMultiSelect.value + ? IconButton( + tooltip: '取消', + onPressed: _favDetailController.handleSelect, + icon: const Icon(Icons.close_outlined), + ) + : null, + expandedHeight: kToolbarHeight + 130, + pinned: true, + title: _favDetailController.enableMultiSelect.value + ? Text('已选: ${_favDetailController.checkedCount.value}') + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _favDetailController.item.value.title ?? '', + style: theme.textTheme.titleMedium, + ), + Text( + '共${_favDetailController.item.value.mediaCount}条视频', + style: theme.textTheme.labelMedium, + ) + ], + ), + actions: _favDetailController.enableMultiSelect.value + ? [ + TextButton( + style: TextButton.styleFrom( + visualDensity: VisualDensity.compact, + ), + onPressed: () => _favDetailController.handleSelect(true), + child: const Text('全选'), + ), + TextButton( + style: TextButton.styleFrom( + visualDensity: VisualDensity.compact, + ), + onPressed: () { + RequestUtils.onCopyOrMove( + context: context, + isCopy: true, + ctr: _favDetailController, + mediaId: _favDetailController.mediaId, + mid: _favDetailController.mid, + ); + }, + child: Text( + '复制', + style: TextStyle( + color: theme.colorScheme.onSurfaceVariant, + ), + ), + ), + TextButton( + style: TextButton.styleFrom( + visualDensity: VisualDensity.compact, + ), + onPressed: () { + RequestUtils.onCopyOrMove( + context: context, + isCopy: false, + ctr: _favDetailController, + mediaId: _favDetailController.mediaId, + mid: _favDetailController.mid, + ); + }, + child: Text( + '移动', + style: TextStyle( + color: theme.colorScheme.onSurfaceVariant, + ), + ), + ), + TextButton( + style: TextButton.styleFrom( + visualDensity: VisualDensity.compact, + ), + onPressed: () => _favDetailController.onDelChecked(context), + child: Text( + '删除', + style: TextStyle(color: theme.colorScheme.error), + ), + ), + const SizedBox(width: 6), + ] + : [ + IconButton( + tooltip: '搜索', + onPressed: () => Get.toNamed( + '/favSearch', + arguments: { + 'type': 0, + 'mediaId': int.parse(mediaId), + 'title': _favDetailController.item.value.title, + 'count': _favDetailController.item.value.mediaCount, + 'isOwner': _favDetailController.isOwner.value, + }, + ), + icon: const Icon(Icons.search_outlined), + ), + Obx( + () => _favDetailController.isOwner.value + ? PopupMenuButton( + icon: const Icon(Icons.more_vert), + itemBuilder: (context) => [ + PopupMenuItem( + onTap: () { + Get.toNamed( + '/createFav', + parameters: {'mediaId': mediaId}, + )?.then((res) { + if (res is FavFolderItemData) { + _favDetailController.item.value = res; + } + }); + }, + child: const Text('编辑信息'), ), - actions: _favDetailController.enableMultiSelect.value - ? [ - TextButton( - style: TextButton.styleFrom( - visualDensity: VisualDensity.compact, - ), - onPressed: () => - _favDetailController.handleSelect(true), - child: const Text('全选'), - ), - TextButton( - style: TextButton.styleFrom( - visualDensity: VisualDensity.compact, - ), - onPressed: () { - RequestUtils.onCopyOrMove( + PopupMenuItem( + onTap: () { + UserHttp.cleanFav(mediaId: mediaId).then((data) { + if (data['status']) { + SmartDialog.showToast('清除成功'); + Future.delayed( + const Duration(milliseconds: 200), () { + _favDetailController.onReload(); + }); + } else { + SmartDialog.showToast(data['msg']); + } + }); + }, + child: const Text('清除失效内容'), + ), + PopupMenuItem( + onTap: () { + if (_favDetailController.loadingState.value + is Success && + ((_favDetailController.loadingState.value + as Success) + .response as List?) + ?.isNotEmpty == + true) { + if ((_favDetailController + .item.value.mediaCount ?? + 0) > + 1000) { + SmartDialog.showToast('内容太多啦!超过1000不支持排序'); + return; + } + Get.to( + FavSortPage( + favDetailController: + _favDetailController), + ); + } + }, + child: const Text('排序'), + ), + if (!Utils.isDefaultFav( + _favDetailController.item.value.attr ?? 0)) + PopupMenuItem( + onTap: () { + showConfirmDialog( context: context, - isCopy: true, - ctr: _favDetailController, - mediaId: _favDetailController.mediaId, - mid: _favDetailController.mid, + title: '确定删除该收藏夹?', + onConfirm: () { + UserHttp.deleteFolder(mediaIds: [mediaId]) + .then((data) { + if (data['status']) { + SmartDialog.showToast('删除成功'); + Get.back(result: true); + } else { + SmartDialog.showToast(data['msg']); + } + }); + }, ); }, - child: Text( - '复制', - style: TextStyle( - color: theme.colorScheme.onSurfaceVariant, - ), - ), - ), - TextButton( - style: TextButton.styleFrom( - visualDensity: VisualDensity.compact, - ), - onPressed: () { - RequestUtils.onCopyOrMove( - context: context, - isCopy: false, - ctr: _favDetailController, - mediaId: _favDetailController.mediaId, - mid: _favDetailController.mid, - ); - }, - child: Text( - '移动', - style: TextStyle( - color: theme.colorScheme.onSurfaceVariant, - ), - ), - ), - TextButton( - style: TextButton.styleFrom( - visualDensity: VisualDensity.compact, - ), - onPressed: () => - _favDetailController.onDelChecked(context), child: Text( '删除', - style: - TextStyle(color: theme.colorScheme.error), + style: TextStyle( + color: theme.colorScheme.error, + ), ), ), - const SizedBox(width: 6), - ] - : [ - IconButton( - tooltip: '搜索', - onPressed: () => Get.toNamed( - '/favSearch', - arguments: { - 'type': 0, - 'mediaId': int.parse(mediaId), - 'title': - _favDetailController.item.value.title, - 'count': _favDetailController - .item.value.mediaCount, - 'isOwner': _favDetailController.isOwner.value, - }, - ), - icon: const Icon(Icons.search_outlined), - ), - Obx( - () => _favDetailController.isOwner.value - ? PopupMenuButton( - icon: const Icon(Icons.more_vert), - itemBuilder: (context) => [ - PopupMenuItem( - onTap: () { - Get.toNamed( - '/createFav', - parameters: {'mediaId': mediaId}, - )?.then((res) { - if (res is FavFolderItemData) { - _favDetailController - .item.value = res; - } - }); - }, - child: const Text('编辑信息'), - ), - PopupMenuItem( - onTap: () { - UserHttp.cleanFav(mediaId: mediaId) - .then((data) { - if (data['status']) { - SmartDialog.showToast('清除成功'); - Future.delayed( - const Duration( - milliseconds: 200), () { - _favDetailController - .onReload(); - }); - } else { - SmartDialog.showToast( - data['msg']); - } - }); - }, - child: const Text('清除失效内容'), - ), - PopupMenuItem( - onTap: () { - if (_favDetailController - .loadingState - .value is Success && - ((_favDetailController - .loadingState - .value - as Success) - .response as List?) - ?.isNotEmpty == - true) { - if ((_favDetailController.item - .value.mediaCount ?? - 0) > - 1000) { - SmartDialog.showToast( - '内容太多啦!超过1000不支持排序'); - return; - } - Get.to( - FavSortPage( - favDetailController: - _favDetailController), - ); - } - }, - child: const Text('排序'), - ), - if (!Utils.isDefaultFav( - _favDetailController - .item.value.attr ?? - 0)) - PopupMenuItem( - onTap: () { - showConfirmDialog( - context: context, - title: '确定删除该收藏夹?', - onConfirm: () { - UserHttp.deleteFolder( - mediaIds: [mediaId]) - .then((data) { - if (data['status']) { - SmartDialog.showToast( - '删除成功'); - Get.back(result: true); - } else { - SmartDialog.showToast( - data['msg']); - } - }); - }, - ); - }, - child: Text( - '删除', - style: TextStyle( - color: theme.colorScheme.error, - ), - ), - ), - ], - ) - : const SizedBox.shrink(), - ), - const SizedBox(width: 6), - ], - flexibleSpace: FlexibleSpaceBar( - background: Padding( - padding: EdgeInsets.only( - top: kToolbarHeight + - MediaQuery.of(context).padding.top + - 10, - left: 14, - right: 20, - bottom: 10, - ), - child: SizedBox( - height: 110, - child: Obx( - () => Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Hero( - tag: _favDetailController.heroTag, - child: NetworkImgLayer( - width: 176, - height: 110, - src: _favDetailController.item.value.cover, - ), - ), - const SizedBox(width: 14), - Expanded( - child: SizedBox( - height: 110, - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - const SizedBox(height: 4), - Text( - _favDetailController - .item.value.title ?? - '', - style: TextStyle( - fontSize: theme.textTheme - .titleMedium!.fontSize, - fontWeight: FontWeight.bold), - ), - if (_favDetailController - .item.value.intro?.isNotEmpty == - true) - Text( - _favDetailController - .item.value.intro ?? - '', - style: TextStyle( - fontSize: theme.textTheme - .labelSmall!.fontSize, - color: - theme.colorScheme.outline), - ), - const SizedBox(height: 4), - Text( - _favDetailController - .item.value.upper?.name ?? - '', - style: TextStyle( - fontSize: theme.textTheme - .labelSmall!.fontSize, - color: theme.colorScheme.outline), - ), - const Spacer(), - if (_favDetailController - .item.value.attr != - null) - Text( - '共${_favDetailController.item.value.mediaCount}条视频 · ${Utils.isPublicFavText(_favDetailController.item.value.attr ?? 0)}', - style: TextStyle( - fontSize: theme.textTheme - .labelSmall!.fontSize, - color: - theme.colorScheme.outline), - ), - ], - ), - ), - ), - ], - ), + ], + ) + : const SizedBox.shrink(), + ), + const SizedBox(width: 6), + ], + flexibleSpace: FlexibleSpaceBar( + background: Padding( + padding: EdgeInsets.only( + top: kToolbarHeight + MediaQuery.of(context).padding.top + 10, + left: 14, + right: 20, + bottom: 10, + ), + child: SizedBox( + height: 110, + child: Obx( + () => Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Hero( + tag: _favDetailController.heroTag, + child: NetworkImgLayer( + width: 176, + height: 110, + src: _favDetailController.item.value.cover, + ), + ), + const SizedBox(width: 14), + Expanded( + child: SizedBox( + height: 110, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 4), + Text( + _favDetailController.item.value.title ?? '', + style: TextStyle( + fontSize: theme.textTheme.titleMedium!.fontSize, + fontWeight: FontWeight.bold), ), - ), + if (_favDetailController + .item.value.intro?.isNotEmpty == + true) + Text( + _favDetailController.item.value.intro ?? '', + style: TextStyle( + fontSize: + theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline), + ), + const SizedBox(height: 4), + Text( + _favDetailController.item.value.upper?.name ?? '', + style: TextStyle( + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline), + ), + const Spacer(), + if (_favDetailController.item.value.attr != null) + Text( + '共${_favDetailController.item.value.mediaCount}条视频 · ${Utils.isPublicFavText(_favDetailController.item.value.attr ?? 0)}', + style: TextStyle( + fontSize: + theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline), + ), + ], ), ), ), - Obx(() => _buildBody( - theme, _favDetailController.loadingState.value)), ], ), ), diff --git a/lib/pages/follow/widgets/follow_item.dart b/lib/pages/follow/widgets/follow_item.dart index 0d4349cb..10533cdd 100644 --- a/lib/pages/follow/widgets/follow_item.dart +++ b/lib/pages/follow/widgets/follow_item.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/follow/result.dart'; import 'package:PiliPlus/pages/share/view.dart' show UserModel; import 'package:PiliPlus/utils/feed_back.dart'; @@ -49,7 +50,7 @@ class FollowItem extends StatelessWidget { child: NetworkImgLayer( width: 45, height: 45, - type: 'avatar', + type: ImageType.avatar, src: item.face, ), ), diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index 575f53e6..3356c532 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -2,6 +2,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/models/common/dynamic/dynamic_badge_mode.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/home/controller.dart'; import 'package:PiliPlus/pages/main/controller.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; @@ -98,7 +99,7 @@ class _HomePageState extends State clipBehavior: Clip.none, children: [ NetworkImgLayer( - type: 'avatar', + type: ImageType.avatar, width: 34, height: 34, src: _homeController.userFace.value, diff --git a/lib/pages/live/view.dart b/lib/pages/live/view.dart index 645360c0..ec216b97 100644 --- a/lib/pages/live/view.dart +++ b/lib/pages/live/view.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/common/widgets/pair.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/live/live_feed_index/card_data_list_item.dart'; import 'package:PiliPlus/models/live/live_feed_index/card_list.dart'; import 'package:PiliPlus/pages/common/common_page.dart'; @@ -311,7 +312,7 @@ class _LivePageState extends CommonPageState shape: BoxShape.circle, ), child: NetworkImgLayer( - type: 'avatar', + type: ImageType.avatar, width: 45, height: 45, src: item.face, diff --git a/lib/pages/live_area/view.dart b/lib/pages/live_area/view.dart index 48b6504e..03816c75 100644 --- a/lib/pages/live_area/view.dart +++ b/lib/pages/live_area/view.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/live/live_area_list/area_item.dart'; import 'package:PiliPlus/models/live/live_area_list/area_list.dart'; import 'package:PiliPlus/pages/live_area/controller.dart'; @@ -258,7 +259,7 @@ class _LiveAreaPageState extends State { width: 45, height: 45, src: item.pic, - type: 'emote', + type: ImageType.emote, ), const SizedBox(height: 4), Text( diff --git a/lib/pages/live_area_detail/view.dart b/lib/pages/live_area_detail/view.dart index b5f167a0..3250595f 100644 --- a/lib/pages/live_area_detail/view.dart +++ b/lib/pages/live_area_detail/view.dart @@ -2,6 +2,7 @@ import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/live/live_area_list/area_item.dart'; import 'package:PiliPlus/pages/live_area_detail/child/view.dart'; import 'package:PiliPlus/pages/live_area_detail/controller.dart'; @@ -131,7 +132,7 @@ class _LiveAreaDetailPageState extends State { width: 45, height: 45, src: item.pic, - type: 'emote', + type: ImageType.emote, ), const SizedBox(height: 4), Text( diff --git a/lib/pages/live_emote/view.dart b/lib/pages/live_emote/view.dart index 355d2ff2..0fb74766 100644 --- a/lib/pages/live_emote/view.dart +++ b/lib/pages/live_emote/view.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/live/live_emoticons/datum.dart'; import 'package:PiliPlus/models/live/live_emoticons/emoticon.dart'; import 'package:PiliPlus/pages/live_emote/controller.dart'; @@ -93,7 +94,7 @@ class _LiveEmotePanelState extends State src: item.emoticons![index].url!, width: widthFac * 38, height: heightFac * 38, - type: 'emote', + type: ImageType.emote, quality: item.pkgType == 3 ? null : 80, ), ), @@ -122,7 +123,7 @@ class _LiveEmotePanelState extends State child: NetworkImgLayer( width: 24, height: 24, - type: 'emote', + type: ImageType.emote, src: item.currentCover, ), ), diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index 1a8a2aa1..925857ee 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'dart:ui'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/live/live_room/room_info_h5.dart'; import 'package:PiliPlus/pages/live_room/controller.dart'; import 'package:PiliPlus/pages/live_room/send_danmaku/view.dart'; @@ -386,7 +387,7 @@ class _LiveRoomPageState extends State child: NetworkImgLayer( width: 34, height: 34, - type: 'avatar', + type: ImageType.avatar, src: _liveRoomController .roomInfoH5.value!.anchorInfo!.baseInfo!.face, ), diff --git a/lib/pages/live_room/widgets/chat.dart b/lib/pages/live_room/widgets/chat.dart index 7630f450..0f9afd95 100644 --- a/lib/pages/live_room/widgets/chat.dart +++ b/lib/pages/live_room/widgets/chat.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/live_room/controller.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/gestures.dart'; @@ -126,7 +127,7 @@ class LiveRoomChat extends StatelessWidget { child: ExcludeSemantics( child: NetworkImgLayer( src: emote['url'], - type: 'emote', + type: ImageType.emote, width: emote['width'].toDouble(), height: emote['height'].toDouble(), semanticsLabel: key, diff --git a/lib/pages/live_search/widgets/live_search_user.dart b/lib/pages/live_search/widgets/live_search_user.dart index cad9ae97..2b916960 100644 --- a/lib/pages/live_search/widgets/live_search_user.dart +++ b/lib/pages/live_search/widgets/live_search_user.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/live/live_search/user_item.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -30,7 +31,7 @@ class LiveSearchUserItem extends StatelessWidget { src: item.face, width: 42, height: 42, - type: 'avatar', + type: ImageType.avatar, ), const SizedBox(width: 10), Column( diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index 7315a61a..d626630b 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/tabs.dart'; import 'package:PiliPlus/models/common/dynamic/dynamic_badge_mode.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/pages/dynamics/view.dart'; import 'package:PiliPlus/pages/home/controller.dart'; @@ -435,7 +436,7 @@ class _MainAppState extends State clipBehavior: Clip.none, children: [ NetworkImgLayer( - type: 'avatar', + type: ImageType.avatar, width: 34, height: 34, src: _homeController.userFace.value, diff --git a/lib/pages/member_opus/widgets/space_opus_item.dart b/lib/pages/member_opus/widgets/space_opus_item.dart index c20ce502..80cc7596 100644 --- a/lib/pages/member_opus/widgets/space_opus_item.dart +++ b/lib/pages/member_opus/widgets/space_opus_item.dart @@ -1,5 +1,6 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/stat/stat.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/space_opus/item.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; @@ -38,7 +39,7 @@ class SpaceOpusItem extends StatelessWidget { width: constraints.maxWidth, height: constraints.maxWidth * item.cover!.ratio, src: item.cover!.url, - type: 'emote', + type: ImageType.emote, quality: 60, ); }, diff --git a/lib/pages/msg_feed_top/at_me/view.dart b/lib/pages/msg_feed_top/at_me/view.dart index f338ef1b..7892e6c1 100644 --- a/lib/pages/msg_feed_top/at_me/view.dart +++ b/lib/pages/msg_feed_top/at_me/view.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/grpc/bilibili/app/im/v1.pbenum.dart' show IMSettingType; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/msg/msgfeed_at_me.dart'; import 'package:PiliPlus/pages/msg_feed_top/at_me/controller.dart'; import 'package:PiliPlus/pages/whisper_settings/view.dart'; @@ -100,7 +101,7 @@ class _AtMePageState extends State { child: NetworkImgLayer( width: 45, height: 45, - type: 'avatar', + type: ImageType.avatar, src: item.user?.avatar, ), ), @@ -147,7 +148,6 @@ class _AtMePageState extends State { ? NetworkImgLayer( width: 45, height: 45, - type: 'cover', src: item.item?.image, ) : null, diff --git a/lib/pages/msg_feed_top/like_me/view.dart b/lib/pages/msg_feed_top/like_me/view.dart index 5dd0c987..5ef7ad00 100644 --- a/lib/pages/msg_feed_top/like_me/view.dart +++ b/lib/pages/msg_feed_top/like_me/view.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/grpc/bilibili/app/im/v1.pbenum.dart' show IMSettingType; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/msg/msgfeed_like_me.dart'; import 'package:PiliPlus/pages/msg_feed_top/like_me/controller.dart'; import 'package:PiliPlus/pages/whisper_settings/view.dart'; @@ -255,7 +256,7 @@ class _LikeMePageState extends State { child: NetworkImgLayer( width: item.users!.length > 1 ? 30 : 45, height: item.users!.length > 1 ? 30 : 45, - type: 'avatar', + type: ImageType.avatar, src: item.users![j].avatar, )), ] @@ -319,7 +320,6 @@ class _LikeMePageState extends State { NetworkImgLayer( width: 45, height: 45, - type: 'cover', src: item.item!.image, ), if (item.noticeState == 1) diff --git a/lib/pages/msg_feed_top/reply_me/view.dart b/lib/pages/msg_feed_top/reply_me/view.dart index ff0cd638..42b26528 100644 --- a/lib/pages/msg_feed_top/reply_me/view.dart +++ b/lib/pages/msg_feed_top/reply_me/view.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/grpc/bilibili/app/im/v1.pbenum.dart' show IMSettingType; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/msg/msgfeed_reply_me.dart'; import 'package:PiliPlus/pages/msg_feed_top/reply_me/controller.dart'; import 'package:PiliPlus/pages/whisper_settings/view.dart'; @@ -105,7 +106,7 @@ class _ReplyMePageState extends State { child: NetworkImgLayer( width: 45, height: 45, - type: 'avatar', + type: ImageType.avatar, src: item.user?.avatar, ), ), diff --git a/lib/pages/search_panel/live/widgets/item.dart b/lib/pages/search_panel/live/widgets/item.dart index c81672ae..f960f2ee 100644 --- a/lib/pages/search_panel/live/widgets/item.dart +++ b/lib/pages/search_panel/live/widgets/item.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/image/image_save.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -37,7 +38,7 @@ class LiveItem extends StatelessWidget { children: [ NetworkImgLayer( src: liveItem.cover, - type: 'emote', + type: ImageType.emote, width: maxWidth, height: maxHeight, ), diff --git a/lib/pages/share/view.dart b/lib/pages/share/view.dart index 366d841d..1d1c7d48 100644 --- a/lib/pages/share/view.dart +++ b/lib/pages/share/view.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/contact/view.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/request_utils.dart'; @@ -130,7 +131,7 @@ class _SharePanelState extends State { width: 40, height: 40, src: _userList[index].avatar, - type: 'avatar', + type: ImageType.avatar, ), ), const SizedBox(height: 2), diff --git a/lib/pages/subscription_detail/view.dart b/lib/pages/subscription_detail/view.dart index 0b108813..2fc19cac 100644 --- a/lib/pages/subscription_detail/view.dart +++ b/lib/pages/subscription_detail/view.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/common/skeleton/video_card_h.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; +import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/user/sub_detail.dart'; import 'package:PiliPlus/models/user/sub_folder.dart'; @@ -23,23 +24,6 @@ class _SubDetailPageState extends State { SubDetailController(), tag: Utils.makeHeroTag(Get.parameters['id']), ); - final RxBool showTitle = false.obs; - - @override - void initState() { - super.initState(); - _subDetailController.scrollController.addListener(listener); - } - - void listener() { - showTitle.value = _subDetailController.scrollController.offset > 132; - } - - @override - void dispose() { - _subDetailController.scrollController.removeListener(listener); - super.dispose(); - } @override Widget build(BuildContext context) { @@ -48,14 +32,17 @@ class _SubDetailPageState extends State { body: SafeArea( top: false, bottom: false, - child: CustomScrollView( - controller: _subDetailController.scrollController, - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - _buildAppBar(theme), - _buildCount(theme), - Obx(() => _buildBody(_subDetailController.loadingState.value)), - ], + child: refreshIndicator( + onRefresh: _subDetailController.onRefresh, + child: CustomScrollView( + controller: _subDetailController.scrollController, + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + _buildAppBar(theme), + _buildCount(theme), + Obx(() => _buildBody(_subDetailController.loadingState.value)), + ], + ), ), ), ); @@ -105,7 +92,7 @@ class _SubDetailPageState extends State { padding: const EdgeInsets.only(top: 12, bottom: 8, left: 14), child: Obx( () => Text( - '共${_subDetailController.mediaCount}条视频', + '共${_subDetailController.mediaCount.value}条视频', style: TextStyle( fontSize: theme.textTheme.labelMedium!.fontSize, color: theme.colorScheme.outline, @@ -116,32 +103,25 @@ class _SubDetailPageState extends State { ), ); - Widget _buildAppBar(ThemeData theme) => SliverAppBar( + Widget _buildAppBar(ThemeData theme) => SliverAppBar.medium( expandedHeight: kToolbarHeight + 132, pinned: true, - title: Obx( - () { - return AnimatedOpacity( - opacity: showTitle.value ? 1 : 0, - curve: Curves.easeOut, - duration: const Duration(milliseconds: 500), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _subDetailController.item.title!, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.titleMedium, - ), - Text( - '共${_subDetailController.mediaCount.value}条视频', - style: theme.textTheme.labelMedium, - ) - ], + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _subDetailController.item.title!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.titleMedium, + ), + Obx( + () => Text( + '共${_subDetailController.mediaCount.value}条视频', + style: theme.textTheme.labelMedium, ), - ); - }, + ), + ], ), flexibleSpace: FlexibleSpaceBar( background: Container( diff --git a/lib/pages/video/introduction/ugc/view.dart b/lib/pages/video/introduction/ugc/view.dart index 04f9dcea..8e7844a0 100644 --- a/lib/pages/video/introduction/ugc/view.dart +++ b/lib/pages/video/introduction/ugc/view.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/pendant_avatar.dart'; import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart'; import 'package:PiliPlus/common/widgets/stat/stat.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/video_detail_res.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; import 'package:PiliPlus/pages/search/widgets/search_text.dart'; @@ -389,7 +390,7 @@ class _VideoInfoState extends State { clipBehavior: Clip.none, children: [ NetworkImgLayer( - type: 'avatar', + type: ImageType.avatar, src: videoItem['staff'][index].face, width: 35, height: 35, diff --git a/lib/pages/video/member/view.dart b/lib/pages/video/member/view.dart index bf10cb29..f65dc3f7 100644 --- a/lib/pages/video/member/view.dart +++ b/lib/pages/video/member/view.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/video_card/video_card_h_member_video.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/image_preview_type.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/member/info.dart'; import 'package:PiliPlus/models/space_archive/item.dart'; import 'package:PiliPlus/pages/video/controller.dart'; @@ -417,7 +418,7 @@ class _HorizontalMemberPageState extends State { }, child: NetworkImgLayer( src: face, - type: 'avatar', + type: ImageType.avatar, width: 70, height: 70, ), diff --git a/lib/pages/video/note/view.dart b/lib/pages/video/note/view.dart index d5c3e16b..2b7f6345 100644 --- a/lib/pages/video/note/view.dart +++ b/lib/pages/video/note/view.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/common/common_slide_page.dart'; import 'package:PiliPlus/pages/video/note/controller.dart'; import 'package:PiliPlus/pages/webview/view.dart'; @@ -212,7 +213,7 @@ Widget _itemWidget(BuildContext context, ThemeData theme, dynamic item) { height: 34, width: 34, src: item['author']['face'], - type: 'avatar', + type: ImageType.avatar, ), ), const SizedBox(width: 12), diff --git a/lib/pages/video/reply/widgets/reply_item_grpc.dart b/lib/pages/video/reply/widgets/reply_item_grpc.dart index 815163f4..88a85d2c 100644 --- a/lib/pages/video/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/reply/widgets/reply_item_grpc.dart @@ -11,6 +11,7 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/models/common/badge_type.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/dynamics/widgets/vote.dart'; import 'package:PiliPlus/pages/save_panel/view.dart'; import 'package:PiliPlus/pages/video/controller.dart'; @@ -656,7 +657,7 @@ class ReplyItemGrpc extends StatelessWidget { src: content.emotes[matchStr]?.hasGifUrl() == true ? content.emotes[matchStr]?.gifUrl : content.emotes[matchStr]?.url, - type: 'emote', + type: ImageType.emote, width: size * 20, height: size * 20, semanticsLabel: matchStr, diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index 5e3c362d..1d1ef065 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/grpc/bilibili/im/type.pb.dart' show Msg; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/msg.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/common/publish_panel_type.dart'; import 'package:PiliPlus/pages/common/common_publish_page.dart'; import 'package:PiliPlus/pages/emote/view.dart'; @@ -79,7 +80,7 @@ class _WhisperDetailPageState NetworkImgLayer( width: 34, height: 34, - type: 'avatar', + type: ImageType.avatar, src: _whisperDetailController.face, ), const SizedBox(width: 6), diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index 31536d40..7eec04cf 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/grpc/bilibili/im/interfaces/v1.pb.dart' import 'package:PiliPlus/grpc/bilibili/im/type.pb.dart' show Msg, MsgType; import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/common/image_preview_type.dart'; +import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/id_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; @@ -598,7 +599,7 @@ class ChatItem extends StatelessWidget { width: emojiMap[emojiKey]!['size'], height: emojiMap[emojiKey]!['size'], src: emojiMap[emojiKey]!['url'], - type: 'emote', + type: ImageType.emote, ), ), );