* opt: unused layout

* mod: semantics

* opt: DanmakuMsg type

* opt: avoid cast

* opt: unnecessary_lambdas

* opt: use isEven

* opt: logger

* opt: invalid common page

* tweak

* opt: unify DynController
This commit is contained in:
My-Responsitories
2025-08-27 12:01:53 +08:00
committed by GitHub
parent 56ffc2781f
commit 5f8313901b
83 changed files with 551 additions and 545 deletions

View File

@@ -6,6 +6,8 @@ import 'package:PiliPlus/http/constants.dart';
import 'package:PiliPlus/http/live.dart';
import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/common/video/live_quality.dart';
import 'package:PiliPlus/models_new/live/live_danmaku/danmaku_msg.dart';
import 'package:PiliPlus/models_new/live/live_danmaku/live_emote.dart';
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';
@@ -22,6 +24,7 @@ import 'package:PiliPlus/utils/video_utils.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -60,7 +63,7 @@ class LiveRoomController extends GetxController {
// dm
LiveDmInfoData? dmInfo;
List<RichTextItem>? savedDanmaku;
RxList<dynamic> messages = [].obs;
RxList<DanmakuMsg> messages = <DanmakuMsg>[].obs;
RxBool disableAutoScroll = false.obs;
LiveMessageStream? _msgStream;
late final ScrollController scrollController = ScrollController()
@@ -214,20 +217,12 @@ class LiveRoomController extends GetxController {
if (v['data'] case List list) {
try {
messages.addAll(
list.map(
(obj) => {
'name': obj['user']['base']['name'],
'uid': obj['user']['uid'],
'text': obj['text'],
'emots': obj['emots'],
'uemote': obj['emoticon']['emoticon_unique'] != ""
? obj['emoticon']
: null,
},
),
list.cast<Map<String, dynamic>>().map(DanmakuMsg.fromPrefetch),
);
WidgetsBinding.instance.addPostFrameCallback(scrollToBottom);
} catch (_) {}
} catch (e) {
if (kDebugMode) debugPrint(e.toString());
}
}
}
});
@@ -307,13 +302,18 @@ class LiveRoomController extends GetxController {
final extra = jsonDecode(content['extra']);
final user = content['user'];
final uid = user['uid'];
messages.add({
'name': user['base']['name'],
'uid': uid,
'text': info[1],
'emots': extra['emots'],
'uemote': first[13],
});
messages.add(
DanmakuMsg()
..name = user['base']['name']
..uid = uid
..text = info[1]
..emots = (extra['emots'] as Map<String, dynamic>?)?.map(
(k, v) => MapEntry(k, BaseEmote.fromJson(v)),
)
..uemote = first[13] is Map<String, dynamic>
? BaseEmote.fromJson(first[13])
: null,
);
if (plPlayerController.showDanmaku) {
plPlayerController.danmakuController?.addDanmaku(
@@ -335,7 +335,9 @@ class LiveRoomController extends GetxController {
}
}
}
} catch (_) {}
} catch (e) {
if (kDebugMode) debugPrint(e.toString());
}
})
..init();
}

View File

@@ -1,5 +1,6 @@
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/models/common/image_type.dart';
import 'package:PiliPlus/models_new/live/live_danmaku/danmaku_msg.dart';
import 'package:PiliPlus/pages/live_room/controller.dart';
import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/gestures.dart';
@@ -54,7 +55,7 @@ class LiveRoomChat extends StatelessWidget {
TextSpan(
children: [
TextSpan(
text: '${item['name']}: ',
text: '${item.name}: ',
style: TextStyle(
color: nameColor,
fontSize: 14,
@@ -62,7 +63,7 @@ class LiveRoomChat extends StatelessWidget {
recognizer: TapGestureRecognizer()
..onTap = () {
try {
Get.toNamed('/member?mid=${item['uid']}');
Get.toNamed('/member?mid=${item.uid}');
} catch (err) {
if (kDebugMode) debugPrint(err.toString());
}
@@ -99,31 +100,37 @@ class LiveRoomChat extends StatelessWidget {
);
}
TextSpan _buildMsg(dynamic obj) {
dynamic emots = obj['emots'];
dynamic uemote = obj['uemote'];
List<String> list = [
if (emots != null) ...emots.keys,
if (uemote is Map) uemote['emoticon_unique'].replaceFirst('upower_', ''),
];
if (list.isNotEmpty) {
RegExp regExp = RegExp(list.map(RegExp.escape).join('|'));
InlineSpan _buildMsg(DanmakuMsg obj) {
final uemote = obj.uemote;
if (uemote != null) {
// "room_{{room_id}}_{{int}}" or "upower_[{{emote}}]"
return WidgetSpan(
child: NetworkImgLayer(
src: uemote.url,
type: ImageType.emote,
width: uemote.width,
height: uemote.height,
semanticsLabel: obj.text,
),
);
}
final emots = obj.emots;
if (emots != null) {
RegExp regExp = RegExp(emots.keys.map(RegExp.escape).join('|'));
final List<InlineSpan> spanChildren = <InlineSpan>[];
(obj['text'] as String).splitMapJoin(
obj.text.splitMapJoin(
regExp,
onMatch: (Match match) {
String key = match[0]!;
dynamic emote = emots?[key] ?? uemote;
onMatch: (match) {
final key = match[0]!;
final emote = emots[key]!;
spanChildren.add(
WidgetSpan(
child: ExcludeSemantics(
child: NetworkImgLayer(
src: emote['url'],
type: ImageType.emote,
width: emote['width'].toDouble(),
height: emote['height'].toDouble(),
semanticsLabel: key,
),
child: NetworkImgLayer(
src: emote.url,
type: ImageType.emote,
width: emote.width,
height: emote.height,
semanticsLabel: key,
),
),
);
@@ -145,7 +152,7 @@ class LiveRoomChat extends StatelessWidget {
return TextSpan(children: spanChildren);
} else {
return TextSpan(
text: obj['text'],
text: obj.text,
style: const TextStyle(
color: Colors.white,
fontSize: 14,