diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index ac92d0722..10132342a 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -67,7 +67,7 @@ class VideoCardV extends StatelessWidget { if (uri.startsWith('http')) { String id = Uri.parse(uri).path.split('/')[1]; if (isStringNumeric(id)) { - PageUtils.pushDynFromId(id); + PageUtils.pushDynFromId(id: id); return; } } diff --git a/lib/http/html.dart b/lib/http/html.dart index 719537fa1..42b0437f8 100644 --- a/lib/http/html.dart +++ b/lib/http/html.dart @@ -24,9 +24,10 @@ class HtmlHttp { } try { if (response.data.contains('Redirecting to')) { - String? cvid = RegExp(r'cv\d+').firstMatch(response.data)?.group(0); - if (cvid != null) { - return await reqReadHtml(cvid, dynamicType, false); + RegExpMatch? cvid = + RegExp(r'/([a-zA-Z]+)/(cv\d+)').firstMatch(response.data); + if (cvid?.group(2) != null) { + return await reqReadHtml(cvid?.group(2), cvid?.group(1), false); } RegExp regex = RegExp(r'//([\w\.]+)/(\w+)/(\w+)'); @@ -185,6 +186,7 @@ class HtmlHttp { 'updateTime': '', 'content': opusContent, 'isJsonContent': isJsonContent, + 'commentType': 12, 'commentId': int.parse(number), }; } catch (e) { diff --git a/lib/pages/html/controller.dart b/lib/pages/html/controller.dart index 539b39197..bdc89cd3e 100644 --- a/lib/pages/html/controller.dart +++ b/lib/pages/html/controller.dart @@ -83,7 +83,9 @@ class HtmlRenderController extends ReplyController { if (dynamicType == 'opus' || dynamicType == 'picture') { res = await HtmlHttp.reqHtml(id, dynamicType); if (res != null) { - type = res['commentType']; + if (res['commentType'] is int) { + type = res['commentType']; + } if (res['favorite'] != null) { favStat.addAll({ 'status': true, diff --git a/lib/pages/msg_feed_top/sys_msg/view.dart b/lib/pages/msg_feed_top/sys_msg/view.dart index 9576d4346..b1f908837 100644 --- a/lib/pages/msg_feed_top/sys_msg/view.dart +++ b/lib/pages/msg_feed_top/sys_msg/view.dart @@ -211,7 +211,7 @@ class _SysMsgPageState extends State { recognizer: TapGestureRecognizer() ..onTap = () { try { - PageUtils.pushDynFromId(match[4]); + PageUtils.pushDynFromId(id: match[4]); } catch (err) { SmartDialog.showToast(err.toString()); } diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index 6a91bc0c4..1d3968f7f 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -176,44 +176,86 @@ class ChatItem extends StatelessWidget { ), ); case MsgType.share_v2: + String? type; + GestureTapCallback onTap; + switch (content['source']) { + // album + case 2: + type = '相簿'; + onTap = () { + PageUtils.pushDynFromId(rid: content['id']); + }; + break; + + // video + case 5: + type = '视频'; + onTap = () async { + dynamic aid = content['id']; + if (aid is String) { + aid = int.tryParse(aid); + } + dynamic bvid = content["bvid"]; + if (aid == null && bvid == null) { + SmartDialog.showToast('null'); + } + bvid ??= IdUtils.av2bv(aid); + SmartDialog.showLoading(); + final int cid = await SearchHttp.ab2c(bvid: bvid); + SmartDialog.dismiss().then( + (e) => PageUtils.toVideoPage( + 'bvid=$bvid&cid=$cid', + arguments: { + 'pic': content['thumb'], + 'heroTag': Utils.makeHeroTag(bvid), + }, + ), + ); + }; + break; + + // article + case 6: + type = '专栏'; + onTap = () { + Get.toNamed( + '/htmlRender', + parameters: { + 'url': 'www.bilibili.com/opus/cv${content['id']}', + 'title': '', + 'id': 'cv${content['id']}', + 'dynamicType': 'read' + }, + ); + }; + break; + + // dynamic + case 11: + type = '动态'; + onTap = () { + PageUtils.pushDynFromId(id: content['id']); + }; + break; + + // pgc + case 16: + onTap = () { + PageUtils.viewBangumi(epId: content['id']); + }; + break; + + default: + onTap = () { + SmartDialog.showToast( + 'unsupported source type: ${content['source']}'); + }; + } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ GestureDetector( - onTap: () async { - if (content['source'] == 16) { - PageUtils.viewBangumi(epId: content['id']); - return; - } - - if (content['source'] == 5) { - dynamic aid = content['id']; - if (aid is String) { - aid = int.tryParse(aid); - } - dynamic bvid = content["bvid"]; - if (aid == null && bvid == null) { - SmartDialog.showToast('null'); - return; - } - bvid ??= IdUtils.av2bv(aid); - SmartDialog.showLoading(); - final int cid = await SearchHttp.ab2c(bvid: bvid); - SmartDialog.dismiss().then( - (e) => PageUtils.toVideoPage( - 'bvid=$bvid&cid=$cid', - arguments: { - 'pic': content['thumb'], - 'heroTag': Utils.makeHeroTag(bvid), - }, - ), - ); - return; - } - - SmartDialog.showToast( - 'unsupported source type: ${content['source']}'); - }, + onTap: onTap, child: NetworkImgLayer( width: 220, height: 220 * 9 / 16, @@ -230,16 +272,31 @@ class ChatItem extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 1), - Text( - content['author'] ?? "", - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor().withOpacity(0.6), - fontSize: 12, + if (content['source'] == 6 && + (content['headline'] as String?)?.isNotEmpty == true) ...[ + const SizedBox(height: 1), + Text( + content['headline'], + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(), + fontWeight: FontWeight.bold, + ), ), - ), + ], + if (content['author'] != null) ...[ + const SizedBox(height: 1), + Text( + '${content['author']}${type != null ? ' · $type' : ''}', + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor().withOpacity(0.6), + fontSize: 12, + ), + ), + ], ], ); case MsgType.archive_card: @@ -451,6 +508,56 @@ class ChatItem extends StatelessWidget { ], ), ); + case MsgType.common_share: + if (content['source'] == '直播') { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: () { + Get.toNamed('/liveRoom?roomid=${content['sourceID']}'); + }, + child: NetworkImgLayer( + width: 220, + height: 220 * 9 / 16, + src: content['cover'], + ), + ), + const SizedBox(height: 6), + Text( + content['title'] ?? "", + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 1), + Text( + '${content['author']} · 直播', + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor().withOpacity(0.6), + fontSize: 12, + ), + ), + ], + ); + } else { + return Text( + content != null && content != '' + ? (content['content'] ?? content.toString()) + : '不支持的消息类型', + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(), + fontWeight: FontWeight.bold, + ), + ); + } default: return Text( content != null && content != '' diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index f0887f2b2..a1532646d 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:PiliPlus/http/dynamics.dart'; import 'package:PiliPlus/models/common/reply_type.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/page_utils.dart'; @@ -437,22 +436,7 @@ class PiliScheme { case 'album': String? rid = uriDigitRegExp.firstMatch(path)?.group(1); if (rid != null) { - SmartDialog.showLoading(); - dynamic res = await DynamicsHttp.dynamicDetail(rid: rid, type: 2); - SmartDialog.dismiss(); - if (res['status']) { - PageUtils.toDupNamed( - '/dynamicDetail', - arguments: { - 'item': res['data'], - 'floor': 1, - 'action': 'detail' - }, - off: off, - ); - } else { - SmartDialog.showToast(res['msg']); - } + PageUtils.pushDynFromId(rid: rid, off: off); return true; } return false; @@ -708,7 +692,7 @@ class PiliScheme { static Future _onPushDynDetail(path, off) async { String? id = uriDigitRegExp.firstMatch(path)?.group(1); if (id != null) { - PageUtils.pushDynFromId(id, off: off); + PageUtils.pushDynFromId(id: id, off: off); return true; } return false; diff --git a/lib/utils/page_utils.dart b/lib/utils/page_utils.dart index 45b48636f..9507751a5 100644 --- a/lib/utils/page_utils.dart +++ b/lib/utils/page_utils.dart @@ -271,9 +271,13 @@ class PageUtils { ); } - static Future pushDynFromId(id, {bool off = false}) async { + static Future pushDynFromId({id, rid, bool off = false}) async { SmartDialog.showLoading(); - dynamic res = await DynamicsHttp.dynamicDetail(id: id); + dynamic res = await DynamicsHttp.dynamicDetail( + id: id, + rid: rid, + type: rid != null ? 2 : null, + ); SmartDialog.dismiss(); if (res['status']) { DynamicItemModel data = res['data'];