mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-21 08:38:37 +00:00
feat: merge danmaku
Closes #150 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import 'package:PiliPlus/grpc/dm/v1/dm.pb.dart';
|
import 'package:PiliPlus/grpc/dm/v1/dm.pb.dart';
|
||||||
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'index.dart';
|
import 'index.dart';
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ class DanmakaHttp {
|
|||||||
static Future queryDanmaku({
|
static Future queryDanmaku({
|
||||||
required int cid,
|
required int cid,
|
||||||
required int segmentIndex,
|
required int segmentIndex,
|
||||||
|
required bool mergeDanmaku,
|
||||||
}) async {
|
}) async {
|
||||||
// 构建参数对象
|
// 构建参数对象
|
||||||
Map<String, int> params = {
|
Map<String, int> params = {
|
||||||
@@ -22,7 +24,11 @@ class DanmakaHttp {
|
|||||||
if (response.statusCode != 200 || response.data == null) {
|
if (response.statusCode != 200 || response.data == null) {
|
||||||
return DmSegMobileReply();
|
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({
|
static Future shootDanmaku({
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:PiliPlus/grpc/dm/v1/dm.pb.dart';
|
import 'package:PiliPlus/grpc/dm/v1/dm.pb.dart';
|
||||||
import 'package:PiliPlus/http/danmaku.dart';
|
import 'package:PiliPlus/http/danmaku.dart';
|
||||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||||
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
|
|
||||||
class PlDanmakuController {
|
class PlDanmakuController {
|
||||||
PlDanmakuController(
|
PlDanmakuController(
|
||||||
@@ -18,6 +19,8 @@ class PlDanmakuController {
|
|||||||
|
|
||||||
static int segmentLength = 60 * 6 * 1000;
|
static int segmentLength = 60 * 6 * 1000;
|
||||||
|
|
||||||
|
late final mergeDanmaku = GStorage.mergeDanmaku;
|
||||||
|
|
||||||
void initiate(int videoDuration, int progress) {
|
void initiate(int videoDuration, int progress) {
|
||||||
if (videoDuration <= 0) {
|
if (videoDuration <= 0) {
|
||||||
return;
|
return;
|
||||||
@@ -45,7 +48,10 @@ class PlDanmakuController {
|
|||||||
assert(requestedSeg[segmentIndex] == false);
|
assert(requestedSeg[segmentIndex] == false);
|
||||||
requestedSeg[segmentIndex] = true;
|
requestedSeg[segmentIndex] = true;
|
||||||
final DmSegMobileReply result = await DanmakaHttp.queryDanmaku(
|
final DmSegMobileReply result = await DanmakaHttp.queryDanmaku(
|
||||||
cid: cid, segmentIndex: segmentIndex + 1);
|
cid: cid,
|
||||||
|
segmentIndex: segmentIndex + 1,
|
||||||
|
mergeDanmaku: mergeDanmaku,
|
||||||
|
);
|
||||||
if (result.elems.isNotEmpty) {
|
if (result.elems.isNotEmpty) {
|
||||||
for (var element in result.elems) {
|
for (var element in result.elems) {
|
||||||
int pos = element.progress ~/ 100; //每0.1秒存储一次
|
int pos = element.progress ~/ 100; //每0.1秒存储一次
|
||||||
|
|||||||
@@ -1754,6 +1754,14 @@ List<SettingsModel> get extraSettings => [
|
|||||||
setKey: SettingBoxKey.showVipDanmaku,
|
setKey: SettingBoxKey.showVipDanmaku,
|
||||||
defaultVal: true,
|
defaultVal: true,
|
||||||
),
|
),
|
||||||
|
SettingsModel(
|
||||||
|
settingsType: SettingsType.sw1tch,
|
||||||
|
title: '合并弹幕',
|
||||||
|
subtitle: '合并一段时间内获取到的相同弹幕',
|
||||||
|
leading: Icon(Icons.merge),
|
||||||
|
setKey: SettingBoxKey.mergeDanmaku,
|
||||||
|
defaultVal: false,
|
||||||
|
),
|
||||||
SettingsModel(
|
SettingsModel(
|
||||||
settingsType: SettingsType.sw1tch,
|
settingsType: SettingsType.sw1tch,
|
||||||
enableFeedback: true,
|
enableFeedback: true,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -339,6 +339,9 @@ class GStorage {
|
|||||||
static bool get showVipDanmaku =>
|
static bool get showVipDanmaku =>
|
||||||
GStorage.setting.get(SettingBoxKey.showVipDanmaku, defaultValue: true);
|
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
|
static List<double> get dynamicDetailRatio => List<double>.from(setting
|
||||||
.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]));
|
.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]));
|
||||||
|
|
||||||
@@ -558,6 +561,7 @@ class SettingBoxKey {
|
|||||||
refreshDragPercentage = 'refreshDragPercentage',
|
refreshDragPercentage = 'refreshDragPercentage',
|
||||||
refreshDisplacement = 'refreshDisplacement',
|
refreshDisplacement = 'refreshDisplacement',
|
||||||
showVipDanmaku = 'showVipDanmaku',
|
showVipDanmaku = 'showVipDanmaku',
|
||||||
|
mergeDanmaku = 'mergeDanmaku',
|
||||||
|
|
||||||
// Sponsor Block
|
// Sponsor Block
|
||||||
enableSponsorBlock = 'enableSponsorBlock',
|
enableSponsorBlock = 'enableSponsorBlock',
|
||||||
|
|||||||
Reference in New Issue
Block a user