mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-08 03:54:49 +08:00
@@ -70,6 +70,8 @@ class PlDanmakuController {
|
||||
final danmakuWeight = DanmakuOptions.danmakuWeight;
|
||||
final shouldFilter = filters.count != 0;
|
||||
for (final element in elems) {
|
||||
if (element.mode == 7) continue;
|
||||
|
||||
if (_isLogin) {
|
||||
element.isSelf = element.midHash == _plPlayerController.midHash;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
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/danmaku_model.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/play_status.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/utils/danmaku_options.dart';
|
||||
@@ -40,7 +37,7 @@ class _PlDanmakuState extends State<PlDanmaku> {
|
||||
PlPlayerController get playerController => widget.playerController;
|
||||
|
||||
late final PlDanmakuController _plDanmakuController;
|
||||
DanmakuController<DanmakuExtra>? _controller;
|
||||
DanmakuController? _controller;
|
||||
int latestAddedPosition = -1;
|
||||
|
||||
@override
|
||||
@@ -113,42 +110,17 @@ class _PlDanmakuState extends State<PlDanmaku> {
|
||||
List<DanmakuElem>? currentDanmakuList = _plDanmakuController
|
||||
.getCurrentDanmaku(currentPosition);
|
||||
if (currentDanmakuList != null) {
|
||||
final blockColorful = DanmakuOptions.blockColorful;
|
||||
for (DanmakuElem e in currentDanmakuList) {
|
||||
if (e.mode == 7) {
|
||||
try {
|
||||
_controller!.addDanmaku(
|
||||
SpecialDanmakuContentItem.fromList(
|
||||
DmUtils.decimalToColor(e.color),
|
||||
e.fontsize.toDouble(),
|
||||
jsonDecode(e.content.replaceAll('\n', '\\n')),
|
||||
extra: VideoDanmaku(
|
||||
id: e.id.toInt(),
|
||||
mid: e.midHash,
|
||||
like: e.likeCount.toInt(),
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (_) {}
|
||||
} else {
|
||||
_controller!.addDanmaku(
|
||||
DanmakuContentItem(
|
||||
e.content,
|
||||
color: blockColorful
|
||||
? Colors.white
|
||||
: DmUtils.decimalToColor(e.color),
|
||||
type: DmUtils.getPosition(e.mode),
|
||||
isColorful: e.colorful == DmColorfulType.VipGradualColor,
|
||||
count: e.count > 1 ? e.count : null,
|
||||
selfSend: e.isSelf,
|
||||
extra: VideoDanmaku(
|
||||
id: e.id.toInt(),
|
||||
mid: e.midHash,
|
||||
like: e.likeCount.toInt(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
_controller!.addDanmaku(
|
||||
DanmakuContentItem(
|
||||
e.content,
|
||||
color: DmUtils.decimalToColor(e.color),
|
||||
type: DmUtils.getPosition(e.mode),
|
||||
isColorful: e.colorful == DmColorfulType.VipGradualColor,
|
||||
count: e.count > 1 ? e.count : null,
|
||||
selfSend: e.isSelf,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,7 +147,7 @@ class _PlDanmakuState extends State<PlDanmaku> {
|
||||
? playerController.danmakuOpacity.value
|
||||
: 0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: DanmakuScreen<DanmakuExtra>(
|
||||
child: DanmakuScreen(
|
||||
createdController: (e) {
|
||||
playerController.danmakuController = _controller = e;
|
||||
},
|
||||
|
||||
@@ -22,7 +22,6 @@ import 'package:PiliPlus/pages/live_room/send_danmaku/view.dart';
|
||||
import 'package:PiliPlus/pages/video/widgets/header_control.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/models/data_source.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/utils/danmaku_options.dart';
|
||||
import 'package:PiliPlus/services/service_locator.dart';
|
||||
import 'package:PiliPlus/tcp/live.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
@@ -49,7 +48,7 @@ class LiveRoomController extends GetxController {
|
||||
|
||||
int roomId = Get.arguments;
|
||||
int? ruid;
|
||||
DanmakuController<DanmakuExtra>? danmakuController;
|
||||
DanmakuController? danmakuController;
|
||||
final plPlayerController = PlPlayerController.getInstance(isLive: true);
|
||||
|
||||
final isLoaded = false.obs;
|
||||
@@ -407,7 +406,7 @@ class LiveRoomController extends GetxController {
|
||||
..init();
|
||||
}
|
||||
|
||||
void addDm(dynamic msg, [DanmakuContentItem<DanmakuExtra>? item]) {
|
||||
void addDm(dynamic msg, [DanmakuContentItem? item]) {
|
||||
if (plPlayerController.showDanmaku) {
|
||||
if (item != null) {
|
||||
danmakuController?.addDanmaku(item);
|
||||
@@ -473,13 +472,10 @@ class LiveRoomController extends GetxController {
|
||||
),
|
||||
DanmakuContentItem(
|
||||
msg,
|
||||
color: DanmakuOptions.blockColorful
|
||||
? Colors.white
|
||||
: DmUtils.decimalToColor(extra['color']),
|
||||
color: DmUtils.decimalToColor(extra['color']),
|
||||
type: DmUtils.getPosition(extra['mode']),
|
||||
// extra['send_from_me'] is invalid
|
||||
selfSend: isLogin && uid == mid,
|
||||
extra: liveExtra,
|
||||
),
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -19,7 +19,6 @@ import 'package:PiliPlus/models/common/image_type.dart';
|
||||
import 'package:PiliPlus/models/common/live/live_contribution_rank_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/danmaku_model.dart';
|
||||
import 'package:PiliPlus/pages/live_room/contribution_rank/controller.dart';
|
||||
import 'package:PiliPlus/pages/live_room/contribution_rank/view.dart';
|
||||
import 'package:PiliPlus/pages/live_room/controller.dart';
|
||||
@@ -1044,7 +1043,7 @@ class _LiveDanmakuState extends State<LiveDanmaku> {
|
||||
? plPlayerController.danmakuOpacity.value
|
||||
: 0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: DanmakuScreen<DanmakuExtra>(
|
||||
child: DanmakuScreen(
|
||||
createdController: (e) {
|
||||
widget.liveRoomController.danmakuController =
|
||||
plPlayerController.danmakuController = e;
|
||||
|
||||
@@ -1443,49 +1443,4 @@ class VideoDetailController extends GetxController
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
Future<void> onCast() async {
|
||||
SmartDialog.showLoading();
|
||||
final res = await VideoHttp.tvPlayUrl(
|
||||
cid: cid.value,
|
||||
objectId: epId ?? aid,
|
||||
playurlType: epId != null ? 2 : 1,
|
||||
qn: currentVideoQa.value?.code,
|
||||
);
|
||||
SmartDialog.dismiss();
|
||||
if (res case Success(:final response)) {
|
||||
final first = response.durl?.firstOrNull;
|
||||
if (first == null || first.playUrls.isEmpty) {
|
||||
SmartDialog.showToast('不支持投屏');
|
||||
return;
|
||||
}
|
||||
final url = VideoUtils.getCdnUrl(first.playUrls);
|
||||
|
||||
String? title;
|
||||
try {
|
||||
if (isUgc) {
|
||||
title = Get.find<UgcIntroController>(
|
||||
tag: heroTag,
|
||||
).videoDetail.value.title;
|
||||
} else {
|
||||
title = Get.find<PgcIntroController>(
|
||||
tag: heroTag,
|
||||
).videoDetail.value.title;
|
||||
}
|
||||
} catch (_) {}
|
||||
if (kDebugMode) {
|
||||
debugPrint(title);
|
||||
}
|
||||
Get.toNamed(
|
||||
'/dlna',
|
||||
parameters: {
|
||||
'url': url,
|
||||
'title': ?title,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
res.toast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ import 'package:PiliPlus/http/danmaku.dart';
|
||||
import 'package:PiliPlus/http/loading_state.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/danmaku_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';
|
||||
@@ -22,7 +20,7 @@ class SendDanmakuPanel extends CommonTextPubPage {
|
||||
final dynamic bvid;
|
||||
final dynamic progress;
|
||||
|
||||
final ValueChanged<DanmakuContentItem<DanmakuExtra>> onSuccess;
|
||||
final ValueChanged<DanmakuContentItem> onSuccess;
|
||||
|
||||
// config
|
||||
final ({int? mode, int? fontSize, Color? color})? dmConfig;
|
||||
@@ -460,17 +458,10 @@ class _SendDanmakuPanelState extends CommonTextPubPageState<SendDanmakuPanel> {
|
||||
colorful: isColorful,
|
||||
);
|
||||
SmartDialog.dismiss();
|
||||
if (res case Success(:final response)) {
|
||||
if (res is Success) {
|
||||
hasPub = true;
|
||||
Get.back();
|
||||
SmartDialog.showToast('发送成功');
|
||||
VideoDanmaku? extra;
|
||||
if (response.dmid case final dmid?) {
|
||||
extra = VideoDanmaku(
|
||||
id: dmid,
|
||||
mid: PlPlayerController.instance!.midHash,
|
||||
);
|
||||
}
|
||||
widget.onSuccess(
|
||||
DanmakuContentItem(
|
||||
editController.text,
|
||||
@@ -482,7 +473,6 @@ class _SendDanmakuPanelState extends CommonTextPubPageState<SendDanmakuPanel> {
|
||||
},
|
||||
selfSend: true,
|
||||
isColorful: isColorful,
|
||||
extra: extra,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'dart:io' show Platform, File;
|
||||
import 'dart:typed_data' show Uint8List;
|
||||
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
||||
import 'package:PiliPlus/common/widgets/custom_icon.dart';
|
||||
import 'package:PiliPlus/common/widgets/dialog/report.dart';
|
||||
import 'package:PiliPlus/common/widgets/marquee.dart';
|
||||
@@ -51,7 +50,6 @@ import 'package:PiliPlus/utils/storage_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:PiliPlus/utils/video_utils.dart';
|
||||
import 'package:battery_plus/battery_plus.dart';
|
||||
import 'package:canvas_danmaku/canvas_danmaku.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
@@ -613,15 +611,6 @@ class HeaderControlState extends State<HeaderControl>
|
||||
descPosType: .subtitle,
|
||||
descFontSize: 12,
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
Get.back();
|
||||
showDanmakuPool();
|
||||
},
|
||||
leading: const Icon(CustomIcons.dm_on, size: 20),
|
||||
title: const Text('弹幕列表', style: titleStyle),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
@@ -1496,142 +1485,6 @@ class HeaderControlState extends State<HeaderControl>
|
||||
)?.whenComplete(plPlayerController.putSubtitleSettings);
|
||||
}
|
||||
|
||||
void showDanmakuPool() {
|
||||
final ctr = plPlayerController.danmakuController;
|
||||
if (ctr == null) return;
|
||||
showBottomSheet((context, setState) {
|
||||
final theme = Theme.of(context);
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 45,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('弹幕列表'),
|
||||
iconButton(
|
||||
onPressed: () => setState(() {}),
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
type: .transparency,
|
||||
clipBehavior: .hardEdge,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
bottom: Radius.circular(12),
|
||||
),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
?_buildDanmakuList(ctr.staticDanmaku.nonNulls.toList()),
|
||||
?_buildDanmakuList(
|
||||
ctr.scrollDanmaku.expand((e) => e).toList(),
|
||||
),
|
||||
?_buildDanmakuList(ctr.specialDanmaku.toList()),
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget? _buildDanmakuList(List<DanmakuItem<DanmakuExtra>> list) {
|
||||
if (list.isEmpty) return null;
|
||||
|
||||
return SliverList.builder(
|
||||
itemCount: list.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = list[index];
|
||||
final extra = item.content.extra! as VideoDanmaku;
|
||||
return ListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
onLongPress: () => Utils.copyText(item.content.text),
|
||||
title: Text(
|
||||
item.content.text,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Builder(
|
||||
builder: (context) => Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
iconButton(
|
||||
onPressed: () async {
|
||||
if (await HeaderControl.likeDanmaku(
|
||||
extra,
|
||||
plPlayerController.cid!,
|
||||
) &&
|
||||
context.mounted) {
|
||||
(context as Element).markNeedsBuild();
|
||||
}
|
||||
},
|
||||
icon: extra.isLike
|
||||
? const Icon(CustomIcons.player_dm_tip_like_solid)
|
||||
: const Icon(CustomIcons.player_dm_tip_like),
|
||||
),
|
||||
if (extra.like > 0)
|
||||
Positioned(
|
||||
left: 24.5,
|
||||
top: 1.5,
|
||||
child: Text(
|
||||
extra.like.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 10.5,
|
||||
letterSpacing: 0,
|
||||
// fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (item.content.selfSend)
|
||||
iconButton(
|
||||
onPressed: () => HeaderControl.deleteDanmaku(
|
||||
extra.id,
|
||||
plPlayerController.cid!,
|
||||
).then((_) => item.expired = true),
|
||||
icon: const Icon(CustomIcons.player_dm_tip_recall),
|
||||
)
|
||||
else
|
||||
iconButton(
|
||||
onPressed: () => HeaderControl.reportDanmaku(
|
||||
context,
|
||||
extra: extra,
|
||||
ctr: plPlayerController,
|
||||
),
|
||||
icon: const Icon(CustomIcons.player_dm_tip_back),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
late final isFileSource = videoDetailCtr.isFileSource;
|
||||
|
||||
@override
|
||||
@@ -1779,7 +1632,7 @@ class HeaderControlState extends State<HeaderControl>
|
||||
);
|
||||
}),
|
||||
if (!isFileSource) ...[
|
||||
if (!isFSOrPip) ...[
|
||||
if (!isFSOrPip)
|
||||
if (videoDetailCtr.isUgc)
|
||||
SizedBox(
|
||||
width: btnWidth,
|
||||
@@ -1795,21 +1648,6 @@ class HeaderControlState extends State<HeaderControl>
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: btnWidth,
|
||||
height: btnHeight,
|
||||
child: IconButton(
|
||||
tooltip: '投屏',
|
||||
style: btnStyle,
|
||||
onPressed: videoDetailCtr.onCast,
|
||||
icon: const Icon(
|
||||
Icons.cast,
|
||||
size: 19,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
if (plPlayerController.enableSponsorBlock)
|
||||
SizedBox(
|
||||
width: btnWidth,
|
||||
|
||||
@@ -44,8 +44,6 @@ mixin HeaderMixin<T extends StatefulWidget> on State<T> {
|
||||
(value: 2, label: '滚动'),
|
||||
(value: 5, label: '顶部'),
|
||||
(value: 4, label: '底部'),
|
||||
(value: 6, label: '彩色'),
|
||||
(value: 7, label: '高级'),
|
||||
];
|
||||
|
||||
final danmakuController = plPlayerController.danmakuController;
|
||||
@@ -140,7 +138,6 @@ mixin HeaderMixin<T extends StatefulWidget> on State<T> {
|
||||
} else {
|
||||
DanmakuOptions.blockTypes.add(blockType);
|
||||
}
|
||||
DanmakuOptions.blockColorful = DanmakuOptions.blockTypes.contains(6);
|
||||
setState(() {});
|
||||
setOptions();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user