opt: share origin img & lazy to opus (#768)

* opt: type

* opt: share origin img

* opt: lazy to opus
This commit is contained in:
My-Responsitories
2025-04-28 14:17:41 +08:00
committed by GitHub
parent a831b41623
commit 7f93b42a1b
7 changed files with 196 additions and 263 deletions

View File

@@ -786,6 +786,4 @@ class Api {
static const String articleView = '/x/article/view'; static const String articleView = '/x/article/view';
static const String opusDetail = '/x/polymer/web-dynamic/v1/opus/detail'; static const String opusDetail = '/x/polymer/web-dynamic/v1/opus/detail';
static const String feedInfoWeb = '${HttpString.tUrl}/x/im/feed/infoweb';
} }

View File

@@ -570,26 +570,4 @@ class MsgHttp {
static String getDevId() { static String getDevId() {
return Uuid().v4(); return Uuid().v4();
} }
static Future feedInfoWeb({
List? aids,
List? epIds,
List? articleIds,
}) async {
var res = await Request().get(
Api.feedInfoWeb,
queryParameters: {
if (aids != null) 'aids': aids.join(','),
if (epIds != null) 'ep_ids': epIds.join(','),
if (articleIds != null) 'article_ids': articleIds.join(','),
'build': 0,
'mobi_app': 'web',
},
);
if (res.data['code'] == 0) {
return {'status': true, 'data': res.data['data']};
} else {
return {'status': false, 'msg': res.data['message']};
}
}
} }

View File

