mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-23 10:36:24 +08:00
feat: danmaku api (#1530)
This commit is contained in:
committed by
GitHub
parent
88d207cc24
commit
e5f0742bf6
@@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class CustomSliverPersistentHeaderDelegate
|
||||
extends SliverPersistentHeaderDelegate {
|
||||
CustomSliverPersistentHeaderDelegate({
|
||||
const CustomSliverPersistentHeaderDelegate({
|
||||
required this.child,
|
||||
required this.bgColor,
|
||||
double extent = 45,
|
||||
|
||||
@@ -231,4 +231,34 @@ class ReportOptions {
|
||||
0: '其他',
|
||||
},
|
||||
};
|
||||
|
||||
static Map<String, Map<int, String>> get danmakuReport => const {
|
||||
'': {
|
||||
1: '违法违禁',
|
||||
2: '色情低俗',
|
||||
3: '赌博诈骗',
|
||||
4: '人身攻击',
|
||||
5: '侵犯隐私',
|
||||
6: '垃圾广告',
|
||||
7: '引战',
|
||||
8: '剧透',
|
||||
9: '恶意刷屏',
|
||||
10: '视频无关',
|
||||
12: '青少年不良信息',
|
||||
13: '违法信息外链',
|
||||
0: '其它', // 11
|
||||
},
|
||||
};
|
||||
|
||||
static Map<String, Map<int, String>> get liveDanmakuReport => const {
|
||||
'': {
|
||||
1: '违法违规',
|
||||
2: '低俗色情',
|
||||
3: '垃圾广告',
|
||||
4: '辱骂引战',
|
||||
5: '政治敏感',
|
||||
6: '青少年不良信息',
|
||||
7: '其他 ', // avoid show form
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -955,4 +955,15 @@ class Api {
|
||||
static const String popularPrecious = '/x/web-interface/popular/precious';
|
||||
|
||||
static const String userRealName = '/x/member/app/up/realname';
|
||||
|
||||
static const String liveDmReport =
|
||||
'${HttpString.liveBaseUrl}/xlive/web-ucenter/v1/dMReport/Report';
|
||||
|
||||
static const String danmakuLike = '/x/v2/dm/thumbup/add';
|
||||
|
||||
static const String danmakuReport = '/x/dm/report/add';
|
||||
|
||||
static const String danmakuRecall = '/x/dm/recall';
|
||||
|
||||
static const String danmakuEditState = '/x/v2/dm/edit/state';
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import 'package:PiliPlus/http/api.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class DanmakuHttp {
|
||||
abstract final class DanmakuHttp {
|
||||
static Future shootDanmaku({
|
||||
int type = 1, //弹幕类选择(1:视频弹幕 2:漫画弹幕)
|
||||
required int oid, // 视频cid
|
||||
@@ -27,23 +28,23 @@ class DanmakuHttp {
|
||||
// assert(aid != null || bvid != null);
|
||||
// assert(csrf != null || access_key != null);
|
||||
// 构建参数对象
|
||||
var data = <String, dynamic>{
|
||||
var data = <String, Object>{
|
||||
'type': type,
|
||||
'oid': oid,
|
||||
'msg': msg,
|
||||
'mode': mode,
|
||||
//'aid': aid,
|
||||
'bvid': bvid,
|
||||
'progress': progress,
|
||||
'color': colorful ? 16777215 : color,
|
||||
'fontsize': fontsize,
|
||||
'pool': pool,
|
||||
'progress': ?progress,
|
||||
'color': ?colorful ? 16777215 : color,
|
||||
'fontsize': ?fontsize,
|
||||
'pool': ?pool,
|
||||
'rnd': DateTime.now().microsecondsSinceEpoch,
|
||||
'colorful': colorful ? 60001 : null,
|
||||
'checkbox_type': checkboxType,
|
||||
'colorful': ?colorful ? 60001 : null,
|
||||
'checkbox_type': ?checkboxType,
|
||||
'csrf': Accounts.main.csrf,
|
||||
// 'access_key': access_key,
|
||||
}..removeWhere((key, value) => value == null);
|
||||
};
|
||||
|
||||
var response = await Request().post(
|
||||
Api.shootDanmaku,
|
||||
@@ -68,4 +69,132 @@ class DanmakuHttp {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static Future<LoadingState<Null>> danmakuLike({
|
||||
required bool isLike,
|
||||
required int cid,
|
||||
required int id,
|
||||
}) async {
|
||||
final data = {
|
||||
'op': isLike ? 2 : 1,
|
||||
'dmid': id,
|
||||
'oid': cid,
|
||||
'platform': 'web_player',
|
||||
'polaris_app_id': 100,
|
||||
'polaris_platform': 5,
|
||||
'spmid': '333.788.0.0',
|
||||
'from_spmid': '333.788.0.0',
|
||||
'statistics': '{"appId":100,"platform":5,"abtest":"","version":""}',
|
||||
'csrf': Accounts.main.csrf,
|
||||
};
|
||||
final res = await Request().post(
|
||||
Api.danmakuLike,
|
||||
data: data,
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return const Success(null);
|
||||
} else {
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> danmakuReport({
|
||||
required int reason,
|
||||
required int cid,
|
||||
required int id,
|
||||
bool block = false,
|
||||
String? content,
|
||||
}) async {
|
||||
final data = {
|
||||
'cid': cid,
|
||||
'dmid': id,
|
||||
'reason': reason,
|
||||
'block': block,
|
||||
'originCid': cid,
|
||||
'content': ?content,
|
||||
'polaris_app_id': 100,
|
||||
'polaris_platform': 5,
|
||||
'spmid': '333.788.0.0',
|
||||
'from_spmid': '333.788.0.0',
|
||||
'statistics': '{"appId":100,"platform":5,"abtest":"","version":""}',
|
||||
'csrf': Accounts.main.csrf,
|
||||
};
|
||||
final res = await Request().post(
|
||||
Api.danmakuReport,
|
||||
data: data,
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return {
|
||||
'status': true,
|
||||
'data': res.data['data']['block'],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
|
||||
/// {
|
||||
/// 0: "举报已提交",
|
||||
/// "-1": "举报失败,请先激活账号。",
|
||||
/// "-2": "举报失败,系统拒绝受理您的举报请求。",
|
||||
/// "-3": "举报失败,您已经被禁言。",
|
||||
/// "-4": "您的操作过于频繁,请稍后再试。",
|
||||
/// "-5": "您已经举报过这条弹幕了。",
|
||||
/// "-6": "举报失败,系统错误。"
|
||||
/// }
|
||||
}
|
||||
}
|
||||
|
||||
static Future<LoadingState<String?>> danmakuRecall({
|
||||
required int cid,
|
||||
required int id,
|
||||
}) async {
|
||||
final data = {
|
||||
'dmid': id,
|
||||
'cid': cid,
|
||||
'type': 1,
|
||||
'csrf': Accounts.main.csrf,
|
||||
};
|
||||
final res = await Request().post(
|
||||
Api.danmakuRecall,
|
||||
data: data,
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return Success(res.data['message']);
|
||||
} else {
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<LoadingState<String?>> danmakuEditState({
|
||||
required int oid,
|
||||
required Iterable<int> ids,
|
||||
required int state,
|
||||
}) async {
|
||||
/// 0: 取消删除
|
||||
/// 1:删除弹幕
|
||||
/// 2:弹幕保护
|
||||
/// 3:取消保护
|
||||
final data = {
|
||||
'dmids': ids.join(','),
|
||||
'oid': oid,
|
||||
'state': state,
|
||||
'type': 1,
|
||||
'csrf': Accounts.main.csrf,
|
||||
};
|
||||
final res = await Request().post(
|
||||
Api.danmakuRecall,
|
||||
data: data,
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return Success(res.data['message']);
|
||||
} else {
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,4 +666,41 @@ abstract final class LiveHttp {
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<LoadingState<Null>> liveDmReport({
|
||||
required Object roomId,
|
||||
required int mid,
|
||||
required String msg,
|
||||
required String reason,
|
||||
required int reasonId,
|
||||
required String id,
|
||||
}) async {
|
||||
final csrf = Accounts.main.csrf;
|
||||
final data = {
|
||||
'id': 0,
|
||||
'roomid': roomId,
|
||||
'tuid': mid,
|
||||
'msg': msg,
|
||||
'reason': reason,
|
||||
'sign': '',
|
||||
'reason_id': reasonId,
|
||||
'token': '',
|
||||
'dm_type': '0',
|
||||
'id_str': id,
|
||||
'csrf_token': csrf,
|
||||
'csrf': csrf,
|
||||
'visit_id': '',
|
||||
'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
};
|
||||
final res = await Request().post(
|
||||
Api.liveDmReport,
|
||||
data: data,
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return const Success(null); // {"id": num}
|
||||
} else {
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
lib/pages/danmaku/dnamaku_model.dart
Normal file
27
lib/pages/danmaku/dnamaku_model.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
sealed class DanmakuExtra {
|
||||
String get mid;
|
||||
Object get id;
|
||||
|
||||
const DanmakuExtra();
|
||||
}
|
||||
|
||||
class VideoDanmaku extends DanmakuExtra {
|
||||
@override
|
||||
final int id;
|
||||
@override
|
||||
final String mid;
|
||||
|
||||
bool isLike;
|
||||
|
||||
VideoDanmaku({required this.id, required this.mid, this.isLike = false});
|
||||
}
|
||||
|
||||
class LiveDanmaku extends DanmakuExtra {
|
||||
@override
|
||||
final String id;
|
||||
@override
|
||||
final String mid;
|
||||
final String uname;
|
||||
|
||||
const LiveDanmaku({required this.id, required this.mid, required this.uname});
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:PiliPlus/grpc/bilibili/community/service/dm/v1.pb.dart';
|
||||
import 'package:PiliPlus/pages/danmaku/controller.dart';
|
||||
import 'package:PiliPlus/pages/danmaku/dnamaku_model.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/play_status.dart';
|
||||
import 'package:PiliPlus/utils/danmaku_utils.dart';
|
||||
@@ -32,7 +33,7 @@ class _PlDanmakuState extends State<PlDanmaku> {
|
||||
PlPlayerController get playerController => widget.playerController;
|
||||
|
||||
late PlDanmakuController _plDanmakuController;
|
||||
DanmakuController? _controller;
|
||||
DanmakuController<DanmakuExtra>? _controller;
|
||||
int latestAddedPosition = -1;
|
||||
|
||||
@override
|
||||
@@ -130,6 +131,7 @@ class _PlDanmakuState extends State<PlDanmaku> {
|
||||
e.colorful == DmColorfulType.VipGradualColor,
|
||||
count: e.hasCount() ? e.count : null,
|
||||
selfSend: e.isSelf,
|
||||
extra: VideoDanmaku(id: e.id.toInt(), mid: e.midHash),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -154,8 +156,8 @@ class _PlDanmakuState extends State<PlDanmaku> {
|
||||
? playerController.danmakuOpacity.value
|
||||
: 0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: DanmakuScreen(
|
||||
createdController: (DanmakuController e) {
|
||||
child: DanmakuScreen<DanmakuExtra>(
|
||||
createdController: (e) {
|
||||
playerController.danmakuController = _controller = e;
|
||||
},
|
||||
option: DanmakuOption(
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:PiliPlus/models_new/live/live_dm_info/data.dart';
|
||||
import 'package:PiliPlus/models_new/live/live_room_info_h5/data.dart';
|
||||
import 'package:PiliPlus/models_new/live/live_room_play_info/codec.dart';
|
||||
import 'package:PiliPlus/models_new/live/live_superchat/item.dart';
|
||||
import 'package:PiliPlus/pages/danmaku/dnamaku_model.dart';
|
||||
import 'package:PiliPlus/pages/live_room/send_danmaku/view.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/data_source.dart';
|
||||
@@ -36,7 +37,7 @@ class LiveRoomController extends GetxController {
|
||||
final String heroTag;
|
||||
|
||||
int roomId = Get.arguments;
|
||||
DanmakuController? danmakuController;
|
||||
DanmakuController<DanmakuExtra>? danmakuController;
|
||||
PlPlayerController plPlayerController = PlPlayerController.getInstance(
|
||||
isLive: true,
|
||||
);
|
||||
@@ -340,7 +341,9 @@ class LiveRoomController extends GetxController {
|
||||
final info = obj['info'];
|
||||
final first = info[0];
|
||||
final content = first[15];
|
||||
final extra = jsonDecode(content['extra']);
|
||||
final Map<String, dynamic> extra = jsonDecode(
|
||||
content['extra'],
|
||||
);
|
||||
final user = content['user'];
|
||||
final uid = user['uid'];
|
||||
BaseEmote? uemote;
|
||||
@@ -368,6 +371,11 @@ class LiveRoomController extends GetxController {
|
||||
: DmUtils.decimalToColor(extra['color']),
|
||||
type: DmUtils.getPosition(extra['mode']),
|
||||
selfSend: extra['send_from_me'] ?? false,
|
||||
extra: LiveDanmaku(
|
||||
id: extra['id_str'],
|
||||
mid: uid,
|
||||
uname: user['base']['name'],
|
||||
),
|
||||
),
|
||||
);
|
||||
if (!disableAutoScroll.value) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:PiliPlus/common/widgets/scroll_physics.dart';
|
||||
import 'package:PiliPlus/models/common/image_type.dart';
|
||||
import 'package:PiliPlus/models_new/live/live_room_info_h5/data.dart';
|
||||
import 'package:PiliPlus/models_new/live/live_superchat/item.dart';
|
||||
import 'package:PiliPlus/pages/danmaku/dnamaku_model.dart';
|
||||
import 'package:PiliPlus/pages/live_room/controller.dart';
|
||||
import 'package:PiliPlus/pages/live_room/superchat/superchat_card.dart';
|
||||
import 'package:PiliPlus/pages/live_room/superchat/superchat_panel.dart';
|
||||
@@ -1039,8 +1040,8 @@ class _LiveDanmakuState extends State<LiveDanmaku> {
|
||||
? plPlayerController.danmakuOpacity.value
|
||||
: 0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: DanmakuScreen(
|
||||
createdController: (DanmakuController e) {
|
||||
child: DanmakuScreen<DanmakuExtra>(
|
||||
createdController: (e) {
|
||||
widget.liveRoomController.danmakuController =
|
||||
plPlayerController.danmakuController = e;
|
||||
},
|
||||
|
||||
@@ -6,7 +6,9 @@ import 'package:PiliPlus/http/danmaku.dart';
|
||||
import 'package:PiliPlus/main.dart';
|
||||
import 'package:PiliPlus/models/common/publish_panel_type.dart';
|
||||
import 'package:PiliPlus/pages/common/publish/common_text_pub_page.dart';
|
||||
import 'package:PiliPlus/pages/danmaku/dnamaku_model.dart';
|
||||
import 'package:PiliPlus/pages/setting/slide_color_picker.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:canvas_danmaku/models/danmaku_content_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -20,7 +22,7 @@ class SendDanmakuPanel extends CommonTextPubPage {
|
||||
final dynamic bvid;
|
||||
final dynamic progress;
|
||||
|
||||
final ValueChanged<DanmakuContentItem> callback;
|
||||
final ValueChanged<DanmakuContentItem<DanmakuExtra>> callback;
|
||||
final bool darkVideoPage;
|
||||
|
||||
// config
|
||||
@@ -473,6 +475,10 @@ class _SendDanmakuPanelState extends CommonTextPubPageState<SendDanmakuPanel> {
|
||||
},
|
||||
selfSend: true,
|
||||
isColorful: isColorful,
|
||||
extra: VideoDanmaku(
|
||||
id: res['dmid'],
|
||||
mid: PlPlayerController.instance!.midHash,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,11 @@ import 'dart:typed_data';
|
||||
|
||||
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
||||
import 'package:PiliPlus/common/widgets/custom_icon.dart';
|
||||
import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart';
|
||||
import 'package:PiliPlus/common/widgets/dialog/report.dart';
|
||||
import 'package:PiliPlus/common/widgets/marquee.dart';
|
||||
import 'package:PiliPlus/http/danmaku.dart';
|
||||
import 'package:PiliPlus/http/danmaku_block.dart';
|
||||
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
||||
import 'package:PiliPlus/models/common/video/audio_quality.dart';
|
||||
import 'package:PiliPlus/models/common/video/cdn_type.dart';
|
||||
@@ -13,6 +17,7 @@ import 'package:PiliPlus/models/common/video/video_decode_type.dart';
|
||||
import 'package:PiliPlus/models/common/video/video_quality.dart';
|
||||
import 'package:PiliPlus/models/video/play/url.dart';
|
||||
import 'package:PiliPlus/pages/common/common_intro_controller.dart';
|
||||
import 'package:PiliPlus/pages/danmaku/dnamaku_model.dart';
|
||||
import 'package:PiliPlus/pages/setting/widgets/select_dialog.dart';
|
||||
import 'package:PiliPlus/pages/setting/widgets/switch_item.dart';
|
||||
import 'package:PiliPlus/pages/video/controller.dart';
|
||||
@@ -407,6 +412,15 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
style: subTitleStyle,
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
Get.back();
|
||||
showDanmakuPool();
|
||||
},
|
||||
leading: const Icon(CustomIcons.dm_on, size: 20),
|
||||
title: const Text('弹幕列表', style: titleStyle),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
@@ -1337,7 +1351,7 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
int danmakuFontWeight = plPlayerController.danmakuFontWeight;
|
||||
bool massiveMode = plPlayerController.massiveMode;
|
||||
|
||||
final DanmakuController? danmakuController =
|
||||
final DanmakuController<DanmakuExtra>? danmakuController =
|
||||
plPlayerController.danmakuController;
|
||||
|
||||
showBottomSheet(
|
||||
@@ -1843,6 +1857,146 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
);
|
||||
}
|
||||
|
||||
void showDanmakuPool() {
|
||||
final ctr = plPlayerController.danmakuController;
|
||||
if (ctr == null) return;
|
||||
showBottomSheet((context, setState) {
|
||||
final theme = Theme.of(context);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Material(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
color: theme.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverPersistentHeader(
|
||||
pinned: true,
|
||||
delegate: CustomSliverPersistentHeaderDelegate(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('弹幕列表'),
|
||||
IconButton(
|
||||
onPressed: () => setState(() {}),
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bgColor: null,
|
||||
),
|
||||
),
|
||||
?_buildDanmakuList(ctr.staticDanmaku),
|
||||
?_buildDanmakuList(ctr.scrollDanmaku),
|
||||
?_buildDanmakuList(ctr.specialDanmaku),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget? _buildDanmakuList(List<DanmakuItem<DanmakuExtra>> list) {
|
||||
if (list.isEmpty) return null;
|
||||
list = List.of(list);
|
||||
|
||||
return SliverList.builder(
|
||||
itemCount: list.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = list[index];
|
||||
final extra = item.content.extra! as VideoDanmaku;
|
||||
return ListTile(
|
||||
onLongPress: () => Utils.copyText(item.content.text),
|
||||
subtitle: Text(item.content.text),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Builder(
|
||||
builder: (context) => IconButton(
|
||||
onPressed: () async {
|
||||
if (!Accounts.main.isLogin) {
|
||||
SmartDialog.showToast('请先登录');
|
||||
return;
|
||||
}
|
||||
final res = await DanmakuHttp.danmakuLike(
|
||||
isLike: extra.isLike,
|
||||
cid: plPlayerController.cid!,
|
||||
id: extra.id,
|
||||
);
|
||||
if (res.isSuccess) {
|
||||
extra.isLike = !extra.isLike;
|
||||
if (context.mounted) {
|
||||
(context as Element).markNeedsBuild();
|
||||
}
|
||||
} else {
|
||||
res.toast();
|
||||
}
|
||||
},
|
||||
icon: extra.isLike
|
||||
? const Icon(Icons.thumb_up)
|
||||
: const Icon(Icons.thumb_up_outlined),
|
||||
),
|
||||
),
|
||||
if (item.content.selfSend)
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
final res = await DanmakuHttp.danmakuRecall(
|
||||
cid: plPlayerController.cid!,
|
||||
id: extra.id,
|
||||
);
|
||||
if (res.isSuccess) {
|
||||
SmartDialog.showToast('删除成功');
|
||||
} else {
|
||||
res.toast();
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.delete_outline),
|
||||
)
|
||||
else
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
autoWrapReportDialog(
|
||||
context,
|
||||
ReportOptions.danmakuReport,
|
||||
(reasonType, reasonDesc, banUid) {
|
||||
if (banUid) {
|
||||
final filter = plPlayerController.filters;
|
||||
if (filter.dmUid.add(extra.mid)) {
|
||||
filter.count++;
|
||||
GStorage.localCache.put(
|
||||
LocalCacheKey.danmakuFilterRules,
|
||||
filter,
|
||||
);
|
||||
}
|
||||
DanmakuFilterHttp.danmakuFilterAdd(
|
||||
filter: extra.mid,
|
||||
type: 2,
|
||||
);
|
||||
}
|
||||
return DanmakuHttp.danmakuReport(
|
||||
reason: reasonType == 0 ? 11 : reasonType,
|
||||
cid: plPlayerController.cid!,
|
||||
id: extra.id,
|
||||
content: reasonDesc,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.report_problem_outlined),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 播放顺序
|
||||
void showSetRepeat() {
|
||||
showBottomSheet(
|
||||
|
||||
@@ -17,6 +17,7 @@ import 'package:PiliPlus/models/common/video/video_type.dart';
|
||||
import 'package:PiliPlus/models/user/danmaku_rule.dart';
|
||||
import 'package:PiliPlus/models/video/play/url.dart';
|
||||
import 'package:PiliPlus/models_new/video/video_shot/data.dart';
|
||||
import 'package:PiliPlus/pages/danmaku/dnamaku_model.dart';
|
||||
import 'package:PiliPlus/pages/mine/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/bottom_progress_behavior.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/data_source.dart';
|
||||
@@ -326,7 +327,7 @@ class PlPlayerController {
|
||||
late int danmakuWeight = Pref.danmakuWeight;
|
||||
late RuleFilter filters = Pref.danmakuFilterRule;
|
||||
// 关联弹幕控制器
|
||||
DanmakuController? danmakuController;
|
||||
DanmakuController<DanmakuExtra>? danmakuController;
|
||||
bool showDanmaku = true;
|
||||
Set<int> dmState = <int>{};
|
||||
late final mergeDanmaku = Pref.mergeDanmaku;
|
||||
|
||||
Reference in New Issue
Block a user