diff --git a/lib/grpc/dm.dart b/lib/grpc/dm.dart index 5c5c1f447..74ffb7bdc 100644 --- a/lib/grpc/dm.dart +++ b/lib/grpc/dm.dart @@ -21,4 +21,12 @@ abstract final class DmGrpc { isolate: true, ); } + + static Future> dmView(int aid, int cid) { + return GrpcReq.request( + GrpcUrl.dmView, + DmViewReq(pid: Int64(aid), oid: Int64(cid), type: 1), + DmViewReply.fromBuffer, + ); + } } diff --git a/lib/grpc/url.dart b/lib/grpc/url.dart index 6ace7c1cc..78238ef02 100644 --- a/lib/grpc/url.dart +++ b/lib/grpc/url.dart @@ -14,6 +14,7 @@ abstract final class GrpcUrl { // danmaku static const dmSegMobile = '/bilibili.community.service.dm.v1.DM/DmSegMobile'; + static const dmView = '/bilibili.community.service.dm.v1.DM/DmView'; // reply static const reply = '/bilibili.main.community.reply.v1.Reply'; diff --git a/lib/models_new/video/video_play_info/subtitle.dart b/lib/models_new/video/video_play_info/subtitle.dart index 797adb963..f3bf28306 100644 --- a/lib/models_new/video/video_play_info/subtitle.dart +++ b/lib/models_new/video/video_play_info/subtitle.dart @@ -1,4 +1,4 @@ -class Subtitle { +class Subtitle implements Comparable { late String lan; String? lanDoc; String? subtitleUrl; @@ -8,6 +8,8 @@ class Subtitle { Subtitle({ required this.lan, this.lanDoc, + this.subtitleUrl, + this.isAi = false, }); Subtitle.fromJson(Map json) { @@ -17,4 +19,13 @@ class Subtitle { subtitleUrl = json["subtitle_url"]; subtitleUrlV2 = json["subtitle_url_v2"]; } + + @override + int compareTo(Subtitle other) { + final thisHasZh = lan.contains('zh'); + final otherHasZh = other.lan.contains('zh'); + if (thisHasZh != otherHasZh) return thisHasZh ? -1 : 1; + if (isAi != other.isAi) return isAi ? 1 : -1; + return 0; + } } diff --git a/lib/models_new/video/video_play_info/subtitle_info.dart b/lib/models_new/video/video_play_info/subtitle_info.dart index d559c1697..33e886186 100644 --- a/lib/models_new/video/video_play_info/subtitle_info.dart +++ b/lib/models_new/video/video_play_info/subtitle_info.dart @@ -14,12 +14,6 @@ class SubtitleInfo { (json['subtitles'] as List?) ?.map((e) => Subtitle.fromJson(e as Map)) .toList() - ?..sort((a, b) { - final aHasZh = a.lan.contains('zh'); - final bHasZh = b.lan.contains('zh'); - if (aHasZh != bHasZh) return aHasZh ? -1 : 1; - if (a.isAi != b.isAi) return a.isAi ? 1 : -1; - return 0; - }), + ?..sort(), ); } diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index 3bf31dc6e..e3e3a5611 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/common/widgets/pair.dart'; import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart'; import 'package:PiliPlus/grpc/bilibili/app/listener/v1.pbenum.dart' show PlaylistSource; +import 'package:PiliPlus/grpc/dm.dart'; import 'package:PiliPlus/http/fav.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/loading_state.dart'; @@ -1178,24 +1179,52 @@ class VideoDetailController extends GetxController } if (response.subtitle?.subtitles case final sub? when (sub.isNotEmpty)) { - subtitles.value = sub; - final idx = switch (Pref.subtitlePreferenceV2) { - .off => 0, - .on => 1, - .withoutAi => sub.first.lan.startsWith('ai') ? 0 : 1, - .auto => - !sub.first.lan.startsWith('ai') || - (PlatformUtils.isMobile && - (await FlutterVolumeController.getVolume() ?? 0.0) <= - 0.0) - ? 1 - : 0, - }; - await setSubtitle(idx); + _setSubtitle(sub); + } else if (!Accounts.main.isLogin) { + final res = await DmGrpc.dmView(aid, cid.value); + if (res case Success(:final response)) { + if (response.hasSubtitle() && + response.subtitle.subtitles.isNotEmpty) { + _setSubtitle( + response.subtitle.subtitles + .map( + (i) => Subtitle( + lan: i.lan, + lanDoc: i.lanDoc, + subtitleUrl: i.subtitleUrl.replaceFirst( + RegExp('^https?:'), + '', + ), + isAi: i.type == .AI, + ), + ) + .toList() + ..sort(), + ); + } + } else { + res.toast(); + } } } } + Future _setSubtitle(List sub) async { + subtitles.value = sub; + final idx = switch (Pref.subtitlePreferenceV2) { + .off => 0, + .on => 1, + .withoutAi => sub.first.lan.startsWith('ai') ? 0 : 1, + .auto => + !sub.first.lan.startsWith('ai') || + (PlatformUtils.isMobile && + (await FlutterVolumeController.getVolume() ?? 0.0) <= 0.0) + ? 1 + : 0, + }; + await setSubtitle(idx); + } + void updateMediaListHistory(int aid) { if (args['sortField'] != null) { VideoHttp.medialistHistory(