opt: member page

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-04-01 15:11:29 +08:00
parent 22866012ca
commit f70cf05870
15 changed files with 506 additions and 246 deletions

View File

@@ -67,6 +67,7 @@ class StatView extends _StatItemBase {
IconData get iconData => switch (goto) { IconData get iconData => switch (goto) {
'picture' => Icons.remove_red_eye_outlined, 'picture' => Icons.remove_red_eye_outlined,
'like' => Icons.thumb_up_outlined, 'like' => Icons.thumb_up_outlined,
'reply' => Icons.comment_outlined,
_ => Icons.play_circle_outlined, _ => Icons.play_circle_outlined,
}; };

View File

@@ -1,5 +1,7 @@
import 'package:PiliPlus/common/widgets/image_save.dart'; import 'package:PiliPlus/common/widgets/image_save.dart';
import 'package:PiliPlus/http/search.dart';
import 'package:PiliPlus/models/space/item.dart'; import 'package:PiliPlus/models/space/item.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import '../../utils/utils.dart'; import '../../utils/utils.dart';
@@ -28,9 +30,15 @@ class VideoCardVMemberHome extends StatelessWidget {
return; 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( Utils.toViewPage(
'bvid=$bvid&cid=${videoItem.firstCid}', 'bvid=${bvid ?? IdUtils.av2bv(int.parse(aid!))}&cid=$cid',
arguments: { arguments: {
// 'videoItem': videoItem, // 'videoItem': videoItem,
'pic': videoItem.cover, 'pic': videoItem.cover,

View File

@@ -1,17 +1,18 @@
import 'package:PiliPlus/models/space/item.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
part 'coin_archive.g.dart'; part 'coin_archive.g.dart';
@JsonSerializable() @JsonSerializable()
class CoinArchive { class CoinArchive {
int? count; int? count;
List<dynamic>? item; List<Item>? item;
CoinArchive({this.count, this.item}); CoinArchive({this.count, this.item});
factory CoinArchive.fromJson(Map<String, dynamic> json) { factory CoinArchive.fromJson(Map<String, dynamic> json) {
return _$CoinArchiveFromJson(json); return _$CoinArchiveFromJson(json);
} }
Map<String, dynamic> toJson() => _$CoinArchiveToJson(this); Map<String, dynamic> toJson() => _$CoinArchiveToJson(this);
} }

View File

@@ -8,7 +8,9 @@ part of 'coin_archive.dart';
CoinArchive _$CoinArchiveFromJson(Map<String, dynamic> json) => CoinArchive( CoinArchive _$CoinArchiveFromJson(Map<String, dynamic> json) => CoinArchive(
count: (json['count'] as num?)?.toInt(), count: (json['count'] as num?)?.toInt(),
item: json['item'] as List<dynamic>?, item: (json['item'] as List<dynamic>?)
?.map((json) => Item.fromJson(json))
.toList(),
); );
Map<String, dynamic> _$CoinArchiveToJson(CoinArchive instance) => Map<String, dynamic> _$CoinArchiveToJson(CoinArchive instance) =>

View File

@@ -4,14 +4,14 @@ part 'favourite2.g.dart';
@JsonSerializable() @JsonSerializable()
class Favourite2 { class Favourite2 {
int? count; int? count;
List<dynamic>? item; List<dynamic>? item;
Favourite2({this.count, this.item}); Favourite2({this.count, this.item});
factory Favourite2.fromJson(Map<String, dynamic> json) { factory Favourite2.fromJson(Map<String, dynamic> json) {
return _$Favourite2FromJson(json); return _$Favourite2FromJson(json);
} }
Map<String, dynamic> toJson() => _$Favourite2ToJson(this); Map<String, dynamic> toJson() => _$Favourite2ToJson(this);
} }

View File

@@ -1,17 +1,18 @@
import 'package:PiliPlus/models/space/item.dart';
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
part 'like_archive.g.dart'; part 'like_archive.g.dart';
@JsonSerializable() @JsonSerializable()
class LikeArchive { class LikeArchive {
int? count; int? count;
List<dynamic>? item; List<Item>? item;
LikeArchive({this.count, this.item}); LikeArchive({this.count, this.item});
factory LikeArchive.fromJson(Map<String, dynamic> json) { factory LikeArchive.fromJson(Map<String, dynamic> json) {
return _$LikeArchiveFromJson(json); return _$LikeArchiveFromJson(json);
} }
Map<String, dynamic> toJson() => _$LikeArchiveToJson(this); Map<String, dynamic> toJson() => _$LikeArchiveToJson(this);
} }

View File

@@ -8,7 +8,9 @@ part of 'like_archive.dart';
LikeArchive _$LikeArchiveFromJson(Map<String, dynamic> json) => LikeArchive( LikeArchive _$LikeArchiveFromJson(Map<String, dynamic> json) => LikeArchive(
count: (json['count'] as num?)?.toInt(), count: (json['count'] as num?)?.toInt(),
item: json['item'] as List<dynamic>?, item: (json['item'] as List<dynamic>?)
?.map((json) => Item.fromJson(json))
.toList(),
); );
Map<String, dynamic> _$LikeArchiveToJson(LikeArchive instance) => Map<String, dynamic> _$LikeArchiveToJson(LikeArchive instance) =>

View File

@@ -103,7 +103,7 @@ Widget bangumiContent(Item bangumiItem) {
style: const TextStyle( style: const TextStyle(
letterSpacing: 0.3, letterSpacing: 0.3,
), ),
maxLines: 1, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
)), )),
], ],

View File

@@ -1,11 +1,10 @@
import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/loading_widget.dart';
import 'package:PiliPlus/common/widgets/refresh_indicator.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/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/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:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -43,62 +42,31 @@ class _MemberArticleState extends State<MemberArticle>
return switch (loadingState) { return switch (loadingState) {
Loading() => loadingWidget, Loading() => loadingWidget,
Success() => (loadingState.response as List?)?.isNotEmpty == true Success() => (loadingState.response as List?)?.isNotEmpty == true
? MediaQuery.removePadding( ? refreshIndicator(
context: context, onRefresh: () async {
removeTop: true, await _controller.onRefresh();
child: refreshIndicator( },
onRefresh: () async { child: CustomScrollView(
await _controller.onRefresh(); slivers: [
}, SliverGrid(
child: ListView.separated( gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
itemCount: loadingState.response.length, mainAxisSpacing: 2,
itemBuilder: (context, index) { maxCrossAxisExtent: Grid.mediumCardWidth * 2,
if (index == loadingState.response.length - 1) { childAspectRatio: StyleString.aspectRatio * 2.2,
_controller.onLoadMore(); ),
} delegate: SliverChildBuilderDelegate(
Item item = loadingState.response[index]; (context, index) {
return ListTile( if (index == loadingState.response.length - 1) {
dense: true, _controller.onLoadMore();
onTap: () { }
PiliScheme.routePushFromUrl(item.uri ?? ''); return MemberArticleItem(
item: loadingState.response[index],
);
}, },
leading: item.originImageUrls?.isNotEmpty == true childCount: loadingState.response.length,
? 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),
),
), ),
) )
: scrollErrorWidget( : scrollErrorWidget(

View File

@@ -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,
),
],
),
],
),
),
],
),
),
),
);
}
}

