improve handle opus nullType

Closes #2148

Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-05-20 12:21:39 +08:00
parent 46baad899c
commit 7c342032de

View File

@@ -81,9 +81,7 @@ class OpusContent extends StatelessWidget {
// case 'RICH_TEXT_NODE_TYPE_TOPIC':
default:
if (rich.jumpUrl != null) {
PiliScheme.routePushFromUrl(
rich.jumpUrl!,
);
PiliScheme.routePushFromUrl(rich.jumpUrl!);
}
}
},
@@ -100,7 +98,7 @@ class OpusContent extends StatelessWidget {
colorScheme.onSurfaceVariant,
BlendMode.srcIn,
),
alignment: Alignment.centerLeft,
alignment: .centerLeft,
placeholderBuilder: (_) => Text(latex),
errorBuilder: (_) => Text(latex),
),
@@ -281,7 +279,7 @@ class OpusContent extends StatelessWidget {
children: [
const WidgetSpan(
child: Icon(MdiIcons.circleMedium),
alignment: PlaceholderAlignment.middle,
alignment: .middle,
),
...entry.$2.nodes!.map((item) {
if (item.word != null) {
@@ -318,18 +316,272 @@ class OpusContent extends StatelessWidget {
),
);
case 6:
final type = element.linkCard!.card!.type;
Widget child;
switch (type) {
case 'LINK_CARD_TYPE_UGC':
final ugc = element.linkCard!.card!.ugc!;
child = Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: ugc.cover,
borderRadius: const .all(.circular(6)),
),
Expanded(
child: Column(
crossAxisAlignment: .start,
children: [
Text(ugc.title!),
Text(
ugc.descSecond!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
);
case 'LINK_CARD_TYPE_ITEM_NULL':
final itemNull = element.linkCard?.card?.itemNull;
child = Text(
' ${itemNull?.text}: ${element.linkCard?.card?.oid}',
);
case 'LINK_CARD_TYPE_COMMON':
final common = element.linkCard!.card!.common!;
child = Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: common.cover,
borderRadius: const .all(.circular(6)),
),
Expanded(
child: Column(
crossAxisAlignment: .start,
children: [
Text(common.title!),
if (common.desc1 != null)
Text(
common.desc1!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
if (common.desc2 != null)
Text(
common.desc2!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
);
case 'LINK_CARD_TYPE_LIVE':
final live = element.linkCard!.card!.live!;
child = Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: live.cover,
borderRadius: const .all(.circular(6)),
),
Expanded(
child: Column(
crossAxisAlignment: .start,
children: [
Text(live.title!),
if (live.descFirst != null)
Text(
live.descFirst!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
if (live.descSecond != null)
Text(
live.descSecond!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
);
case 'LINK_CARD_TYPE_OPUS':
final opus = element.linkCard!.card!.opus!;
child = Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: opus.cover,
borderRadius: const .all(.circular(6)),
),
Expanded(
child: Column(
crossAxisAlignment: .start,
children: [
Text(opus.title!),
Text(
'${opus.authorName} · ${opus.statView ?? 0}阅读',
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
);
case 'LINK_CARD_TYPE_VOTE':
final vote = element.linkCard!.card!.vote!;
child = Row(
spacing: 10,
children: [
Container(
decoration: BoxDecoration(
borderRadius: const .all(.circular(6)),
color: colorScheme.secondaryContainer,
),
width: 70,
height: 50,
alignment: .center,
child: Icon(
Icons.bar_chart_rounded,
color: colorScheme.onSurfaceVariant,
),
),
Expanded(
child: Column(
crossAxisAlignment: .start,
children: [
Text(vote.desc!),
Text(
'${vote.joinNum}人参与',
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
);
case 'LINK_CARD_TYPE_MUSIC':
final music = element.linkCard!.card!.music!;
child = Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: music.cover,
borderRadius: const .all(.circular(6)),
),
Expanded(
child: Column(
crossAxisAlignment: .start,
children: [
Text(music.title!),
if (music.label != null)
Text(
music.label!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
);
case 'LINK_CARD_TYPE_GOODS':
final goods = element.linkCard!.card!.goods!;
child = Column(
children: goods.items!.map((e) {
return GestureDetector(
onTap: () {
if (e.jumpUrl?.isNotEmpty == true) {
PiliScheme.routePushFromUrl(e.jumpUrl!);
}
},
child: Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: e.cover,
borderRadius: const .all(.circular(6)),
),
Expanded(
child: Column(
crossAxisAlignment: .start,
children: [
Text(e.name!),
if (e.brief?.isNotEmpty == true)
Text(
e.brief!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
if (e.price?.isNotEmpty == true)
Text(
'${e.price!}',
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
);
}).toList(),
);
default:
throw UnimplementedError(
'\nparaType: ${element.paraType},\ncard type: $type',
);
}
return Material(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
borderRadius: .all(.circular(8)),
),
color: colorScheme.onInverseSurface,
child: InkWell(
onTap: element.linkCard!.card!.type == 'LINK_CARD_TYPE_GOODS'
onTap: type == 'LINK_CARD_TYPE_GOODS'
? null
: () {
try {
if (element.linkCard!.card!.type ==
'LINK_CARD_TYPE_VOTE') {
if (type == 'LINK_CARD_TYPE_VOTE') {
showVoteDialog(
context,
element.linkCard!.card!.vote?.voteId ??
@@ -337,296 +589,42 @@ class OpusContent extends StatelessWidget {
);
return;
}
String? url =
switch (element.linkCard!.card!.type) {
'LINK_CARD_TYPE_UGC' =>
element.linkCard!.card!.ugc!.jumpUrl,
'LINK_CARD_TYPE_COMMON' =>
element.linkCard!.card!.common!.jumpUrl,
'LINK_CARD_TYPE_LIVE' =>
element.linkCard!.card!.live!.jumpUrl,
'LINK_CARD_TYPE_OPUS' =>
element.linkCard!.card!.opus!.jumpUrl,
'LINK_CARD_TYPE_MUSIC' =>
element.linkCard!.card!.music!.jumpUrl,
_ => null,
};
if (type == 'LINK_CARD_TYPE_ITEM_NULL') {
switch (element.linkCard?.card?.itemNull?.text) {
case '视频':
PiliScheme.videoPush(
int.parse(element.linkCard!.card!.oid!),
null,
);
default:
PageUtils.pushDynFromId(
id: element.linkCard!.card!.oid!,
);
}
return;
}
String? url = switch (type) {
'LINK_CARD_TYPE_UGC' =>
element.linkCard!.card!.ugc!.jumpUrl,
'LINK_CARD_TYPE_COMMON' =>
element.linkCard!.card!.common!.jumpUrl,
'LINK_CARD_TYPE_LIVE' =>
element.linkCard!.card!.live!.jumpUrl,
'LINK_CARD_TYPE_OPUS' =>
element.linkCard!.card!.opus!.jumpUrl,
'LINK_CARD_TYPE_MUSIC' =>
element.linkCard!.card!.music!.jumpUrl,
_ => null,
};
if (url != null && url.isNotEmpty) {
PiliScheme.routePushFromUrl(url);
}
} catch (_) {}
},
borderRadius: const BorderRadius.all(Radius.circular(8)),
borderRadius: const .all(.circular(8)),
child: Padding(
padding: const EdgeInsets.all(8),
child: switch (element.linkCard?.card?.type) {
'LINK_CARD_TYPE_UGC' => Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: element.linkCard!.card!.ugc!.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(element.linkCard!.card!.ugc!.title!),
Text(
element.linkCard!.card!.ugc!.descSecond!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
'LINK_CARD_TYPE_ITEM_NULL' => Row(
children: [
if (element
.linkCard
?.card
?.itemNull
?.icon
?.isNullOrEmpty ==
true)
const Icon(Icons.info, size: 20),
Text(' ${element.linkCard?.card?.itemNull?.text}'),
],
),
'LINK_CARD_TYPE_COMMON' => Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: element.linkCard!.card!.common!.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(element.linkCard!.card!.common!.title!),
if (element.linkCard!.card!.common!.desc1 !=
null)
Text(
element.linkCard!.card!.common!.desc1!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
if (element.linkCard!.card!.common!.desc2 !=
null)
Text(
element.linkCard!.card!.common!.desc2!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
'LINK_CARD_TYPE_LIVE' => Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: element.linkCard!.card!.live!.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(element.linkCard!.card!.live!.title!),
if (element.linkCard!.card!.live!.descFirst !=
null)
Text(
element.linkCard!.card!.live!.descFirst!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
if (element.linkCard!.card!.live!.descSecond !=
null)
Text(
element.linkCard!.card!.live!.descSecond!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
'LINK_CARD_TYPE_OPUS' => Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: element.linkCard!.card!.opus!.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(element.linkCard!.card!.opus!.title!),
Text(
'${element.linkCard!.card!.opus!.authorName} · ${element.linkCard!.card!.opus!.statView ?? 0}阅读',
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
'LINK_CARD_TYPE_VOTE' => Row(
spacing: 10,
children: [
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
color: colorScheme.secondaryContainer,
),
width: 70,
height: 50,
alignment: Alignment.center,
child: Icon(
Icons.bar_chart_rounded,
color: colorScheme.onSurfaceVariant,
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(element.linkCard!.card!.vote!.desc!),
Text(
'${element.linkCard!.card!.vote!.joinNum}人参与',
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
'LINK_CARD_TYPE_MUSIC' => Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: element.linkCard!.card!.music!.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(element.linkCard!.card!.music!.title!),
if (element.linkCard!.card!.music!.label !=
null)
Text(
element.linkCard!.card!.music!.label!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
'LINK_CARD_TYPE_GOODS' => Column(
children: element.linkCard!.card!.goods!.items!.map((
e,
) {
return GestureDetector(
onTap: () {
if (e.jumpUrl?.isNotEmpty == true) {
PiliScheme.routePushFromUrl(e.jumpUrl!);
}
},
child: Row(
spacing: 10,
children: [
NetworkImgLayer(
width: 104,
height: 65,
src: e.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(e.name!),
if (e.brief?.isNotEmpty == true)
Text(
e.brief!,
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
if (e.price?.isNotEmpty == true)
Text(
'${e.price!}',
style: TextStyle(
fontSize: 13,
color: colorScheme.outline,
),
),
],
),
),
],
),
);
}).toList(),
),
_ => throw UnimplementedError(
'\nparaType: ${element.paraType},\ncard type: ${element.linkCard?.card?.type}',
),
},
padding: const .all(8),
child: child,
),
),
);
@@ -648,12 +646,12 @@ class OpusContent extends StatelessWidget {
)
.render(renderer);
return Container(
padding: const EdgeInsets.all(12),
padding: const .all(12),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8)),
borderRadius: const .all(.circular(8)),
color: colorScheme.onInverseSurface,
),
width: double.infinity,
width: .infinity,
child: SelectableText.rich(renderer.span!),
);
case 8 when (element.heading?.nodes?.isNotEmpty == true):
@@ -691,7 +689,7 @@ class OpusContent extends StatelessWidget {
return SelectableText(
'不支持的类型 (${element.paraType})',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontWeight: .bold,
color: Colors.red,
),
);
@@ -700,7 +698,7 @@ class OpusContent extends StatelessWidget {
return SelectableText(
'错误的类型 $e',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontWeight: .bold,
color: Colors.red,
),
);
@@ -723,7 +721,7 @@ Widget moduleBlockedItem(
? null
: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
fit: .fill,
image: ResizeImage(
CachedNetworkImageProvider(
ImageUtils.thumbnailUrl(
@@ -759,7 +757,7 @@ Widget moduleBlockedItem(
return FilledButton.tonal(
style: FilledButton.styleFrom(
padding: padding,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
tapTargetSize: .shrinkWrap,
visualDensity: visualDensity,
backgroundColor: theme.colorScheme.btnColor,
foregroundColor: Colors.white,
@@ -771,7 +769,7 @@ Widget moduleBlockedItem(
}
},
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
if (moduleBlocked.button!.icon?.isNotEmpty == true)
CachedNetworkImage(
@@ -798,9 +796,9 @@ Widget moduleBlockedItem(
width: maxWidth,
height: maxWidth,
decoration: bgImg(maxWidth),
padding: const EdgeInsets.all(12),
padding: const .all(12),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: .center,
children: [
if (moduleBlocked.icon != null)
icon(math.max(40, maxWidth / 7)),
@@ -830,16 +828,16 @@ Widget moduleBlockedItem(
builder: (context, constraints) {
return Container(
decoration: bgImg(constraints.maxWidth),
padding: const EdgeInsets.all(12),
padding: const .all(12),
child: Row(
spacing: 8,
children: [
if (moduleBlocked.icon != null) icon(42),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
spacing: 2,
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
if (moduleBlocked.title?.isNotEmpty == true)
Text(moduleBlocked.title!),
@@ -862,9 +860,9 @@ Widget moduleBlockedItem(
horizontal: -4,
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6)),
borderRadius: .all(.circular(6)),
),
padding: const EdgeInsets.symmetric(horizontal: 10),
padding: const .symmetric(horizontal: 10),
),
],
),
@@ -891,15 +889,15 @@ Widget opusCollection(ThemeData theme, ModuleCollection item) {
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
Text(item.title!),
Text.rich(
TextSpan(
children: [
WidgetSpan(
alignment: PlaceholderAlignment.middle,
alignment: .middle,
child: Icon(
size: 18,
Icons.article_outlined,