diff --git a/lib/common/widgets/stat/stat.dart b/lib/common/widgets/stat/stat.dart index b3a0263c2..a83904dd8 100644 --- a/lib/common/widgets/stat/stat.dart +++ b/lib/common/widgets/stat/stat.dart @@ -67,6 +67,7 @@ class StatView extends _StatItemBase { IconData get iconData => switch (goto) { 'picture' => Icons.remove_red_eye_outlined, 'like' => Icons.thumb_up_outlined, + 'reply' => Icons.comment_outlined, _ => Icons.play_circle_outlined, }; diff --git a/lib/common/widgets/video_card_v_member_home.dart b/lib/common/widgets/video_card_v_member_home.dart index e9bac0f81..5aec82823 100644 --- a/lib/common/widgets/video_card_v_member_home.dart +++ b/lib/common/widgets/video_card_v_member_home.dart @@ -1,5 +1,7 @@ import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/models/space/item.dart'; +import 'package:PiliPlus/utils/id_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import '../../utils/utils.dart'; @@ -28,9 +30,15 @@ class VideoCardVMemberHome extends StatelessWidget { return; } } - String bvid = videoItem.bvid ?? ''; + String? aid = videoItem.param; + String? bvid = videoItem.bvid; + if (aid == null && bvid == null) { + return; + } + int? cid = videoItem.firstCid; + cid ??= await SearchHttp.ab2c(aid: aid, bvid: bvid); Utils.toViewPage( - 'bvid=$bvid&cid=${videoItem.firstCid}', + 'bvid=${bvid ?? IdUtils.av2bv(int.parse(aid!))}&cid=$cid', arguments: { // 'videoItem': videoItem, 'pic': videoItem.cover, diff --git a/lib/models/space/coin_archive.dart b/lib/models/space/coin_archive.dart index 59af1bcec..02bb44e75 100644 --- a/lib/models/space/coin_archive.dart +++ b/lib/models/space/coin_archive.dart @@ -1,17 +1,18 @@ +import 'package:PiliPlus/models/space/item.dart'; import 'package:json_annotation/json_annotation.dart'; part 'coin_archive.g.dart'; @JsonSerializable() class CoinArchive { - int? count; - List? item; + int? count; + List? item; - CoinArchive({this.count, this.item}); + CoinArchive({this.count, this.item}); - factory CoinArchive.fromJson(Map json) { - return _$CoinArchiveFromJson(json); - } + factory CoinArchive.fromJson(Map json) { + return _$CoinArchiveFromJson(json); + } - Map toJson() => _$CoinArchiveToJson(this); + Map toJson() => _$CoinArchiveToJson(this); } diff --git a/lib/models/space/coin_archive.g.dart b/lib/models/space/coin_archive.g.dart index 8dddf6207..ee834b661 100644 --- a/lib/models/space/coin_archive.g.dart +++ b/lib/models/space/coin_archive.g.dart @@ -8,7 +8,9 @@ part of 'coin_archive.dart'; CoinArchive _$CoinArchiveFromJson(Map json) => CoinArchive( count: (json['count'] as num?)?.toInt(), - item: json['item'] as List?, + item: (json['item'] as List?) + ?.map((json) => Item.fromJson(json)) + .toList(), ); Map _$CoinArchiveToJson(CoinArchive instance) => diff --git a/lib/models/space/favourite2.dart b/lib/models/space/favourite2.dart index 6968144d9..0f14102f7 100644 --- a/lib/models/space/favourite2.dart +++ b/lib/models/space/favourite2.dart @@ -4,14 +4,14 @@ part 'favourite2.g.dart'; @JsonSerializable() class Favourite2 { - int? count; - List? item; + int? count; + List? item; - Favourite2({this.count, this.item}); + Favourite2({this.count, this.item}); - factory Favourite2.fromJson(Map json) { - return _$Favourite2FromJson(json); - } + factory Favourite2.fromJson(Map json) { + return _$Favourite2FromJson(json); + } - Map toJson() => _$Favourite2ToJson(this); + Map toJson() => _$Favourite2ToJson(this); } diff --git a/lib/models/space/like_archive.dart b/lib/models/space/like_archive.dart index 1ff59a4b6..0b4c04f27 100644 --- a/lib/models/space/like_archive.dart +++ b/lib/models/space/like_archive.dart @@ -1,17 +1,18 @@ +import 'package:PiliPlus/models/space/item.dart'; import 'package:json_annotation/json_annotation.dart'; part 'like_archive.g.dart'; @JsonSerializable() class LikeArchive { - int? count; - List? item; + int? count; + List? item; - LikeArchive({this.count, this.item}); + LikeArchive({this.count, this.item}); - factory LikeArchive.fromJson(Map json) { - return _$LikeArchiveFromJson(json); - } + factory LikeArchive.fromJson(Map json) { + return _$LikeArchiveFromJson(json); + } - Map toJson() => _$LikeArchiveToJson(this); + Map toJson() => _$LikeArchiveToJson(this); } diff --git a/lib/models/space/like_archive.g.dart b/lib/models/space/like_archive.g.dart index 59f39886d..cd111d219 100644 --- a/lib/models/space/like_archive.g.dart +++ b/lib/models/space/like_archive.g.dart @@ -8,7 +8,9 @@ part of 'like_archive.dart'; LikeArchive _$LikeArchiveFromJson(Map json) => LikeArchive( count: (json['count'] as num?)?.toInt(), - item: json['item'] as List?, + item: (json['item'] as List?) + ?.map((json) => Item.fromJson(json)) + .toList(), ); Map _$LikeArchiveToJson(LikeArchive instance) => diff --git a/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart b/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart index cf9828c5c..0309ee79d 100644 --- a/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart +++ b/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart @@ -103,7 +103,7 @@ Widget bangumiContent(Item bangumiItem) { style: const TextStyle( letterSpacing: 0.3, ), - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, )), ], diff --git a/lib/pages/member/new/content/member_contribute/content/article/member_article.dart b/lib/pages/member/new/content/member_contribute/content/article/member_article.dart index 326e95b17..5843c5d0a 100644 --- a/lib/pages/member/new/content/member_contribute/content/article/member_article.dart +++ b/lib/pages/member/new/content/member_contribute/content/article/member_article.dart @@ -1,11 +1,10 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; -import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/http/loading_state.dart'; -import 'package:PiliPlus/models/space_article/item.dart'; import 'package:PiliPlus/pages/member/new/content/member_contribute/content/article/member_article_ctr.dart'; -import 'package:PiliPlus/utils/app_scheme.dart'; +import 'package:PiliPlus/pages/member/new/content/member_contribute/content/article/widget/item.dart'; +import 'package:PiliPlus/utils/grid.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -43,62 +42,31 @@ class _MemberArticleState extends State return switch (loadingState) { Loading() => loadingWidget, Success() => (loadingState.response as List?)?.isNotEmpty == true - ? MediaQuery.removePadding( - context: context, - removeTop: true, - child: refreshIndicator( - onRefresh: () async { - await _controller.onRefresh(); - }, - child: ListView.separated( - itemCount: loadingState.response.length, - itemBuilder: (context, index) { - if (index == loadingState.response.length - 1) { - _controller.onLoadMore(); - } - Item item = loadingState.response[index]; - return ListTile( - dense: true, - onTap: () { - PiliScheme.routePushFromUrl(item.uri ?? ''); + ? refreshIndicator( + onRefresh: () async { + await _controller.onRefresh(); + }, + child: CustomScrollView( + slivers: [ + SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: 2, + maxCrossAxisExtent: Grid.mediumCardWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.2, + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + if (index == loadingState.response.length - 1) { + _controller.onLoadMore(); + } + return MemberArticleItem( + item: loadingState.response[index], + ); }, - leading: item.originImageUrls?.isNotEmpty == true - ? Container( - margin: const EdgeInsets.symmetric(vertical: 6), - child: LayoutBuilder( - builder: (context, constraints) { - return NetworkImgLayer( - radius: 6, - src: item.originImageUrls!.first, - width: constraints.maxHeight * - StyleString.aspectRatio, - height: constraints.maxHeight, - ); - }, - ), - ) - : null, - title: Text( - item.title ?? '', - style: TextStyle( - fontSize: 15, - ), - ), - subtitle: item.summary?.isNotEmpty == true - ? Text( - item.summary!, - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), - ) - : null, - ); - }, - separatorBuilder: (context, index) => Divider(height: 1), - ), + childCount: loadingState.response.length, + ), + ), + ], ), ) : scrollErrorWidget( diff --git a/lib/pages/member/new/content/member_contribute/content/article/widget/item.dart b/lib/pages/member/new/content/member_contribute/content/article/widget/item.dart new file mode 100644 index 000000000..c93bdd913 --- /dev/null +++ b/lib/pages/member/new/content/member_contribute/content/article/widget/item.dart @@ -0,0 +1,105 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/common/widgets/stat/stat.dart'; +import 'package:PiliPlus/models/space_article/item.dart'; +import 'package:PiliPlus/utils/app_scheme.dart'; +import 'package:flutter/material.dart'; + +class MemberArticleItem extends StatelessWidget { + const MemberArticleItem({super.key, required this.item}); + + final Item item; + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + if (item.uri?.isNotEmpty == true) { + PiliScheme.routePushFromUrl(item.uri!); + } + }, + onLongPress: () { + imageSaveDialog( + context: context, + title: item.title, + cover: item.originImageUrls?.firstOrNull, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: 5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (item.originImageUrls?.firstOrNull?.isNotEmpty == true) ...[ + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder( + builder: + (BuildContext context, BoxConstraints boxConstraints) { + return NetworkImgLayer( + src: item.originImageUrls!.first, + width: boxConstraints.maxWidth, + height: boxConstraints.maxHeight, + ); + }, + ), + ), + const SizedBox(width: 10), + ], + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (item.title?.isNotEmpty == true) ...[ + Text( + item.title!, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const Spacer(), + ], + Text( + '${item.publishTimeText}', + style: TextStyle( + fontSize: 12, + color: Theme.of(context).colorScheme.outline, + ), + ), + const SizedBox(height: 4), + Row( + children: [ + StatView( + context: context, + value: item.stats?.view ?? 0, + size: 'medium', + goto: 'picture', + textColor: Theme.of(context).colorScheme.outline, + ), + const SizedBox(width: 16), + StatView( + context: context, + goto: 'reply', + size: 'medium', + value: item.stats?.reply ?? 0, + textColor: Theme.of(context).colorScheme.outline, + ), + ], + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi.dart b/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi.dart index cbe038528..f680446d2 100644 --- a/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi.dart +++ b/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi.dart @@ -66,7 +66,7 @@ class _MemberBangumiState extends State maxCrossAxisExtent: Grid.smallCardWidth / 3 * 2, childAspectRatio: 0.75, mainAxisExtent: - MediaQuery.textScalerOf(context).scale(30), + MediaQuery.textScalerOf(context).scale(52), ), delegate: SliverChildBuilderDelegate( (context, index) { diff --git a/lib/pages/member/new/content/member_contribute/content/favorite/member_favorite.dart b/lib/pages/member/new/content/member_contribute/content/favorite/member_favorite.dart index 2e3618e4a..98fb44d2b 100644 --- a/lib/pages/member/new/content/member_contribute/content/favorite/member_favorite.dart +++ b/lib/pages/member/new/content/member_contribute/content/favorite/member_favorite.dart @@ -1,14 +1,11 @@ import 'package:PiliPlus/common/constants.dart'; -import 'package:PiliPlus/common/widgets/badge.dart'; import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; -import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/space_fav/datum.dart'; import 'package:PiliPlus/models/space_fav/list.dart'; -import 'package:PiliPlus/models/user/sub_folder.dart'; import 'package:PiliPlus/pages/member/new/content/member_contribute/content/favorite/member_favorite_ctr.dart'; -import 'package:PiliPlus/utils/utils.dart'; +import 'package:PiliPlus/pages/member/new/content/member_contribute/content/favorite/widget/item.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -64,7 +61,7 @@ class _MemberFavoriteState extends State ), SliverToBoxAdapter( child: SizedBox( - height: 12 + MediaQuery.of(context).padding.bottom, + height: 80 + MediaQuery.of(context).padding.bottom, ), ) ], @@ -82,6 +79,7 @@ class _MemberFavoriteState extends State } _buildItem(Datum data, bool isFirst) { + final height = 120 / StyleString.aspectRatio + 10; return Theme( data: Theme.of(context).copyWith( dividerColor: Colors.transparent, @@ -109,113 +107,21 @@ class _MemberFavoriteState extends State controlAffinity: ListTileControlAffinity.leading, children: [ ...(data.mediaListResponse?.list as List).map( - (item1) => ListTile( - onTap: () async { - if (item1.state == 1) { - // invalid - return; - } - - if (item1.type == 0) { - dynamic res = await Get.toNamed( - '/favDetail', - parameters: { - 'mediaId': item1.id.toString(), - 'heroTag': widget.heroTag ?? '', - }, - ); + (item) => SizedBox( + height: height, + child: MemberFavItem( + item: item, + callback: (res) { if (res == true) { _controller.first.value.mediaListResponse?.list - ?.remove(item1); + ?.remove(item); _controller.first.refresh(); } else { Future.delayed(const Duration(milliseconds: 100), () { _controller.onRefresh(); }); } - } else { - Get.toNamed( - '/subDetail', - arguments: SubFolderItemData( - type: item1.type, - title: item1.title, - cover: item1.cover, - upper: Upper( - mid: item1.upper?.mid, - name: item1.upper?.name, - face: item1.upper?.face, - ), - mediaCount: item1.mediaCount, - viewCount: item1.viewCount, - ), - parameters: { - 'heroTag': widget.heroTag ?? '', - 'id': item1.id.toString(), - }, - ); - } - }, - leading: Container( - margin: const EdgeInsets.symmetric(vertical: 6), - child: LayoutBuilder( - builder: (context, constraints) { - return Stack( - children: [ - NetworkImgLayer( - radius: 6, - src: item1.cover, - width: - constraints.maxHeight * StyleString.aspectRatio, - height: constraints.maxHeight, - ), - if (item1.type == 21) - PBadge( - right: 3, - bottom: 3, - text: '合集', - bold: false, - size: 'small', - ) - else if (item1.type == 0 || item1.type == 11) - Positioned( - right: 3, - bottom: 3, - child: Container( - padding: const EdgeInsets.all(5), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).colorScheme.primary, - ), - child: Icon( - Icons.video_library_outlined, - size: 12, - color: Theme.of(context).colorScheme.onPrimary, - ), - ), - ), - ], - ); - }, - ), - ), - title: Text( - item1.title ?? '', - style: TextStyle( - fontSize: 14, - ), - ), - subtitle: Text( - item1.type == 0 - ? '${item1.mediaCount}个内容 · ${Utils.isPublicText(item1.attr ?? 0)}' - : item1.type == 11 - ? '${item1.mediaCount}个内容 · ${item1.upper?.name}' - : item1.type == 21 - ? '创建者: ${item1.upper?.name}\n${item1.mediaCount}个视频 · ${Utils.numFormat(item1.viewCount)}播放' - : '${item1.mediaCount}个内容', - style: TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), + }, ), ), ), diff --git a/lib/pages/member/new/content/member_contribute/content/favorite/widget/item.dart b/lib/pages/member/new/content/member_contribute/content/favorite/widget/item.dart new file mode 100644 index 000000000..28eb6e8ca --- /dev/null +++ b/lib/pages/member/new/content/member_contribute/content/favorite/widget/item.dart @@ -0,0 +1,151 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/badge.dart'; +import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/models/space_fav/list.dart'; +import 'package:PiliPlus/models/user/sub_folder.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class MemberFavItem extends StatelessWidget { + const MemberFavItem({super.key, required this.item, this.callback}); + + final FavList item; + final ValueChanged? callback; + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () async { + if (item.state == 1) { + // invalid + return; + } + + if (item.type == 0) { + dynamic res = await Get.toNamed( + '/favDetail', + parameters: { + 'mediaId': item.id.toString(), + 'heroTag': Utils.makeHeroTag(item.id), + }, + ); + callback?.call(res); + } else { + Get.toNamed( + '/subDetail', + arguments: SubFolderItemData( + type: item.type, + title: item.title, + cover: item.cover, + upper: Upper( + mid: item.upper?.mid, + name: item.upper?.name, + face: item.upper?.face, + ), + mediaCount: item.mediaCount, + viewCount: item.viewCount, + ), + parameters: { + 'id': item.id.toString(), + 'heroTag': Utils.makeHeroTag(item.id), + }, + ); + } + }, + onLongPress: () { + imageSaveDialog( + context: context, + title: item.title, + cover: item.cover, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: 5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder( + builder: (context, boxConstraints) { + return Stack( + clipBehavior: Clip.none, + children: [ + NetworkImgLayer( + src: item.cover, + width: boxConstraints.maxWidth, + height: boxConstraints.maxHeight, + ), + if (item.type == 21) + PBadge( + right: 3, + bottom: 3, + text: '合集', + bold: false, + size: 'small', + ) + else if (item.type == 0 || item.type == 11) + Positioned( + right: 3, + bottom: 3, + child: Container( + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).colorScheme.primary, + ), + child: Icon( + Icons.video_library_outlined, + size: 12, + color: Theme.of(context).colorScheme.onPrimary, + ), + ), + ), + ], + ); + }, + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.title ?? '', + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const Spacer(), + Text( + item.type == 0 + ? '${item.mediaCount}个内容 · ${Utils.isPublicText(item.attr ?? 0)}' + : item.type == 11 + ? '${item.mediaCount}个内容 · ${item.upper?.name}' + : item.type == 21 + ? '创建者: ${item.upper?.name}\n${item.mediaCount}个视频 · ${Utils.numFormat(item.viewCount)}播放' + : '${item.mediaCount}个内容', + style: TextStyle( + fontSize: 12, + color: Theme.of(context).colorScheme.outline, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/member/new/content/member_home/member_home.dart b/lib/pages/member/new/content/member_home/member_home.dart index f9f99e28a..af7c67daa 100644 --- a/lib/pages/member/new/content/member_home/member_home.dart +++ b/lib/pages/member/new/content/member_home/member_home.dart @@ -2,13 +2,14 @@ import 'dart:math'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/loading_widget.dart'; -import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/video_card_v_member_home.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/space/data.dart'; import 'package:PiliPlus/models/space/item.dart'; import 'package:PiliPlus/pages/bangumi/widgets/bangumi_card_v_member_home.dart'; +import 'package:PiliPlus/pages/member/new/content/member_contribute/content/article/widget/item.dart'; import 'package:PiliPlus/pages/member/new/content/member_contribute/member_contribute_ctr.dart'; +import 'package:PiliPlus/pages/member/new/content/member_home/widget/fav_item.dart'; import 'package:PiliPlus/pages/member/new/controller.dart'; import 'package:PiliPlus/pages/member_coin/index.dart'; import 'package:PiliPlus/pages/member_like/index.dart'; @@ -17,8 +18,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -import '../../../../../utils/app_scheme.dart'; - class MemberHome extends StatefulWidget { const MemberHome({super.key, this.heroTag}); @@ -42,6 +41,7 @@ class _MemberHomeState extends State } Widget _buildBody(LoadingState loadingState) { + final isVertical = context.orientation == Orientation.portrait; return switch (loadingState) { Loading() => loadingWidget, Success() => loadingState.response is Data @@ -75,8 +75,8 @@ class _MemberHomeState extends State loadingState.response.archive.item[index], ); }, - childCount: - min(4, loadingState.response.archive.item.length), + childCount: min(isVertical ? 4 : 8, + loadingState.response.archive.item.length), ), ), ), @@ -88,7 +88,14 @@ class _MemberHomeState extends State param: 'favorite', count: loadingState.response.favourite2.count, ), - // TODO + SliverToBoxAdapter( + child: SizedBox( + height: 120 / StyleString.aspectRatio + 10, + child: MemberFavItem( + item: loadingState.response.favourite2.item.first, + ), + ), + ), ], if (loadingState.response?.coinArchive?.item?.isNotEmpty == true) ...[ @@ -97,7 +104,31 @@ class _MemberHomeState extends State param: 'coinArchive', count: loadingState.response.coinArchive.count, ), - // TODO + SliverPadding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + ), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.cardSpace, + maxCrossAxisExtent: Grid.smallCardWidth, + childAspectRatio: StyleString.aspectRatio, + mainAxisExtent: + MediaQuery.textScalerOf(context).scale(55), + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return VideoCardVMemberHome( + videoItem: + loadingState.response.coinArchive.item[index], + ); + }, + childCount: min(isVertical ? 2 : 4, + loadingState.response.coinArchive.item.length), + ), + ), + ), ], if (loadingState.response?.likeArchive?.item?.isNotEmpty == true) ...[ @@ -106,7 +137,31 @@ class _MemberHomeState extends State param: 'likeArchive', count: loadingState.response.likeArchive.count, ), - // TODO + SliverPadding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + ), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.cardSpace, + maxCrossAxisExtent: Grid.smallCardWidth, + childAspectRatio: StyleString.aspectRatio, + mainAxisExtent: + MediaQuery.textScalerOf(context).scale(55), + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return VideoCardVMemberHome( + videoItem: + loadingState.response.likeArchive.item[index], + ); + }, + childCount: min(isVertical ? 2 : 4, + loadingState.response.likeArchive.item.length), + ), + ), + ), ], if (loadingState.response?.article?.item?.isNotEmpty == true) ...[ @@ -116,52 +171,21 @@ class _MemberHomeState extends State param1: 'article', count: loadingState.response.article.count, ), - SliverToBoxAdapter( - child: ListTile( - dense: true, - onTap: () { - PiliScheme.routePushFromUrl( - loadingState.response.article.item.first.uri ?? '', + SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: 2, + maxCrossAxisExtent: Grid.mediumCardWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.2, + ), + delegate: SliverChildBuilderDelegate( + (context, index) { + return MemberArticleItem( + item: loadingState.response.article.item[index], ); }, - leading: loadingState.response.article.item.first - .originImageUrls?.isNotEmpty == - true - ? Container( - margin: const EdgeInsets.symmetric(vertical: 6), - child: LayoutBuilder( - builder: (context, constraints) { - return NetworkImgLayer( - radius: 6, - src: loadingState.response.article.item - .first.originImageUrls!.first, - width: constraints.maxHeight * - StyleString.aspectRatio, - height: constraints.maxHeight, - ); - }, - ), - ) - : null, - title: Text( - loadingState.response.article.item.first.title ?? '', - style: TextStyle( - fontSize: 15, - ), - ), - subtitle: loadingState.response.article.item.first.summary - ?.isNotEmpty == - true - ? Text( - loadingState.response.article.item.first.summary!, - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), - ) - : null, + childCount: isVertical + ? 1 + : loadingState.response.article.item.length, ), ), ], @@ -193,7 +217,7 @@ class _MemberHomeState extends State maxCrossAxisExtent: Grid.smallCardWidth / 3 * 2, childAspectRatio: 0.75, mainAxisExtent: - MediaQuery.textScalerOf(context).scale(30), + MediaQuery.textScalerOf(context).scale(52), ), delegate: SliverChildBuilderDelegate( (context, index) { @@ -202,15 +226,15 @@ class _MemberHomeState extends State loadingState.response.season.item[index], ); }, - childCount: - min(3, loadingState.response.season.item.length), + childCount: min(isVertical ? 3 : 6, + loadingState.response.season.item.length), ), ), ), ], SliverToBoxAdapter( child: SizedBox( - height: 12 + MediaQuery.of(context).padding.bottom, + height: 80 + MediaQuery.of(context).padding.bottom, ), ), ], @@ -288,7 +312,8 @@ class _MemberHomeState extends State )); return; } - // TODO + + // else TODO SmartDialog.showToast('view $param'); } }, diff --git a/lib/pages/member/new/content/member_home/widget/fav_item.dart b/lib/pages/member/new/content/member_home/widget/fav_item.dart new file mode 100644 index 000000000..d75ada1b5 --- /dev/null +++ b/lib/pages/member/new/content/member_home/widget/fav_item.dart @@ -0,0 +1,90 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class MemberFavItem extends StatelessWidget { + const MemberFavItem({super.key, required this.item}); + + final dynamic item; + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + if (item['type'] == 2) { + Get.toNamed( + '/favDetail', + parameters: { + 'mediaId': item['media_id'].toString(), + 'heroTag': Utils.makeHeroTag(item['media_id']), + }, + ); + } + }, + onLongPress: () { + imageSaveDialog( + context: context, + title: item['title'], + cover: item['cover'], + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: 5, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder( + builder: (context, boxConstraints) { + return Stack( + clipBehavior: Clip.none, + children: [ + NetworkImgLayer( + src: item['cover'], + width: boxConstraints.maxWidth, + height: boxConstraints.maxHeight, + ), + ], + ); + }, + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item['title'] ?? '', + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + const Spacer(), + Text( + '${item['count']}个内容 · ${item['is_public'] == 1 ? '私密' : '公开'}', + style: TextStyle( + fontSize: 12, + color: Theme.of(context).colorScheme.outline, + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +}