mod: show pendant/decorate

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-01-28 10:00:52 +08:00
parent 7f3f7f6bdd
commit b761c35d10
7 changed files with 356 additions and 161 deletions

View File

@@ -129,6 +129,7 @@ class ModuleAuthorModel {
this.type,
this.vip,
this.decorate,
this.pendant,
});
String? face;
@@ -143,7 +144,7 @@ class ModuleAuthorModel {
String? type;
Map? vip;
Map? decorate;
// Map? pendant;
Map? pendant;
ModuleAuthorModel.fromJson(Map<String, dynamic> json) {
face = json['face'];
@@ -159,7 +160,7 @@ class ModuleAuthorModel {
vip = json['vip'];
if (showDynDecorate) {
decorate = json['decorate'];
// pendant = json['pendant'];
pendant = json['pendant'];
}
}

View File

@@ -31,6 +31,13 @@ class AuthorPanel extends StatelessWidget {
this.onRemove,
});
Widget _buildAvatar(double size) => NetworkImgLayer(
width: size,
height: size,
type: 'avatar',
src: item.modules.moduleAuthor.face,
);
@override
Widget build(BuildContext context) {
return Stack(
@@ -57,12 +64,14 @@ class AuthorPanel extends StatelessWidget {
},
);
},
child: NetworkImgLayer(
width: 40,
height: 40,
type: 'avatar',
src: item.modules.moduleAuthor.face,
),
child: (item.modules.moduleAuthor?.pendant?['image'] as String?)
?.isNotEmpty ==
true
? Padding(
padding: const EdgeInsets.all(3),
child: _buildAvatar(34),
)
: _buildAvatar(40),
),
const SizedBox(width: 10),
Column(
@@ -137,58 +146,59 @@ class AuthorPanel extends StatelessWidget {
? Row(
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap:
item.modules.moduleAuthor.decorate['jump_url'] != null
? () {
Get.toNamed(
'/webview',
parameters: {
'url':
'${item.modules.moduleAuthor.decorate['jump_url']}'
},
);
}
: null,
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.centerRight,
children: [
CachedNetworkImage(
height: 32,
imageUrl:
item.modules.moduleAuthor.decorate['card_url'],
),
if ((item.modules.moduleAuthor.decorate?['fan']
?['num_str'] as String?)
?.isNotEmpty ==
true)
Padding(
padding: const EdgeInsets.only(right: 32),
child: Text(
'${item.modules.moduleAuthor.decorate['fan']['num_str']}',
style: TextStyle(
fontSize: 11,
fontFamily: 'digital_id_num',
color: (item.modules.moduleAuthor
.decorate?['fan']
?['color'] as String?)
?.startsWith('#') ==
true
? Color(
int.parse(
item.modules.moduleAuthor
.decorate['fan']['color']
.replaceFirst('#', '0xFF'),
),
)
: null,
),
// GestureDetector(
// onTap:
// item.modules.moduleAuthor.decorate['jump_url'] != null
// ? () {
// Get.toNamed(
// '/webview',
// parameters: {
// 'url':
// '${item.modules.moduleAuthor.decorate['jump_url']}'
// },
// );
// }
// : null,
// child:
Stack(
clipBehavior: Clip.none,
alignment: Alignment.centerRight,
children: [
CachedNetworkImage(
height: 32,
imageUrl:
item.modules.moduleAuthor.decorate['card_url'],
),
if ((item.modules.moduleAuthor.decorate?['fan']
?['num_str'] as String?)
?.isNotEmpty ==
true)
Padding(
padding: const EdgeInsets.only(right: 32),
child: Text(
'${item.modules.moduleAuthor.decorate['fan']['num_str']}',
style: TextStyle(
fontSize: 11,
fontFamily: 'digital_id_num',
color:
(item.modules.moduleAuthor.decorate?['fan']
?['color'] as String?)
?.startsWith('#') ==
true
? Color(
int.parse(
item.modules.moduleAuthor
.decorate['fan']['color']
.replaceFirst('#', '0xFF'),
),
)
: null,
),
),
],
),
),
],
),
// ),
_moreWidget(context),
],
)

View File

@@ -1,5 +1,6 @@
import 'package:PiliPlus/common/widgets/image_save.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'action_panel.dart';
import 'author_panel.dart';
@@ -79,27 +80,50 @@ class DynamicPanel extends StatelessWidget {
);
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(12, 12, 12, 6),
child: AuthorPanel(
item: item,
source: source,
onRemove: onRemove,
),
),
if (item!.modules!.moduleDynamic!.desc != null ||
item!.modules!.moduleDynamic!.major != null)
content(context, item, source, callback),
forWard(item, context, source, callback),
const SizedBox(height: 2),
if (source == null) ActionPanel(item: item),
],
),
child: (item.modules.moduleAuthor?.pendant?['image'] as String?)
?.isNotEmpty ==
true
? Stack(
clipBehavior: Clip.none,
children: [
_buildContent(context, item, source, callback),
Positioned(
left: 2,
top: 2,
child: IgnorePointer(
child: CachedNetworkImage(
width: 60,
height: 60,
imageUrl: item.modules.moduleAuthor.pendant['image'],
),
),
),
],
)
: _buildContent(context, item, source, callback),
),
),
);
}
Widget _buildContent(context, item, source, callback) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(12, 12, 12, 6),
child: AuthorPanel(
item: item,
source: source,
onRemove: onRemove,
),
),
if (item!.modules!.moduleDynamic!.desc != null ||
item!.modules!.moduleDynamic!.major != null)
content(context, item, source, callback),
forWard(item, context, source, callback),
const SizedBox(height: 2),
if (source == null) ActionPanel(item: item),
],
);
}

