mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-02 15:20:18 +08:00
feat: more subtitle
This commit is contained in:
@@ -21,4 +21,12 @@ abstract final class DmGrpc {
|
|||||||
isolate: true,
|
isolate: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<LoadingState<DmViewReply>> dmView(int aid, int cid) {
|
||||||
|
return GrpcReq.request(
|
||||||
|
GrpcUrl.dmView,
|
||||||
|
DmViewReq(pid: Int64(aid), oid: Int64(cid), type: 1),
|
||||||
|
DmViewReply.fromBuffer,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ abstract final class GrpcUrl {
|
|||||||
|
|
||||||
// danmaku
|
// danmaku
|
||||||
static const dmSegMobile = '/bilibili.community.service.dm.v1.DM/DmSegMobile';
|
static const dmSegMobile = '/bilibili.community.service.dm.v1.DM/DmSegMobile';
|
||||||
|
static const dmView = '/bilibili.community.service.dm.v1.DM/DmView';
|
||||||
|
|
||||||
// reply
|
// reply
|
||||||
static const reply = '/bilibili.main.community.reply.v1.Reply';
|
static const reply = '/bilibili.main.community.reply.v1.Reply';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
class Subtitle {
|
class Subtitle implements Comparable<Subtitle> {
|
||||||
late String lan;
|
late String lan;
|
||||||
String? lanDoc;
|
String? lanDoc;
|
||||||
String? subtitleUrl;
|
String? subtitleUrl;
|
||||||
@@ -8,6 +8,8 @@ class Subtitle {
|
|||||||
Subtitle({
|
Subtitle({
|
||||||
required this.lan,
|
required this.lan,
|
||||||
this.lanDoc,
|
this.lanDoc,
|
||||||
|
this.subtitleUrl,
|
||||||
|
this.isAi = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Subtitle.fromJson(Map<String, dynamic> json) {
|
Subtitle.fromJson(Map<String, dynamic> json) {
|
||||||
@@ -17,4 +19,13 @@ class Subtitle {
|
|||||||
subtitleUrl = json["subtitle_url"];
|
subtitleUrl = json["subtitle_url"];
|
||||||
subtitleUrlV2 = json["subtitle_url_v2"];
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,6 @@ class SubtitleInfo {
|
|||||||
(json['subtitles'] as List<dynamic>?)
|
(json['subtitles'] as List<dynamic>?)
|
||||||
?.map((e) => Subtitle.fromJson(e as Map<String, dynamic>))
|
?.map((e) => Subtitle.fromJson(e as Map<String, dynamic>))
|
||||||
.toList()
|
.toList()
|
||||||
?..sort((a, b) {
|
?..sort(),
|
||||||
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;
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/common/widgets/progress_bar/segment_progress_bar.dart';
|
||||||
import 'package:PiliPlus/grpc/bilibili/app/listener/v1.pbenum.dart'
|
import 'package:PiliPlus/grpc/bilibili/app/listener/v1.pbenum.dart'
|
||||||
show PlaylistSource;
|
show PlaylistSource;
|
||||||
|
import 'package:PiliPlus/grpc/dm.dart';
|
||||||
import 'package:PiliPlus/http/fav.dart';
|
import 'package:PiliPlus/http/fav.dart';
|
||||||
import 'package:PiliPlus/http/init.dart';
|
import 'package:PiliPlus/http/init.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.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)) {
|
if (response.subtitle?.subtitles case final sub? when (sub.isNotEmpty)) {
|
||||||
subtitles.value = sub;
|
_setSubtitle(sub);
|
||||||
final idx = switch (Pref.subtitlePreferenceV2) {
|
} else if (!Accounts.main.isLogin) {
|
||||||
.off => 0,
|
final res = await DmGrpc.dmView(aid, cid.value);
|
||||||
.on => 1,
|
if (res case Success(:final response)) {
|
||||||
.withoutAi => sub.first.lan.startsWith('ai') ? 0 : 1,
|
if (response.hasSubtitle() &&
|
||||||
.auto =>
|
response.subtitle.subtitles.isNotEmpty) {
|
||||||
!sub.first.lan.startsWith('ai') ||
|
_setSubtitle(
|
||||||
(PlatformUtils.isMobile &&
|
response.subtitle.subtitles
|
||||||
(await FlutterVolumeController.getVolume() ?? 0.0) <=
|
.map(
|
||||||
0.0)
|
(i) => Subtitle(
|
||||||
? 1
|
lan: i.lan,
|
||||||
: 0,
|
lanDoc: i.lanDoc,
|
||||||
};
|
subtitleUrl: i.subtitleUrl.replaceFirst(
|
||||||
await setSubtitle(idx);
|
RegExp('^https?:'),
|
||||||
|
'',
|
||||||
|
),
|
||||||
|
isAi: i.type == .AI,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList()
|
||||||
|
..sort(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.toast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _setSubtitle(List<Subtitle> 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) {
|
void updateMediaListHistory(int aid) {
|
||||||
if (args['sortField'] != null) {
|
if (args['sortField'] != null) {
|
||||||
VideoHttp.medialistHistory(
|
VideoHttp.medialistHistory(
|
||||||
|
|||||||
Reference in New Issue
Block a user