@@ -1,7 +1,6 @@
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
import 'package:PiliPlus/http/dynamics.dart'; import 'package:PiliPlus/http/dynamics.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/msg.dart';
import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/dynamics/article_content_model.dart' import 'package:PiliPlus/models/dynamics/article_content_model.dart'
@@ -12,7 +11,6 @@ import 'package:PiliPlus/models/space_article/item.dart';
import 'package:PiliPlus/pages/common/reply_controller.dart'; import 'package:PiliPlus/pages/common/reply_controller.dart';
import 'package:PiliPlus/pages/mine/controller.dart'; import 'package:PiliPlus/pages/mine/controller.dart';
import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/url_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 'package:get/get.dart'; import 'package:get/get.dart';
@@ -23,7 +21,9 @@ class ArticleController extends ReplyController<MainListReply> {
late String id; late String id;
late String type; late String type;
late String url; late String url = type == 'read'
? 'https://www.bilibili.com/read/cv$id'
: 'https://www.bilibili.com/opus/$id';
late int commentType; late int commentType;
late int commentId; late int commentId;
final summary = Summary(); final summary = Summary();
@@ -37,7 +37,7 @@ class ArticleController extends ReplyController<MainListReply> {
dynamic get sourceId => commentType == 12 ? 'cv$commentId' : id; dynamic get sourceId => commentType == 12 ? 'cv$commentId' : id;
final RxBool isLoaded = false.obs; final RxBool isLoaded = false.obs;
DynamicItemModel? opusData; // 采用opus信息作为动态信息, 标题信息从summary获取 DynamicItemModel? opusData; // 标题信息从summary获取, 动态没有favorite
Item? articleData; Item? articleData;
final Rx<ModuleStatModel?> stats = Rx<ModuleStatModel?>(null); final Rx<ModuleStatModel?> stats = Rx<ModuleStatModel?>(null);
@@ -50,52 +50,23 @@ class ArticleController extends ReplyController<MainListReply> {
id = Get.parameters['id']!; id = Get.parameters['id']!;
type = Get.parameters['type']!; type = Get.parameters['type']!;
if (Get.arguments?['item'] is DynamicItemModel) {
opusData = Get.arguments['item'];
if (opusData!.modules.moduleStat != null) {
stats.value = opusData!.modules.moduleStat!;
}
}
// to opus
if (type == 'read') {
UrlUtils.parseRedirectUrl('https://www.bilibili.com/read/cv$id/')
.then((url) {
if (url != null) {
id = url.split('/').last;
type = 'opus';
}
init();
});
} else {
init();
}
}
setUrl() {
url = type == 'read'
? 'https://www.bilibili.com/read/cv$id'
: 'https://www.bilibili.com/opus/$id';
}
init() {
setUrl();
commentType = type == 'picture' ? 11 : 12; commentType = type == 'picture' ? 11 : 12;
_queryContent(); _queryContent(); // lazy to opus
} }
Future<bool> queryOpus(opusId) async { Future<void> _queryOpus(opusId) async {
final res = await DynamicsHttp.opusDetail(opusId: opusId); final res = await DynamicsHttp.opusDetail(opusId: opusId);
if (res is Success) { if (res.isSuccess) {
final opusData = (res as Success<DynamicItemModel>).response; final opusData = res.data;
//fallback //fallback
if (opusData.fallback?.id != null) { if (opusData.fallback?.id != null) {
id = opusData.fallback!.id!; id = opusData.fallback!.id!;
type = 'read'; type = 'read';
setUrl(); if (articleData?.content == null) {
_queryContent(); await _queryRead(id, false);
return false; }
return;
} }
this.opusData = opusData; this.opusData = opusData;
commentType = opusData.basic!.commentType!; commentType = opusData.basic!.commentType!;
@@ -106,44 +77,45 @@ class ArticleController extends ReplyController<MainListReply> {
summary summary
..author ??= opusData.modules.moduleAuthor ..author ??= opusData.modules.moduleAuthor
..title ??= opusData.modules.moduleTag?.text; ..title ??= opusData.modules.moduleTag?.text;
return true; isLoaded.value = true;
} }
return false;
} }
Future<bool> queryRead(cvid) async { Future<void> _queryRead(cvId, [bool toOpus = false]) async {
final res = await DynamicsHttp.articleView(cvId: cvid); final res = await DynamicsHttp.articleView(cvId: cvId);
if (res is Success) { if (res.isSuccess) {
articleData = (res as Success<Item>).response; articleData = res.data;
summary summary
..author ??= articleData!.author ..author ??= articleData!.author
..title ??= articleData!.title ..title ??= articleData!.title
..cover ??= articleData!.originImageUrls?.firstOrNull; ..cover ??= articleData!.originImageUrls?.firstOrNull;
isLoaded.value = true;
if (showDynActionBar) { if (toOpus &&
_queryReadAsDyn(articleData!.dynIdStr); articleData!.dynIdStr != null &&
_getArticleInfo(); articleData?.opus?.content?.isNotEmpty != true) {
await _queryOpus(articleData!.dynIdStr);
if (opusData != null) {
id = articleData!.dynIdStr!;
type = 'opus';
isLoaded.refresh();
}
}
if (showDynActionBar && stats.value == null) {
// _queryReadAsDyn(articleData!.dynIdStr);
getArticleInfo();
} }
return true;
}
return false;
}
// data for forward
Future _queryReadAsDyn(id) async {
if (opusData != null) {
return;
}
final res = await DynamicsHttp.dynamicDetail(id: id);
if (res['status']) {
opusData = res['data'];
} }
} }
// stats // stats
Future _getArticleInfo() async { Future<bool> getArticleInfo() async {
final res = await DynamicsHttp.articleInfo(cvId: commentId); final res = await DynamicsHttp.articleInfo(cvId: commentId);
if (res['status']) { if (res['status']) {
summary
..cover ??= (res['data']?['origin_image_urls'] as List?)?.firstOrNull
..title ??= res['data']?['title'];
stats.value = ModuleStatModel( stats.value = ModuleStatModel(
comment: DynamicStat(count: res['data']?['stats']?['reply']), comment: DynamicStat(count: res['data']?['stats']?['reply']),
forward: DynamicStat(count: res['data']?['stats']?['share']), forward: DynamicStat(count: res['data']?['stats']?['share']),
@@ -156,17 +128,20 @@ class ArticleController extends ReplyController<MainListReply> {
status: res['data']?['favorite'], status: res['data']?['favorite'],
), ),
); );
return true;
} }
SmartDialog.showToast(res['msg']);
return false;
} }
// 请求动态内容 // 请求动态内容
Future _queryContent() async { Future _queryContent() async {
if (type != 'read') { if (type != 'read') {
isLoaded.value = await queryOpus(id); await _queryOpus(id);
} else { } else {
commentId = int.parse(id); commentId = int.parse(id);
commentType = 12; commentType = 12;
isLoaded.value = await queryRead(commentId); await _queryRead(commentId, true);
} }
if (isLoaded.value) { if (isLoaded.value) {
queryData(); queryData();
@@ -219,7 +194,8 @@ class ArticleController extends ReplyController<MainListReply> {
Future onLike(VoidCallback callback) async { Future onLike(VoidCallback callback) async {
bool isLike = stats.value?.like?.status == true; bool isLike = stats.value?.like?.status == true;
final res = await DynamicsHttp.likeDynamic( final res = await DynamicsHttp.likeDynamic(
dynamicId: opusData?.idStr, up: isLike ? 2 : 1); dynamicId: opusData?.idStr ?? articleData?.dynIdStr,
up: isLike ? 2 : 1);
if (res['status']) { if (res['status']) {
stats.value?.like?.status = !isLike; stats.value?.like?.status = !isLike;
int count = stats.value?.like?.count ?? 0; int count = stats.value?.like?.count ?? 0;
@@ -234,19 +210,6 @@ class ArticleController extends ReplyController<MainListReply> {
SmartDialog.showToast(res['msg']); SmartDialog.showToast(res['msg']);
} }
} }
Future getArticleCover() async {
final res = await MsgHttp.feedInfoWeb(articleIds: [commentId]);
if (res['status']) {
summary.cover = ((res['data']?['article'] as List?)
?.firstOrNull?['image_urls'] as List?)
?.firstOrNull;
// debugPrint('cover: ${summary.cover}');
return summary.cover != null;
} else {
SmartDialog.showToast(res['msg']);
}
}
} }
class Summary { class Summary {

View File

@@ -626,8 +626,7 @@ class _ArticlePageState extends State<ArticlePage>
onTap: () async { onTap: () async {
try { try {
if (_articleCtr.summary.cover == null) { if (_articleCtr.summary.cover == null) {
final res = await _articleCtr.getArticleCover(); if (!await _articleCtr.getArticleInfo()) {
if (res != true) {
return; return;
} }
} }

View File

@@ -40,7 +40,7 @@ InlineSpan picsNodes(List<OpusPicsModel> pics, callback) {
); );
} }
Widget _blockedItem(BuildContext context, item, source) { Widget _blockedItem(BuildContext context, DynamicItemModel item, source) {
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.only( padding: EdgeInsets.only(
@@ -49,16 +49,16 @@ Widget _blockedItem(BuildContext context, item, source) {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (item.modules.moduleDynamic.major.blocked['title'] != null) if (item.modules.moduleDynamic!.major!.blocked!['title'] != null)
Text( Text(
item.modules.moduleDynamic.major.blocked['title'], item.modules.moduleDynamic!.major!.blocked!['title'],
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.secondary, color: Theme.of(context).colorScheme.secondary,
), ),
), ),
if (item.modules.moduleDynamic.major.blocked['hint_message'] != null) if (item.modules.moduleDynamic!.major!.blocked!['hint_message'] != null)
Text( Text(
item.modules.moduleDynamic.major.blocked['hint_message'], item.modules.moduleDynamic!.major!.blocked!['hint_message'],
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
@@ -69,14 +69,14 @@ Widget _blockedItem(BuildContext context, item, source) {
); );
} }
Widget forWard(bool isSave, item, BuildContext context, source, callback, Widget forWard(
bool isSave, DynamicItemModel item, BuildContext context, source, callback,
{floor = 1}) { {floor = 1}) {
switch (item.type) { switch (item.type) {
// 图文 // 图文
case 'DYNAMIC_TYPE_DRAW': case 'DYNAMIC_TYPE_DRAW':
bool hasPics = item.modules.moduleDynamic.major != null && bool hasPics =
item.modules.moduleDynamic.major.opus != null && item.modules.moduleDynamic?.major?.opus?.pics?.isNotEmpty == true;
item.modules.moduleDynamic.major.opus.pics.isNotEmpty;
InlineSpan? richNodes = richNode(item, context); InlineSpan? richNodes = richNode(item, context);
return Column( return Column(
@@ -87,17 +87,17 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
children: [ children: [
GestureDetector( GestureDetector(
onTap: () => Get.toNamed( onTap: () => Get.toNamed(
'/member?mid=${item.modules.moduleAuthor.mid}', '/member?mid=${item.modules.moduleAuthor!.mid}',
arguments: {'face': item.modules.moduleAuthor.face}), arguments: {'face': item.modules.moduleAuthor!.face}),
child: Text( child: Text(
'@${item.modules.moduleAuthor.name}', '@${item.modules.moduleAuthor!.name}',
style: style:
TextStyle(color: Theme.of(context).colorScheme.primary), TextStyle(color: Theme.of(context).colorScheme.primary),
), ),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Text( Text(
Utils.dateFormat(item.modules.moduleAuthor.pubTs), Utils.dateFormat(item.modules.moduleAuthor!.pubTs),
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
fontSize: fontSize:
@@ -123,7 +123,8 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
), ),
if (hasPics) ...[ if (hasPics) ...[
Text.rich( Text.rich(
picsNodes(item.modules.moduleDynamic.major.opus.pics, callback), picsNodes(
item.modules.moduleDynamic!.major!.opus!.pics!, callback),
), ),
], ],
const SizedBox(height: 4), const SizedBox(height: 4),
@@ -136,14 +137,14 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
), ),
/// 附加内容 商品信息、直播预约等等 /// 附加内容 商品信息、直播预约等等
if (item.modules.moduleDynamic.additional != null) if (item.modules.moduleDynamic?.additional != null)
addWidget( addWidget(
item, item,
context, context,
item.modules.moduleDynamic.additional.type, item.modules.moduleDynamic?.additional?.type,
floor: floor, floor: floor,
), ),
if (item?.modules.moduleDynamic?.major?.blocked != null) if (item.modules.moduleDynamic?.major?.blocked != null)
_blockedItem(context, item, source), _blockedItem(context, item, source),
], ],
); );
@@ -152,93 +153,87 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
return videoSeasonWidget(source, item, context, 'archive', floor: floor); return videoSeasonWidget(source, item, context, 'archive', floor: floor);
// 文章 // 文章
case 'DYNAMIC_TYPE_ARTICLE': case 'DYNAMIC_TYPE_ARTICLE':
return switch (item) { return item.isForwarded == true
DynamicItemModel() => item.isForwarded == true ? articlePanel(source, item, context, callback, floor: floor)
? articlePanel(source, item, context, callback, floor: floor) : item.modules.moduleDynamic?.major?.blocked != null
: item.modules.moduleDynamic?.major?.blocked != null ? Padding(
? Padding( padding: const EdgeInsets.symmetric(horizontal: 12),
padding: const EdgeInsets.symmetric(horizontal: 12), child: Column(
child: Column( mainAxisSize: MainAxisSize.min,
mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ if (item.modules.moduleDynamic?.major
if (item.modules.moduleDynamic?.major ?.blocked?['title'] !=
?.blocked?['title'] != null)
null) Text(
Text( item.modules.moduleDynamic!.major!.blocked!['title'],
'${item.modules.moduleDynamic?.major?.blocked!['title']}', style: TextStyle(
style: TextStyle( color: Theme.of(context).colorScheme.secondary,
color: Theme.of(context).colorScheme.secondary,
),
), ),
if (item.modules.moduleDynamic?.major ),
?.blocked?['hint_message'] != if (item.modules.moduleDynamic?.major
null) ?.blocked?['hint_message'] !=
Text( null)
'${item.modules.moduleDynamic?.major?.blocked!['hint_message']}', Text(
style: TextStyle( item.modules.moduleDynamic!.major!
fontSize: 12, .blocked!['hint_message'],
color: Theme.of(context).colorScheme.outline, style: TextStyle(
), fontSize: 12,
) color: Theme.of(context).colorScheme.outline,
], ),
), )
) ],
: const SizedBox.shrink(), ),
_ => const SizedBox.shrink(), )
}; : const SizedBox.shrink();
// 转发 // 转发
case 'DYNAMIC_TYPE_FORWARD': case 'DYNAMIC_TYPE_FORWARD':
final isNoneMajor =
item.orig?.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_NONE';
return InkWell( return InkWell(
onTap: () { onTap: isNoneMajor
if (item.orig.modules.moduleDynamic.major?.type == ? null
'MAJOR_TYPE_NONE') { : () => PageUtils.pushDynDetail(item.orig!, floor + 1),
return; onLongPress: isNoneMajor
} ? null
PageUtils.pushDynDetail(item.orig, floor + 1); : () {
}, late String? title, cover;
onLongPress: () { late var origMajor = item.orig?.modules.moduleDynamic?.major;
if (item.orig.modules.moduleDynamic.major?.type == late var major = item.modules.moduleDynamic?.major;
'MAJOR_TYPE_NONE') { switch (item.orig?.type) {
return; case 'DYNAMIC_TYPE_AV':
} title = origMajor?.archive?.title;
if (item.orig.type == 'DYNAMIC_TYPE_AV') { cover = origMajor?.archive?.cover;
imageSaveDialog( break;
context: context, case 'DYNAMIC_TYPE_UGC_SEASON':
title: item.orig.modules.moduleDynamic.major.archive.title, title = origMajor?.ugcSeason?.title;
cover: item.orig.modules.moduleDynamic.major.archive.cover, cover = origMajor?.ugcSeason?.cover;
); break;
} else if (item.orig.type == 'DYNAMIC_TYPE_UGC_SEASON') { case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
imageSaveDialog( title = origMajor?.pgc?.title;
context: context, cover = origMajor?.pgc?.cover;
title: item.orig.modules.moduleDynamic.major.ugcSeason.title, break;
cover: item.orig.modules.moduleDynamic.major.ugcSeason.cover, case 'DYNAMIC_TYPE_LIVE_RCMD':
); title = major?.liveRcmd?.title;
} else if (item.orig.type == 'DYNAMIC_TYPE_PGC' || cover = major?.liveRcmd?.cover;
item.orig.type == 'DYNAMIC_TYPE_PGC_UNION') { break;
imageSaveDialog( case 'DYNAMIC_TYPE_LIVE':
context: context, title = major?.live?.title;
title: item.orig.modules.moduleDynamic.major.pgc.title, cover = major?.live?.cover;
cover: item.orig.modules.moduleDynamic.major.pgc.cover, break;
); default:
} else if (item.type == 'DYNAMIC_TYPE_LIVE_RCMD') { return;
imageSaveDialog( }
context: context, imageSaveDialog(
title: item.modules.moduleDynamic.major.liveRcmd.title, context: context,
cover: item.modules.moduleDynamic.major.liveRcmd.cover, title: title,
); cover: cover,
} else if (item.type == 'DYNAMIC_TYPE_LIVE') { );
imageSaveDialog( },
context: context,
title: item.modules.moduleDynamic.major.live.title,
cover: item.modules.moduleDynamic.major.live.cover,
);
}
},
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
color: Theme.of(context).dividerColor.withOpacity(0.08), color: Theme.of(context).dividerColor.withOpacity(0.08),
child: forWard(isSave, item.orig, context, source, callback, child: forWard(isSave, item.orig!, context, source, callback,
floor: floor + 1), floor: floor + 1),
), ),
); );
@@ -261,17 +256,17 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
children: [ children: [
GestureDetector( GestureDetector(
onTap: () => Get.toNamed( onTap: () => Get.toNamed(
'/member?mid=${item.modules.moduleAuthor.mid}', '/member?mid=${item.modules.moduleAuthor?.mid}',
arguments: {'face': item.modules.moduleAuthor.face}), arguments: {'face': item.modules.moduleAuthor?.face}),
child: Text( child: Text(
'@${item.modules.moduleAuthor.name}', '@${item.modules.moduleAuthor?.name}',
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.primary), color: Theme.of(context).colorScheme.primary),
), ),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Text( Text(
Utils.dateFormat(item.modules.moduleAuthor.pubTs), Utils.dateFormat(item.modules.moduleAuthor?.pubTs),
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
fontSize: fontSize:
@@ -297,14 +292,14 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
), ),
], ],
) )
: item.modules.moduleDynamic.additional != null : item.modules.moduleDynamic?.additional != null
? addWidget( ? addWidget(
item, item,
context, context,
item.modules.moduleDynamic.additional.type, item.modules.moduleDynamic!.additional!.type,
floor: floor, floor: floor,
) )
: item?.modules.moduleDynamic?.major?.blocked != null : item.modules.moduleDynamic?.major?.blocked != null
? _blockedItem(context, item, source) ? _blockedItem(context, item, source)
: const SizedBox(height: 0); : const SizedBox(height: 0);
case 'DYNAMIC_TYPE_PGC': case 'DYNAMIC_TYPE_PGC':
@@ -320,7 +315,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
size: 14, size: 14,
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text(item.modules.moduleDynamic.major.none.tips) Text(item.modules.moduleDynamic!.major!.none!.tips!)
], ],
); );
// 课堂 // 课堂
@@ -329,7 +324,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
"课堂💪:${item.modules.moduleDynamic.major.courses['title']}", "课堂💪:${item.modules.moduleDynamic!.major!.courses!['title']}",
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@@ -341,7 +336,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
return InkWell( return InkWell(
onTap: () { onTap: () {
try { try {
String url = item.modules.moduleDynamic.major.common['jump_url']; String url = item.modules.moduleDynamic!.major!.common!['jump_url'];
if (url.contains('bangumi/play') && PageUtils.viewPgcFromUri(url)) { if (url.contains('bangumi/play') && PageUtils.viewPgcFromUri(url)) {
return; return;
} }
@@ -360,7 +355,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
radius: 8, radius: 8,
width: 45, width: 45,
height: 45, height: 45,
src: item.modules.moduleDynamic.major.common['cover'], src: item.modules.moduleDynamic!.major!.common!['cover'],
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
@@ -368,7 +363,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
item.modules.moduleDynamic.major.common['title'], item.modules.moduleDynamic!.major!.common!['title'],
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
), ),
@@ -377,7 +372,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
), ),
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
item.modules.moduleDynamic.major.common['desc'], item.modules.moduleDynamic!.major!.common!['desc'],
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
fontSize: fontSize:
@@ -394,7 +389,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
), ),
); );
case 'DYNAMIC_TYPE_MUSIC': case 'DYNAMIC_TYPE_MUSIC':
final Map music = item.modules.moduleDynamic.major.music; final Map music = item.modules.moduleDynamic!.major!.music!;
return InkWell( return InkWell(
onTap: () { onTap: () {
PageUtils.handleWebview("https:${music['jump_url']}"); PageUtils.handleWebview("https:${music['jump_url']}");
@@ -450,7 +445,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
GestureDetector( GestureDetector(
onTap: () { onTap: () {
Get.toNamed( Get.toNamed(
'/member?mid=${item.modules.moduleAuthor.mid}', '/member?mid=${item.modules.moduleAuthor!.mid}',
); );
}, },
child: Row( child: Row(
@@ -459,15 +454,15 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
width: 28, width: 28,
height: 28, height: 28,
type: 'avatar', type: 'avatar',
src: item.modules.moduleAuthor.face, src: item.modules.moduleAuthor!.face,
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Text( Text(
item.modules.moduleAuthor.name, item.modules.moduleAuthor!.name!,
style: TextStyle( style: TextStyle(
color: item.modules.moduleAuthor!.vip != null && color: item.modules.moduleAuthor!.vip != null &&
item.modules.moduleAuthor!.vip['status'] > 0 && item.modules.moduleAuthor!.vip!['status'] > 0 &&
item.modules.moduleAuthor!.vip['type'] == 2 item.modules.moduleAuthor!.vip!['type'] == 2
? context.vipColor ? context.vipColor
: Theme.of(context).colorScheme.onSurface, : Theme.of(context).colorScheme.onSurface,
fontSize: fontSize:
@@ -486,17 +481,18 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
Stack( Stack(
children: [ children: [
Hero( Hero(
tag: item.modules.moduleDynamic.major.medialist['cover'], tag: item.modules.moduleDynamic!.major!.medialist!['cover'],
child: NetworkImgLayer( child: NetworkImgLayer(
width: 180, width: 180,
height: 110, height: 110,
src: item.modules.moduleDynamic.major.medialist['cover'], src: item
.modules.moduleDynamic!.major!.medialist!['cover'],
), ),
), ),
PBadge( PBadge(
right: 6, right: 6,
top: 6, top: 6,
text: item.modules.moduleDynamic.major.medialist['badge'] text: item.modules.moduleDynamic!.major!.medialist!['badge']
?['text'], ?['text'],
) )
], ],
@@ -512,7 +508,7 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
children: [ children: [
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
item.modules.moduleDynamic.major.medialist['title'], item.modules.moduleDynamic!.major!.medialist!['title'],
style: TextStyle( style: TextStyle(
fontSize: Theme.of(context) fontSize: Theme.of(context)
.textTheme .textTheme
@@ -520,13 +516,13 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback,
.fontSize, .fontSize,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
), ),
if (item.modules.moduleDynamic.major if (item.modules.moduleDynamic?.major
.medialist['sub_title'] != ?.medialist?['sub_title'] !=
null) ...[ null) ...[
const Spacer(), const Spacer(),
Text( Text(
item.modules.moduleDynamic.major item.modules.moduleDynamic!.major!
.medialist['sub_title'], .medialist!['sub_title'],
style: TextStyle( style: TextStyle(
fontSize: Theme.of(context) fontSize: Theme.of(context)
.textTheme .textTheme

View File

@@ -9,10 +9,10 @@ import 'package:PiliPlus/utils/utils.dart';
import 'rich_node_panel.dart'; import 'rich_node_panel.dart';
Widget liveRcmdPanel(source, item, context, {floor = 1}) { Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) {
TextStyle authorStyle = TextStyle authorStyle =
TextStyle(color: Theme.of(context).colorScheme.primary); TextStyle(color: Theme.of(context).colorScheme.primary);
DynamicLiveModel liveRcmd = item.modules.moduleDynamic.major.liveRcmd; DynamicLiveModel liveRcmd = item.modules.moduleDynamic!.major!.liveRcmd!;
int liveStatus = liveRcmd.liveStatus!; int liveStatus = liveRcmd.liveStatus!;
Map watchedShow = liveRcmd.watchedShow!; Map watchedShow = liveRcmd.watchedShow!;
InlineSpan? richNodes = richNode(item, context); InlineSpan? richNodes = richNode(item, context);
@@ -24,16 +24,16 @@ Widget liveRcmdPanel(source, item, context, {floor = 1}) {
children: [ children: [
GestureDetector( GestureDetector(
onTap: () => Get.toNamed( onTap: () => Get.toNamed(
'/member?mid=${item.modules.moduleAuthor.mid}', '/member?mid=${item.modules.moduleAuthor?.mid}',
arguments: {'face': item.modules.moduleAuthor.face}), arguments: {'face': item.modules.moduleAuthor?.face}),
child: Text( child: Text(
'@${item.modules.moduleAuthor.name}', '@${item.modules.moduleAuthor?.name}',
style: authorStyle, style: authorStyle,
), ),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Text( Text(
Utils.dateFormat(item.modules.moduleAuthor.pubTs), Utils.dateFormat(item.modules.moduleAuthor?.pubTs),
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.outline, color: Theme.of(context).colorScheme.outline,
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize), fontSize: Theme.of(context).textTheme.labelSmall!.fontSize),
@@ -42,20 +42,20 @@ Widget liveRcmdPanel(source, item, context, {floor = 1}) {
), ),
], ],
const SizedBox(height: 4), const SizedBox(height: 4),
if (item.modules.moduleDynamic.topic != null) ...[ if (item.modules.moduleDynamic?.topic != null) ...[
Padding( Padding(
padding: padding:
const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
child: GestureDetector( child: GestureDetector(
child: Text( child: Text(
'#${item.modules.moduleDynamic.topic.name}', '#${item.modules.moduleDynamic!.topic!.name}',
style: authorStyle, style: authorStyle,
), ),
), ),
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
], ],
if (floor == 2 && item.modules.moduleDynamic.desc != null) ...[ if (floor == 2 && item.modules.moduleDynamic?.desc != null) ...[
if (richNodes != null) Text.rich(richNodes), if (richNodes != null) Text.rich(richNodes),
const SizedBox(height: 6), const SizedBox(height: 6),
], ],
@@ -75,7 +75,7 @@ Widget liveRcmdPanel(source, item, context, {floor = 1}) {
child: NetworkImgLayer( child: NetworkImgLayer(
width: width, width: width,
height: width / StyleString.aspectRatio, height: width / StyleString.aspectRatio,
src: item.modules.moduleDynamic.major.liveRcmd.cover, src: item.modules.moduleDynamic?.major?.liveRcmd?.cover,
), ),
), ),
PBadge( PBadge(
@@ -126,8 +126,8 @@ Widget liveRcmdPanel(source, item, context, {floor = 1}) {
color: Colors.white), color: Colors.white),
child: Row( child: Row(
children: [ children: [
Text(item.modules.moduleDynamic.major.liveRcmd Text(item.modules.moduleDynamic?.major?.liveRcmd
.areaName ?? ?.areaName ??
''), ''),
], ],
), ),
@@ -144,7 +144,7 @@ Widget liveRcmdPanel(source, item, context, {floor = 1}) {
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
child: Text( child: Text(
item.modules.moduleDynamic.major.liveRcmd.title, item.modules.moduleDynamic!.major!.liveRcmd!.title!,
maxLines: source == 'detail' ? null : 1, maxLines: source == 'detail' ? null : 1,
style: const TextStyle(fontWeight: FontWeight.bold), style: const TextStyle(fontWeight: FontWeight.bold),
overflow: source == 'detail' ? null : TextOverflow.ellipsis, overflow: source == 'detail' ? null : TextOverflow.ellipsis,

View File

@@ -272,9 +272,6 @@ class PageUtils {
'id': id, 'id': id,
'type': 'opus', 'type': 'opus',
}, },
arguments: {
'item': data,
},
off: off, off: off,
); );
} else { } else {
@@ -344,7 +341,8 @@ class PageUtils {
); );
} }
static void pushDynDetail(item, floor, {action = 'all'}) async { static void pushDynDetail(DynamicItemModel item, floor,
{action = 'all'}) async {
feedBack(); feedBack();
/// 点击评论action 直接查看评论 /// 点击评论action 直接查看评论
@@ -364,14 +362,14 @@ class PageUtils {
switch (item.type) { switch (item.type) {
case 'DYNAMIC_TYPE_AV': case 'DYNAMIC_TYPE_AV':
if (item.modules.moduleDynamic.major.archive?.type == 2) { if (item.modules.moduleDynamic?.major?.archive?.type == 2) {
if (item.modules.moduleDynamic.major.archive.jumpUrl if (item.modules.moduleDynamic!.major!.archive!.jumpUrl!
.startsWith('//')) { .startsWith('//')) {
item.modules.moduleDynamic.major.archive.jumpUrl = item.modules.moduleDynamic!.major!.archive!.jumpUrl =
'https:${item.modules.moduleDynamic.major.archive.jumpUrl}'; 'https:${item.modules.moduleDynamic!.major!.archive!.jumpUrl!}';
} }
String? redirectUrl = await UrlUtils.parseRedirectUrl( String? redirectUrl = await UrlUtils.parseRedirectUrl(
item.modules.moduleDynamic.major.archive.jumpUrl, false); item.modules.moduleDynamic!.major!.archive!.jumpUrl!, false);
if (redirectUrl != null) { if (redirectUrl != null) {
viewPgcFromUri(redirectUrl); viewPgcFromUri(redirectUrl);
return; return;
@@ -379,8 +377,8 @@ class PageUtils {
} }
try { try {
String bvid = item.modules.moduleDynamic.major.archive.bvid; String bvid = item.modules.moduleDynamic!.major!.archive!.bvid!;
String cover = item.modules.moduleDynamic.major.archive.cover; String cover = item.modules.moduleDynamic!.major!.archive!.cover!;
int cid = await SearchHttp.ab2c(bvid: bvid); int cid = await SearchHttp.ab2c(bvid: bvid);
toVideoPage( toVideoPage(
'bvid=$bvid&cid=$cid', 'bvid=$bvid&cid=$cid',
@@ -397,7 +395,7 @@ class PageUtils {
/// 专栏文章查看 /// 专栏文章查看
case 'DYNAMIC_TYPE_ARTICLE': case 'DYNAMIC_TYPE_ARTICLE':
String? url = item?.modules?.moduleDynamic?.major?.opus?.jumpUrl; String? url = item.modules.moduleDynamic?.major?.opus?.jumpUrl;
if (url != null) { if (url != null) {
if (url.contains('opus') || url.contains('read')) { if (url.contains('opus') || url.contains('read')) {
RegExp digitRegExp = RegExp(r'\d+'); RegExp digitRegExp = RegExp(r'\d+');
@@ -422,8 +420,9 @@ class PageUtils {
break; break;
case 'DYNAMIC_TYPE_LIVE_RCMD': case 'DYNAMIC_TYPE_LIVE_RCMD':
DynamicLiveModel liveRcmd = item.modules.moduleDynamic.major.liveRcmd; DynamicLiveModel liveRcmd =
ModuleAuthorModel author = item.modules.moduleAuthor; item.modules.moduleDynamic!.major!.liveRcmd!;
ModuleAuthorModel author = item.modules.moduleAuthor!;
LiveItemModel liveItem = LiveItemModel.fromJson({ LiveItemModel liveItem = LiveItemModel.fromJson({
'title': liveRcmd.title, 'title': liveRcmd.title,
'uname': author.name, 'uname': author.name,
@@ -439,7 +438,7 @@ class PageUtils {
/// 合集查看 /// 合集查看
case 'DYNAMIC_TYPE_UGC_SEASON': case 'DYNAMIC_TYPE_UGC_SEASON':
DynamicArchiveModel ugcSeason = DynamicArchiveModel ugcSeason =
item.modules.moduleDynamic.major.ugcSeason; item.modules.moduleDynamic!.major!.ugcSeason!;
int aid = ugcSeason.aid!; int aid = ugcSeason.aid!;
String bvid = IdUtils.av2bv(aid); String bvid = IdUtils.av2bv(aid);
String cover = ugcSeason.cover!; String cover = ugcSeason.cover!;
@@ -457,23 +456,23 @@ class PageUtils {
/// 番剧查看 /// 番剧查看
case 'DYNAMIC_TYPE_PGC_UNION': case 'DYNAMIC_TYPE_PGC_UNION':
debugPrint('DYNAMIC_TYPE_PGC_UNION 番剧'); debugPrint('DYNAMIC_TYPE_PGC_UNION 番剧');
DynamicArchiveModel pgc = item.modules.moduleDynamic.major.pgc; DynamicArchiveModel pgc = item.modules.moduleDynamic!.major!.pgc!;
if (pgc.epid != null) { if (pgc.epid != null) {
viewBangumi(epId: pgc.epid); viewBangumi(epId: pgc.epid);
} }
break; break;
case 'DYNAMIC_TYPE_MEDIALIST': case 'DYNAMIC_TYPE_MEDIALIST':
if (item.modules?.moduleDynamic?.major?.medialist != null) { if (item.modules.moduleDynamic?.major?.medialist != null) {
final String? url = final String? url =
item.modules.moduleDynamic.major.medialist['jump_url']; item.modules.moduleDynamic!.major!.medialist!['jump_url'];
if (url?.contains('medialist/detail/ml') == true) { if (url?.contains('medialist/detail/ml') == true) {
Get.toNamed( Get.toNamed(
'/favDetail', '/favDetail',
parameters: { parameters: {
'heroTag': 'heroTag':
'${item.modules.moduleDynamic.major.medialist['cover']}', '${item.modules.moduleDynamic!.major!.medialist!['cover']}',
'mediaId': 'mediaId':
'${item.modules.moduleDynamic.major.medialist['id']}', '${item.modules.moduleDynamic!.major!.medialist!['id']}',
}, },
); );
} else if (url != null) { } else if (url != null) {