View File

@@ -66,7 +66,7 @@ class _MemberBangumiState extends State<MemberBangumi>
maxCrossAxisExtent: Grid.smallCardWidth / 3 * 2, maxCrossAxisExtent: Grid.smallCardWidth / 3 * 2,
childAspectRatio: 0.75, childAspectRatio: 0.75,
mainAxisExtent: mainAxisExtent:
MediaQuery.textScalerOf(context).scale(30), MediaQuery.textScalerOf(context).scale(52),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(context, index) { (context, index) {

View File

@@ -1,14 +1,11 @@
import 'package:PiliPlus/common/constants.dart'; 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/loading_widget.dart';
import 'package:PiliPlus/common/widgets/refresh_indicator.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/http/loading_state.dart';
import 'package:PiliPlus/models/space_fav/datum.dart'; import 'package:PiliPlus/models/space_fav/datum.dart';
import 'package:PiliPlus/models/space_fav/list.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/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:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -64,7 +61,7 @@ class _MemberFavoriteState extends State<MemberFavorite>
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
height: 12 + MediaQuery.of(context).padding.bottom, height: 80 + MediaQuery.of(context).padding.bottom,
), ),
) )
], ],
@@ -82,6 +79,7 @@ class _MemberFavoriteState extends State<MemberFavorite>
} }
_buildItem(Datum data, bool isFirst) { _buildItem(Datum data, bool isFirst) {
final height = 120 / StyleString.aspectRatio + 10;
return Theme( return Theme(
data: Theme.of(context).copyWith( data: Theme.of(context).copyWith(
dividerColor: Colors.transparent, dividerColor: Colors.transparent,
@@ -109,113 +107,21 @@ class _MemberFavoriteState extends State<MemberFavorite>
controlAffinity: ListTileControlAffinity.leading, controlAffinity: ListTileControlAffinity.leading,
children: [ children: [
...(data.mediaListResponse?.list as List<FavList>).map( ...(data.mediaListResponse?.list as List<FavList>).map(
(item1) => ListTile( (item) => SizedBox(
onTap: () async { height: height,
if (item1.state == 1) { child: MemberFavItem(
// invalid item: item,
return; callback: (res) {
}
if (item1.type == 0) {
dynamic res = await Get.toNamed(
'/favDetail',
parameters: {
'mediaId': item1.id.toString(),
'heroTag': widget.heroTag ?? '',
},
);
if (res == true) { if (res == true) {
_controller.first.value.mediaListResponse?.list _controller.first.value.mediaListResponse?.list
?.remove(item1); ?.remove(item);
_controller.first.refresh(); _controller.first.refresh();
} else { } else {
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 100), () {
_controller.onRefresh(); _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,
),
), ),
), ),
), ),

View File

@@ -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<bool?>? 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,
),
),
],
),
),
],
),
),
),
);
}
}