View File

@@ -1,4 +1,5 @@
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
import 'package:PiliPlus/models/dynamics/result.dart';
import 'package:PiliPlus/models/space/card.dart' as space;
import 'package:PiliPlus/models/space/images.dart' as space;
import 'package:PiliPlus/utils/extension.dart';
@@ -444,22 +445,22 @@ class UserInfoCard extends StatelessWidget {
),
);
_buildAvatar(BuildContext context) => Hero(
tag: card.face ?? 'avatarTag',
child: GestureDetector(
onTap: () {
context.imageView(
imgList: [card.face ?? 'avatarTag'],
);
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 2.5,
color: Theme.of(context).colorScheme.surface,
),
shape: BoxShape.circle,
),
_buildAvatar(BuildContext context) => Container(
decoration: BoxDecoration(
border: Border.all(
width: 2.5,
color: Theme.of(context).colorScheme.surface,
),
shape: BoxShape.circle,
),
child: Hero(
tag: card.face ?? 'avatarTag',
child: GestureDetector(
onTap: () {
context.imageView(
imgList: [card.face ?? 'avatarTag'],
);
},
child: NetworkImgLayer(
src: card.face,
type: 'avatar',
@@ -489,6 +490,19 @@ class UserInfoCard extends StatelessWidget {
left: 20,
child: _buildAvatar(context),
),
if (ModuleAuthorModel.showDynDecorate &&
card.pendant?.image?.isNotEmpty == true)
Positioned(
top: 82.5,
left: -7.5,
child: IgnorePointer(
child: CachedNetworkImage(
width: 140,
height: 140,
imageUrl: card.pendant!.image!,
),
),
),
if (card.officialVerify?.icon?.isNotEmpty == true ||
(card.vip?.vipStatus ?? -1) > 0)
Positioned(
@@ -572,6 +586,19 @@ class UserInfoCard extends StatelessWidget {
clipBehavior: Clip.none,
children: [
_buildAvatar(context),
if (ModuleAuthorModel.showDynDecorate &&
card.pendant?.image?.isNotEmpty == true)
Positioned(
top: -27.5,
left: -27.5,
child: IgnorePointer(
child: CachedNetworkImage(
width: 140,
height: 140,
imageUrl: card.pendant!.image!,
),
),
),
if (card.officialVerify?.icon?.isNotEmpty == true ||
(card.vip?.vipStatus ?? -1) > 0)
Positioned(

View File

@@ -1908,7 +1908,7 @@ List<SettingsModel> get extraSettings => [
),
SettingsModel(
settingsType: SettingsType.sw1tch,
title: '展示动态装饰',
title: '展示头像/评论/动态装饰',
leading: Icon(MdiIcons.stickerCircleOutline),
setKey: SettingBoxKey.showDynDecorate,
defaultVal: true,

View File

@@ -2,8 +2,10 @@ import 'dart:math';
import 'package:PiliPlus/common/widgets/imageview.dart';
import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/dynamics/result.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/global_data.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -77,10 +79,56 @@ class ReplyItem extends StatelessWidget {
},
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(12, 14, 8, 5),
child: content(context),
),
if (ModuleAuthorModel.showDynDecorate &&
(replyItem?.member?.userSailing?.cardbg?['image'] as String?)
?.isNotEmpty ==
true)
Stack(
clipBehavior: Clip.none,
children: [
Positioned(
top: 8,
right: 12,
child: Stack(
alignment: Alignment.centerRight,
children: [
CachedNetworkImage(
height: 38,
imageUrl:
replyItem?.member?.userSailing?.cardbg?['image'],
),
if ((replyItem?.member?.userSailing?.cardbg?['fan']
?['num_desc'] as String?)
?.isNotEmpty ==
true)
Text(
'NO.\n${replyItem?.member?.userSailing?.cardbg?['fan']?['num_desc']}',
style:
(replyItem?.member?.userSailing?.cardbg?['fan']
?['color'] as String?)
?.startsWith('#') ==
true
? TextStyle(
fontSize: 8,
fontFamily: 'digital_id_num',
color: Color(
int.parse(
replyItem?.member?.userSailing
?.cardbg?['fan']?['color']
.replaceFirst('#', '0xFF'),
),
),
)
: null,
),
],
),
),
_buildAuthorPanel(context),
],
)
else
_buildAuthorPanel(context),
if (needDivider)
Divider(
indent: 55,
@@ -97,18 +145,44 @@ class ReplyItem extends StatelessWidget {
);
}
Widget lfAvtar(BuildContext context, String heroTag) {
Widget _buildAuthorPanel(context) => Padding(
padding: const EdgeInsets.fromLTRB(12, 14, 8, 5),
child: content(context),
);
Widget lfAvtar(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
children: [
Hero(
tag: heroTag,
child: NetworkImgLayer(
if (ModuleAuthorModel.showDynDecorate &&
replyItem?.member?.pendant?.image?.isNotEmpty == true) ...[
Padding(
padding: const EdgeInsets.all(2),
child: NetworkImgLayer(
src: replyItem!.member!.avatar,
width: 30,
height: 30,
type: 'avatar',
),
),
Positioned(
left: -9,
top: -9,
child: IgnorePointer(
child: CachedNetworkImage(
width: 52,
height: 52,
imageUrl: replyItem!.member!.pendant!.image!,
),
),
),
] else
NetworkImgLayer(
src: replyItem!.member!.avatar,
width: 34,
height: 34,
type: 'avatar',
),
),
if (replyItem!.member!.vip!['vipStatus'] > 0)
Positioned(
right: 0,
@@ -171,27 +245,25 @@ class ReplyItem extends StatelessWidget {
Widget content(BuildContext context) {
if (replyItem?.member == null) return const SizedBox();
final String heroTag = Utils.makeHeroTag(replyItem!.mid);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/// fix Stack内GestureDetector onTap无效
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
feedBack();
Get.toNamed('/member?mid=${replyItem!.mid}', arguments: {
'face': replyItem!.member!.avatar!,
'heroTag': heroTag
});
Get.toNamed('/member?mid=${replyItem!.mid}');
},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
lfAvtar(context, heroTag),
lfAvtar(context),
const SizedBox(width: 12),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
@@ -223,6 +295,7 @@ class ReplyItem extends StatelessWidget {
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
Utils.dateFormat(replyItem!.ctime),
@@ -470,14 +543,8 @@ class ReplyItem extends StatelessWidget {
recognizer: TapGestureRecognizer()
..onTap = () {
feedBack();
final String heroTag = Utils.makeHeroTag(
replies![i].member!.mid);
Get.toNamed(
'/member?mid=${replies![i].member!.mid}',
arguments: {
'face': replies![i].member!.avatar,
'heroTag': heroTag
});
'/member?mid=${replies![i].member!.mid}');
},
),
if (replies![i].isUp!) ...[
@@ -682,11 +749,7 @@ class ReplyItem extends StatelessWidget {
),
recognizer: TapGestureRecognizer()
..onTap = () {
final String heroTag = Utils.makeHeroTag(userId);
Get.toNamed(
'/member?mid=$userId',
arguments: {'face': '', 'heroTag': heroTag},
);
Get.toNamed('/member?mid=$userId');
},
),
);

View File

@@ -4,9 +4,11 @@ import 'package:PiliPlus/common/widgets/badge.dart';
import 'package:PiliPlus/common/widgets/imageview.dart';
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/dynamics/result.dart';
import 'package:PiliPlus/pages/video/detail/reply/widgets/zan_grpc.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/global_data.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -89,40 +91,116 @@ class ReplyItemGrpc extends StatelessWidget {
},
);
},
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(12, 14, 8, 5),
child: content(context),
),
if (needDivider)
Divider(
indent: 55,
endIndent: 15,
height: 0.3,
color: Theme.of(context)
.colorScheme
.onInverseSurface
.withOpacity(0.5),
)
],
),
child: _buildContent(context),
),
);
}
Widget lfAvtar(BuildContext context, String heroTag) {
return Stack(
Widget _buildAuthorPanel(context) => Padding(
padding: const EdgeInsets.fromLTRB(12, 14, 8, 5),
child: content(context),
);
Widget _buildContent(context) {
print(replyItem.member.garbCardImage);
return Column(
children: [
Hero(
tag: heroTag,
child: NetworkImgLayer(
if (ModuleAuthorModel.showDynDecorate &&
replyItem.member.hasGarbCardImage())
Stack(
clipBehavior: Clip.none,
children: [
Positioned(
top: 8,
right: 12,
// child: GestureDetector(
// onTap: replyItem.member.garbCardJumpUrl.isNotEmpty
// ? () {
// Get.toNamed(
// 'webview',
// parameters: {
// 'url': replyItem.member.garbCardJumpUrl
// },
// );
// }
// : null,
child: Stack(
alignment: Alignment.centerRight,
children: [
CachedNetworkImage(
height: 38,
imageUrl: replyItem.member.garbCardImage,
),
if (replyItem.member.hasGarbCardNumber())
Text(
'NO.\n${replyItem.member.garbCardNumber}',
style: replyItem.member.garbCardFanColor.startsWith('#')
? TextStyle(
fontSize: 8,
fontFamily: 'digital_id_num',
color: Color(
int.parse(
replyItem.member.garbCardFanColor
.replaceFirst('#', '0xFF'),
),
),
)
: null,
),
],
),
),
// ),
_buildAuthorPanel(context),
],
)
else
_buildAuthorPanel(context),
if (needDivider)
Divider(
indent: 55,
endIndent: 15,
height: 0.3,
color:
Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.5),
)
],
);
}
Widget lfAvtar(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
children: [
if (ModuleAuthorModel.showDynDecorate &&
replyItem.member.hasGarbPendantImage()) ...[
Padding(
padding: const EdgeInsets.all(2),
child: NetworkImgLayer(
src: replyItem.member.face,
width: 30,
height: 30,
type: 'avatar',
),
),
Positioned(
left: -9,
top: -9,
child: IgnorePointer(
child: CachedNetworkImage(
width: 52,
height: 52,
imageUrl: replyItem.member.garbPendantImage,
),
),
),
] else
NetworkImgLayer(
src: replyItem.member.face,
width: 34,
height: 34,
type: 'avatar',
),
),
if (replyItem.member.vipStatus > 0)
Positioned(
right: 0,
@@ -182,28 +260,29 @@ class ReplyItemGrpc extends StatelessWidget {
}
Widget content(BuildContext context) {
final String heroTag = Utils.makeHeroTag(replyItem.mid);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/// fix Stack内GestureDetector onTap无效
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
feedBack();
Get.toNamed('/member?mid=${replyItem.mid}',
arguments: {'face': replyItem.member.face, 'heroTag': heroTag});
Get.toNamed('/member?mid=${replyItem.mid}');
},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
lfAvtar(context, heroTag),
lfAvtar(context),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
replyItem.member.name,
@@ -232,6 +311,7 @@ class ReplyItemGrpc extends StatelessWidget {
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
Utils.dateFormat(replyItem.ctime.toInt()),
@@ -496,15 +576,9 @@ class ReplyItemGrpc extends StatelessWidget {
recognizer: TapGestureRecognizer()
..onTap = () {
feedBack();
final String heroTag = Utils.makeHeroTag(
replyItem.replies[i].member.mid);
Get.toNamed(
'/member?mid=${replyItem.replies[i].member.mid}',
arguments: {
'face':
replyItem.replies[i].member.face,
'heroTag': heroTag
});
'/member?mid=${replyItem.replies[i].member.mid}',
);
},
),
if (replyItem.replies[i].mid == upMid) ...[
@@ -715,11 +789,7 @@ class ReplyItemGrpc extends StatelessWidget {
),
recognizer: TapGestureRecognizer()
..onTap = () {
final String heroTag = Utils.makeHeroTag(userId);
Get.toNamed(
'/member?mid=$userId',
arguments: {'face': '', 'heroTag': heroTag},
);
Get.toNamed('/member?mid=$userId');
},
),
);