Skip to content

Commit 10ce888

Browse files
committed
修复滚动
1 parent c42e794 commit 10ce888

3 files changed

Lines changed: 52 additions & 11 deletions

File tree

assets/translations/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,5 +559,6 @@
559559
"detected_room_id_open": "Room ID detected, open live stream?",
560560
"no_room_id_open_url": "No Room ID detected, open webpage instead?",
561561
"cancel_mute": "Unmute",
562-
"mute": "Mute"
562+
"mute": "Mute",
563+
"copy_danmaku": "Copy Danmaku"
563564
}

assets/translations/zh.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,5 +559,6 @@
559559
"detected_room_id_open": "检测到房间号,是否打开直播间?",
560560
"no_room_id_open_url": "未检测到房间号,是否使用网页打开直播间?",
561561
"cancel_mute": "取消静音",
562-
"mute": "静音"
562+
"mute": "静音",
563+
"copy_danmaku": "复制弹幕"
563564
}

lib/modules/live_play/widgets/danmaku_list_view.dart

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
import 'dart:io';
12
import 'dart:async';
23
import 'dart:ui' as ui;
34
import 'package:get/get.dart';
5+
import 'package:flutter/services.dart';
46
import 'package:flutter/rendering.dart';
57
import 'package:flutter/scheduler.dart';
8+
import 'package:flutter/foundation.dart';
69
import 'package:pure_live/common/index.dart';
710
import 'package:pure_live/plugins/emoji_manager.dart';
11+
import 'package:device_info_plus/device_info_plus.dart';
812
import 'package:pure_live/modules/live_play/player_state.dart';
913
import 'package:pure_live/modules/live_play/live_play_controller.dart';
1014

@@ -32,7 +36,7 @@ class DanmakuListViewState extends State<DanmakuListView> {
3236
Worker? windowFullscreenWorker;
3337

3438
StreamSubscription? messagesSub;
35-
39+
bool _autoScrollEnabled = true;
3640
LivePlayController get controller => Get.find<LivePlayController>();
3741

3842
@override
@@ -106,6 +110,7 @@ class DanmakuListViewState extends State<DanmakuListView> {
106110

107111
void scheduleAutoScroll() {
108112
if (!mounted) return;
113+
if (!_autoScrollEnabled) return;
109114
if (!_scrollController.hasClients) return;
110115
final position = _scrollController.position;
111116
bool shouldAutoScroll = true;
@@ -144,6 +149,7 @@ class DanmakuListViewState extends State<DanmakuListView> {
144149
if (!userScrolling) {
145150
setState(() {
146151
userScrolling = true;
152+
_autoScrollEnabled = false;
147153
});
148154
}
149155
}
@@ -213,6 +219,7 @@ class DanmakuListViewState extends State<DanmakuListView> {
213219
onPressed: () async {
214220
setState(() {
215221
userScrolling = false;
222+
_autoScrollEnabled = true;
216223
});
217224

218225
await forceScrollToBottom();
@@ -269,21 +276,16 @@ class DanmakuItem extends StatelessWidget {
269276
),
270277

271278
Expanded(
272-
child: Text.rich(
279+
child: SelectableText.rich(
273280
TextSpan(
274281
children: [
275282
TextSpan(
276283
text: "${danmaku.userName}: ",
277-
style: TextStyle(
278-
fontSize: 14,
279-
fontWeight: FontWeight.w700,
280-
color: Colors.black87,
281-
letterSpacing: 0.2,
282-
),
284+
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w700, color: Colors.black87),
283285
),
284286
TextSpan(
285287
children: parseEmojis(danmaku.message, 14, vibrantColor),
286-
style: TextStyle(
288+
style: const TextStyle(
287289
fontSize: 14,
288290
height: 1.45,
289291
fontWeight: FontWeight.w500,
@@ -292,6 +294,43 @@ class DanmakuItem extends StatelessWidget {
292294
),
293295
],
294296
),
297+
contextMenuBuilder: (BuildContext context, EditableTextState editableTextState) {
298+
return AdaptiveTextSelectionToolbar.buttonItems(
299+
anchors: editableTextState.contextMenuAnchors,
300+
buttonItems: [
301+
ContextMenuButtonItem(
302+
label: i18n('copy_danmaku'),
303+
type: ContextMenuButtonType.copy,
304+
onPressed: () async {
305+
final String textToCopy = "${danmaku.userName}: ${danmaku.message}";
306+
await Clipboard.setData(ClipboardData(text: textToCopy));
307+
ContextMenuController.removeAny();
308+
bool shouldShowToast = false;
309+
if (kIsWeb) {
310+
shouldShowToast = true;
311+
} else if (Platform.isWindows) {
312+
shouldShowToast = true;
313+
} else if (Platform.isAndroid) {
314+
final androidInfo = await DeviceInfoPlugin().androidInfo;
315+
if (androidInfo.version.sdkInt < 33) {
316+
shouldShowToast = true;
317+
}
318+
}
319+
if (shouldShowToast && context.mounted) {
320+
ScaffoldMessenger.of(context).clearSnackBars(); // 清除之前的气泡
321+
ScaffoldMessenger.of(context).showSnackBar(
322+
SnackBar(
323+
content: Text(i18n('copied_to_clipboard')),
324+
duration: const Duration(seconds: 2),
325+
behavior: SnackBarBehavior.floating, // 让气泡悬浮,更好看
326+
),
327+
);
328+
}
329+
},
330+
),
331+
],
332+
);
333+
},
295334
),
296335
),
297336
],

0 commit comments

Comments
 (0)