View File

@@ -2,13 +2,14 @@ import 'dart:math';
import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/loading_widget.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/common/widgets/video_card_v_member_home.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/space/data.dart'; import 'package:PiliPlus/models/space/data.dart';
import 'package:PiliPlus/models/space/item.dart'; import 'package:PiliPlus/models/space/item.dart';
import 'package:PiliPlus/pages/bangumi/widgets/bangumi_card_v_member_home.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_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/new/controller.dart';
import 'package:PiliPlus/pages/member_coin/index.dart'; import 'package:PiliPlus/pages/member_coin/index.dart';
import 'package:PiliPlus/pages/member_like/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:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../../../../utils/app_scheme.dart';
class MemberHome extends StatefulWidget { class MemberHome extends StatefulWidget {
const MemberHome({super.key, this.heroTag}); const MemberHome({super.key, this.heroTag});
@@ -42,6 +41,7 @@ class _MemberHomeState extends State<MemberHome>
} }
Widget _buildBody(LoadingState loadingState) { Widget _buildBody(LoadingState loadingState) {
final isVertical = context.orientation == Orientation.portrait;
return switch (loadingState) { return switch (loadingState) {
Loading() => loadingWidget, Loading() => loadingWidget,
Success() => loadingState.response is Data Success() => loadingState.response is Data
@@ -75,8 +75,8 @@ class _MemberHomeState extends State<MemberHome>
loadingState.response.archive.item[index], loadingState.response.archive.item[index],
); );
}, },
childCount: childCount: min(isVertical ? 4 : 8,
min(4, loadingState.response.archive.item.length), loadingState.response.archive.item.length),
), ),
), ),
), ),
@@ -88,7 +88,14 @@ class _MemberHomeState extends State<MemberHome>
param: 'favorite', param: 'favorite',
count: loadingState.response.favourite2.count, 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 == if (loadingState.response?.coinArchive?.item?.isNotEmpty ==
true) ...[ true) ...[
@@ -97,7 +104,31 @@ class _MemberHomeState extends State<MemberHome>
param: 'coinArchive', param: 'coinArchive',
count: loadingState.response.coinArchive.count, 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 == if (loadingState.response?.likeArchive?.item?.isNotEmpty ==
true) ...[ true) ...[
@@ -106,7 +137,31 @@ class _MemberHomeState extends State<MemberHome>
param: 'likeArchive', param: 'likeArchive',
count: loadingState.response.likeArchive.count, 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 == if (loadingState.response?.article?.item?.isNotEmpty ==
true) ...[ true) ...[
@@ -116,52 +171,21 @@ class _MemberHomeState extends State<MemberHome>
param1: 'article', param1: 'article',
count: loadingState.response.article.count, count: loadingState.response.article.count,
), ),
SliverToBoxAdapter( SliverGrid(
child: ListTile( gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
dense: true, mainAxisSpacing: 2,
onTap: () { maxCrossAxisExtent: Grid.mediumCardWidth * 2,
PiliScheme.routePushFromUrl( childAspectRatio: StyleString.aspectRatio * 2.2,
loadingState.response.article.item.first.uri ?? '', ),
delegate: SliverChildBuilderDelegate(
(context, index) {
return MemberArticleItem(
item: loadingState.response.article.item[index],
); );
}, },
leading: loadingState.response.article.item.first childCount: isVertical
.originImageUrls?.isNotEmpty == ? 1
true : loadingState.response.article.item.length,
? 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,
), ),
), ),
], ],
@@ -193,7 +217,7 @@ class _MemberHomeState extends State<MemberHome>
maxCrossAxisExtent: Grid.smallCardWidth / 3 * 2, maxCrossAxisExtent: Grid.smallCardWidth / 3 * 2,
childAspectRatio: 0.75, childAspectRatio: 0.75,
mainAxisExtent: mainAxisExtent:
MediaQuery.textScalerOf(context).scale(30), MediaQuery.textScalerOf(context).scale(52),
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(context, index) { (context, index) {
@@ -202,15 +226,15 @@ class _MemberHomeState extends State<MemberHome>
loadingState.response.season.item[index], loadingState.response.season.item[index],
); );
}, },
childCount: childCount: min(isVertical ? 3 : 6,
min(3, loadingState.response.season.item.length), loadingState.response.season.item.length),
), ),
), ),
), ),
], ],
SliverToBoxAdapter( SliverToBoxAdapter(
child: SizedBox( child: SizedBox(
height: 12 + MediaQuery.of(context).padding.bottom, height: 80 + MediaQuery.of(context).padding.bottom,
), ),
), ),
], ],
@@ -288,7 +312,8 @@ class _MemberHomeState extends State<MemberHome>
)); ));
return; return;
} }
// TODO
// else TODO
SmartDialog.showToast('view $param'); SmartDialog.showToast('view $param');
} }
}, },

View File

@@ -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,
),
),
],
),
),
],
),
),
),
);
}
}