feat: merge danmaku

Closes #150

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-01-13 14:20:16 +08:00
parent 9bf9f8595b
commit b77d28e285
5 changed files with 35 additions and 2 deletions

View File

@@ -1,4 +1,5 @@
import 'package:PiliPlus/grpc/dm/v1/dm.pb.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:dio/dio.dart';
import 'index.dart';
@@ -7,6 +8,7 @@ class DanmakaHttp {
static Future queryDanmaku({
required int cid,
required int segmentIndex,
required bool mergeDanmaku,
}) async {
// 构建参数对象
Map<String, int> params = {
@@ -22,7 +24,11 @@ class DanmakaHttp {
if (response.statusCode != 200 || response.data == null) {
return DmSegMobileReply();
}
return DmSegMobileReply.fromBuffer(response.data);
DmSegMobileReply data = DmSegMobileReply.fromBuffer(response.data);
if (mergeDanmaku) {
data.elems.unique((item) => item.content);
}
return data;
}
static Future shootDanmaku({

View File

@@ -1,6 +1,7 @@
import 'package:PiliPlus/grpc/dm/v1/dm.pb.dart';
import 'package:PiliPlus/http/danmaku.dart';
import 'package:PiliPlus/plugin/pl_player/controller.dart';
import 'package:PiliPlus/utils/storage.dart';
class PlDanmakuController {
PlDanmakuController(
@@ -18,6 +19,8 @@ class PlDanmakuController {
static int segmentLength = 60 * 6 * 1000;
late final mergeDanmaku = GStorage.mergeDanmaku;
void initiate(int videoDuration, int progress) {
if (videoDuration <= 0) {
return;
@@ -45,7 +48,10 @@ class PlDanmakuController {
assert(requestedSeg[segmentIndex] == false);
requestedSeg[segmentIndex] = true;
final DmSegMobileReply result = await DanmakaHttp.queryDanmaku(
cid: cid, segmentIndex: segmentIndex + 1);
cid: cid,
segmentIndex: segmentIndex + 1,
mergeDanmaku: mergeDanmaku,
);
if (result.elems.isNotEmpty) {
for (var element in result.elems) {
int pos = element.progress ~/ 100; //每0.1秒存储一次

View File

@@ -1754,6 +1754,14 @@ List<SettingsModel> get extraSettings => [
setKey: SettingBoxKey.showVipDanmaku,
defaultVal: true,
),
SettingsModel(
settingsType: SettingsType.sw1tch,
title: '合并弹幕',
subtitle: '合并一段时间内获取到的相同弹幕',
leading: Icon(Icons.merge),
setKey: SettingBoxKey.mergeDanmaku,
defaultVal: false,
),
SettingsModel(
settingsType: SettingsType.sw1tch,
enableFeedback: true,

View File

@@ -88,3 +88,12 @@ extension BuildContextExt on BuildContext {
);
}
}
extension Unique<E, Id> on List<E> {
List<E> unique([Id Function(E element)? id, bool inplace = true]) {
final ids = <dynamic>{};
var list = inplace ? this : List<E>.from(this);
list.retainWhere((x) => ids.add(id != null ? id(x) : x as Id));
return list;
}
}

View File

@@ -339,6 +339,9 @@ class GStorage {
static bool get showVipDanmaku =>
GStorage.setting.get(SettingBoxKey.showVipDanmaku, defaultValue: true);
static bool get mergeDanmaku =>
GStorage.setting.get(SettingBoxKey.mergeDanmaku, defaultValue: false);
static List<double> get dynamicDetailRatio => List<double>.from(setting
.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]));
@@ -558,6 +561,7 @@ class SettingBoxKey {
refreshDragPercentage = 'refreshDragPercentage',
refreshDisplacement = 'refreshDisplacement',
showVipDanmaku = 'showVipDanmaku',
mergeDanmaku = 'mergeDanmaku',
// Sponsor Block
enableSponsorBlock = 'enableSponsorBlock',