Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-05-06 14:14:19 +08:00
parent 1a8c348af1
commit 07843a5e77
239 changed files with 3175 additions and 13237 deletions

View File

@@ -7,7 +7,6 @@ import 'package:PiliPlus/common/widgets/flutter/text_field/controller.dart';
import 'package:PiliPlus/http/live.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/common/super_chat_type.dart';
import 'package:PiliPlus/models/common/video/live_quality.dart';
import 'package:PiliPlus/models/model_owner.dart';
import 'package:PiliPlus/models_new/live/live_danmaku/danmaku_msg.dart';
@@ -31,7 +30,6 @@ import 'package:PiliPlus/utils/connectivity_utils.dart';
import 'package:PiliPlus/utils/danmaku_utils.dart';
import 'package:PiliPlus/utils/duration_utils.dart';
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
import 'package:PiliPlus/utils/global_data.dart';
import 'package:PiliPlus/utils/num_utils.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
@@ -111,7 +109,7 @@ class LiveRoomController extends GetxController {
LiveMessageStream? _msgStream;
late final ScrollController scrollController;
late final RxInt pageIndex = 0.obs;
PageController? pageController;
late final PageController pageController;
int? currentQn = PlatformUtils.isMobile ? null : Pref.liveQuality;
RxString currentQnDesc = ''.obs;
@@ -125,9 +123,6 @@ class LiveRoomController extends GetxController {
bool? isPlaying;
late bool isFullScreen = false;
final superChatType = Pref.superChatType;
late final showSuperChat = superChatType != SuperChatType.disable;
final headerKey = GlobalKey<TimeBatteryMixin>();
final RxString title = ''.obs;
@@ -160,9 +155,7 @@ class LiveRoomController extends GetxController {
if (Accounts.heartbeat.isLogin && !Pref.historyPause) {
VideoHttp.roomEntryAction(roomId: roomId);
}
if (showSuperChat) {
pageController = PageController();
}
pageController = PageController();
}
Future<void>? playerInit({
@@ -177,7 +170,6 @@ class LiveRoomController extends GetxController {
isLive: true,
autoplay: autoplay,
isVertical: isPortrait.value,
autoFullScreenFlag: autoFullScreenFlag,
);
}
@@ -338,9 +330,7 @@ class LiveRoomController extends GetxController {
void startLiveMsg() {
if (messages.isEmpty) {
prefetch();
if (showSuperChat) {
getSuperChatMsg();
}
getSuperChatMsg();
}
if (_msgStream != null) {
return;
@@ -385,14 +375,12 @@ class LiveRoomController extends GetxController {
savedDanmaku?.clear();
savedDanmaku = null;
messages.clear();
if (showSuperChat) {
superChatMsg.clear();
fsSC.value = null;
}
superChatMsg.clear();
fsSC.value = null;
scrollController
..removeListener(listener)
..dispose();
pageController?.dispose();
pageController.dispose();
danmakuController = null;
super.onClose();
}
@@ -485,7 +473,7 @@ class LiveRoomController extends GetxController {
uemote: uemote,
extra: liveExtra,
reply: reply,
medalInfo: !GlobalData().showMedal || user['medal'] == null
medalInfo: user['medal'] == null
? null
: UinfoMedal.fromJson(user['medal']),
),
@@ -501,7 +489,7 @@ class LiveRoomController extends GetxController {
),
);
break;
case 'SUPER_CHAT_MESSAGE' when showSuperChat:
case 'SUPER_CHAT_MESSAGE':
final item = SuperChatItem.fromJson(obj['data']);
superChatMsg.insert(0, item);
if (plPlayerController.showDanmaku &&
@@ -515,27 +503,6 @@ class LiveRoomController extends GetxController {
}
addDm(item);
break;
// case 'SUPER_CHAT_MESSAGE_DELETE' when showSuperChat:
// if (obj['roomid'] == roomId) {
// final ids = obj['data']?['ids'] as List?;
// if (ids != null && ids.isNotEmpty) {
// if (superChatType == .valid) {
// superChatMsg.removeWhere((e) => ids.contains(e.id));
// } else {
// bool? refresh;
// for (final id in ids) {
// if (superChatMsg.firstWhereOrNull((e) => e.id == id)
// case final item?) {
// item.deleted = true;
// refresh ??= true;
// }
// }
// if (refresh ?? false) {
// superChatMsg.refresh();
// }
// }
// }
// }
case 'WATCHED_CHANGE':
watchedShow.value = obj['data']['text_large'];
break;

View File

@@ -1,7 +1,5 @@
import 'package:PiliPlus/models/common/super_chat_type.dart';
import 'package:PiliPlus/pages/live_room/controller.dart';
import 'package:PiliPlus/pages/live_room/superchat/superchat_card.dart';
import 'package:PiliPlus/pages/search/controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
@@ -17,15 +15,9 @@ class SuperChatPanel extends StatefulWidget {
State<SuperChatPanel> createState() => _SuperChatPanelState();
}
class _SuperChatPanelState extends DebounceStreamState<SuperChatPanel, bool>
class _SuperChatPanelState extends State<SuperChatPanel>
with AutomaticKeepAliveClientMixin {
@override
Duration get duration => const Duration(milliseconds: 300);
late final persistentSC =
widget.controller.superChatType == SuperChatType.persist;
@override
Widget build(BuildContext context) {
super.build(context);
return Obx(
@@ -46,8 +38,7 @@ class _SuperChatPanelState extends DebounceStreamState<SuperChatPanel, bool>
return SuperChatCard(
key: ValueKey(item.id),
item: item,
onRemove: () => ctr?.add(true),
persistentSC: persistentSC,
persistentSC: true,
onReport: () => widget.controller.reportSC(item),
);
},
@@ -56,9 +47,6 @@ class _SuperChatPanelState extends DebounceStreamState<SuperChatPanel, bool>
);
}
@override
void onValueChanged(value) => widget.controller.clearSC();
@override
bool get wantKeepAlive => true;
}

View File

@@ -32,21 +32,18 @@ import 'package:PiliPlus/pages/video/widgets/player_focus.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';
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
import 'package:PiliPlus/plugin/pl_player/view/view.dart';
import 'package:PiliPlus/services/service_locator.dart';
import 'package:PiliPlus/utils/extension/num_ext.dart';
import 'package:PiliPlus/utils/extension/size_ext.dart';
import 'package:PiliPlus/utils/extension/theme_ext.dart';
import 'package:PiliPlus/utils/image_utils.dart';
import 'package:PiliPlus/utils/max_screen_size.dart';
import 'package:PiliPlus/utils/mobile_observer.dart';
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:PiliPlus/utils/share_utils.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:PiliPlus/utils/storage_key.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
@@ -55,7 +52,6 @@ import 'package:flutter/foundation.dart' show kDebugMode;
import 'package:flutter/material.dart' hide PageView;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:screen_brightness_platform_interface/screen_brightness_platform_interface.dart';
class LiveRoomPage extends StatefulWidget {
const LiveRoomPage({super.key});
@@ -66,7 +62,6 @@ class LiveRoomPage extends StatefulWidget {
class _LiveRoomPageState extends State<LiveRoomPage>
with WidgetsBindingObserver, RouteAware, RouteAwareMixin {
late final fullScreenSCWidth = Pref.fullScreenSCWidth;
final String heroTag = Utils.generateRandomString(6);
late final LiveRoomController _liveRoomController;
late final PlPlayerController plPlayerController;
@@ -88,26 +83,15 @@ class _LiveRoomPageState extends State<LiveRoomPage>
plPlayerController = _liveRoomController.plPlayerController
..addStatusLister(playerListener);
PlPlayerController.setPlayCallBack(plPlayerController.play);
if (plPlayerController.removeSafeArea) {
hideSystemBar();
}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (plPlayerController.removeSafeArea) {
padding = .zero;
} else {
padding = MediaQuery.viewPaddingOf(context);
}
padding = MediaQuery.viewPaddingOf(context);
final size = MediaQuery.sizeOf(context);
maxWidth = size.width;
maxHeight = size.height;
isWindowMode = MaxScreenSize.isWindowMode(
width: maxWidth,
height: maxHeight,
);
isPortrait = size.isPortrait;
plPlayerController.screenRatio = maxHeight / maxWidth;
}
@@ -170,9 +154,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
void dispose() {
removeObserverMobile(this);
videoPlayerServiceHandler?.onVideoDetailDispose(heroTag);
if (Platform.isAndroid && !plPlayerController.setSystemBrightness) {
ScreenBrightnessPlatform.instance.resetApplicationScreenBrightness();
}
PlPlayerController.setPlayCallBack(null);
plPlayerController
..removeStatusLister(playerListener)
@@ -204,7 +185,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
late double maxWidth;
late double maxHeight;
bool isWindowMode = false;
late EdgeInsets padding;
late bool isPortrait;
@@ -217,7 +197,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
width: maxWidth,
height: maxHeight,
isPipMode: true,
needDm: !plPlayerController.pipNoDanmaku,
);
} else {
child = childWhenDisabled;
@@ -290,8 +269,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
return const SizedBox.shrink();
},
);
if (_liveRoomController.showSuperChat &&
(isFullScreen || plPlayerController.isDesktopPip)) {
if ((isFullScreen || plPlayerController.isDesktopPip)) {
player = Stack(
clipBehavior: Clip.none,
children: [
@@ -324,7 +302,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Positioned(
left: padding.left + 25,
bottom: 25,
width: fullScreenSCWidth,
width: 255.0,
child: Obx(() {
final item = _liveRoomController.fsSC.value;
if (item == null) {
@@ -409,23 +387,22 @@ class _LiveRoomPageState extends State<LiveRoomPage>
);
},
),
Scaffold(
primary: !plPlayerController.removeSafeArea,
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
appBar: isWindowMode && isFullScreen && !isPortrait
? null
: _buildAppBar(isFullScreen),
body: isPortrait
? Obx(
() {
if (_liveRoomController.isPortrait.value) {
return _buildPP(isFullScreen);
}
return _buildPH(isFullScreen);
},
)
: _buildBodyH(isFullScreen),
Column(
children: [
if (!(isFullScreen && !isPortrait)) _buildAppBar(isFullScreen),
Expanded(
child: isPortrait
? Obx(
() {
if (_liveRoomController.isPortrait.value) {
return _buildPP(isFullScreen);
}
return _buildPH(isFullScreen);
},
)
: _buildBodyH(isFullScreen),
),
],
),
],
);
@@ -435,7 +412,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Widget _buildPH(bool isFullScreen) {
final height = maxWidth / Style.aspectRatio16x9;
final videoHeight = isFullScreen
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
? maxHeight - (!isPortrait ? 0 : padding.top)
: height;
final bottomHeight = maxHeight - padding.top - height - kToolbarHeight;
return Column(
@@ -464,7 +441,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Widget _buildPP(bool isFullScreen) {
final bottomHeight = 70 + padding.bottom;
final videoHeight = isFullScreen
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
? maxHeight - (!isPortrait ? 0 : padding.top)
: maxHeight - bottomHeight;
return Stack(
clipBehavior: Clip.none,
@@ -543,7 +520,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
PreferredSizeWidget _buildAppBar(bool isFullScreen) {
final color = Theme.of(context).colorScheme.onSurfaceVariant;
return AppBar(
primary: !plPlayerController.removeSafeArea,
toolbarHeight: isFullScreen ? 0 : null,
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
@@ -652,21 +628,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
],
),
),
PopupMenuItem(
onTap: () => PageUtils.inAppWebview(liveUrl, off: true),
child: Row(
spacing: 10,
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.open_in_browser,
size: 19,
color: color,
),
const Text('浏览器打开'),
],
),
),
if (_liveRoomController.roomInfoH5.value != null)
PopupMenuItem(
onTap: () {
@@ -718,7 +679,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
final videoHeight = maxHeight - padding.top - kToolbarHeight;
final width = isFullScreen ? maxWidth : videoWidth;
final height = isFullScreen
? maxHeight - (isWindowMode && !isPortrait ? 0 : padding.top)
? maxHeight - (!isPortrait ? 0 : padding.top)
: videoHeight;
return Padding(
padding: isFullScreen
@@ -777,24 +738,21 @@ class _LiveRoomPageState extends State<LiveRoomPage>
);
return Padding(
padding: EdgeInsets.only(bottom: 12, top: isPortrait ? 12 : 0),
child: _liveRoomController.showSuperChat
? PageView<CustomHorizontalDragGestureRecognizer>(
key: pageKey,
controller: _liveRoomController.pageController,
physics: clampingScrollPhysics,
onPageChanged: (value) =>
_liveRoomController.pageIndex.value = value,
horizontalDragGestureRecognizer:
CustomHorizontalDragGestureRecognizer.new,
children: [
KeepAliveWrapper(child: chat()),
SuperChatPanel(
key: scKey,
controller: _liveRoomController,
),
],
)
: chat(),
child: PageView<CustomHorizontalDragGestureRecognizer>(
key: pageKey,
controller: _liveRoomController.pageController,
physics: clampingScrollPhysics,
onPageChanged: (value) => _liveRoomController.pageIndex.value = value,
horizontalDragGestureRecognizer:
CustomHorizontalDragGestureRecognizer.new,
children: [
KeepAliveWrapper(child: chat()),
SuperChatPanel(
key: scKey,
controller: _liveRoomController,
),
],
),
);
}
@@ -836,12 +794,10 @@ class _LiveRoomPageState extends State<LiveRoomPage>
onPressed: () {
final newVal = !enableShowLiveDanmaku;
plPlayerController.enableShowDanmaku.value = newVal;
if (!plPlayerController.tempPlayerConf) {
GStorage.setting.put(
SettingBoxKey.enableShowLiveDanmaku,
newVal,
);
}
GStorage.setting.put(
SettingBoxKey.enableShowLiveDanmaku,
newVal,
);
},
icon: enableShowLiveDanmaku
? const Icon(
@@ -941,25 +897,22 @@ class _LiveRoomPageState extends State<LiveRoomPage>
),
),
);
if (_liveRoomController.showSuperChat) {
return Stack(
children: [
child,
Positioned(
left: 0,
top: 0,
right: 0,
child: Obx(
() => _BorderIndicator(
radius: const Radius.circular(20),
isLeft: _liveRoomController.pageIndex.value == 0,
),
return Stack(
children: [
child,
Positioned(
left: 0,
top: 0,
right: 0,
child: Obx(
() => _BorderIndicator(
radius: const Radius.circular(20),
isLeft: _liveRoomController.pageIndex.value == 0,
),
),
],
);
}
return child;
),
],
);
}
WidgetStateProperty<Color?>? overlayColor(ColorScheme theme) =>

View File

@@ -103,12 +103,10 @@ class _BottomControlState extends State<BottomControl> with HeaderMixin {
onTap: () {
final newVal = !enableShowLiveDanmaku;
plPlayerController.enableShowDanmaku.value = newVal;
if (!plPlayerController.tempPlayerConf) {
GStorage.setting.put(
SettingBoxKey.enableShowLiveDanmaku,
newVal,
);
}
GStorage.setting.put(
SettingBoxKey.enableShowLiveDanmaku,
newVal,
);
},
);
},

View File

@@ -137,7 +137,7 @@ class LiveRoomChatPanel extends StatelessWidget {
},
),
),
if (kDebugMode && liveRoomController.showSuperChat) ...[
if (kDebugMode) ...[
Positioned(
top: 50,
right: 0,
@@ -164,55 +164,53 @@ class LiveRoomChatPanel extends StatelessWidget {
),
),
],
if (liveRoomController.showSuperChat)
Positioned(
top: 12,
right: 12,
child: Obx(() {
final isEmpty = liveRoomController.superChatMsg.isEmpty;
return AnimatedOpacity(
opacity: isEmpty ? 0 : 1,
duration: const Duration(milliseconds: 120),
child: GestureDetector(
onTap: isEmpty
? null
: () => liveRoomController.pageController?.animateToPage(
1,
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
),
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8)),
color: const Color(0x2FFFFFFF),
border: Border.all(color: Colors.white24, width: 0.7),
),
padding: const EdgeInsets.fromLTRB(10, 4, 4, 4),
child: Text.rich(
style: const TextStyle(color: Colors.white, height: 1),
strutStyle: const StrutStyle(height: 1, leading: 0),
TextSpan(
children: [
TextSpan(
text:
'SC(${liveRoomController.superChatMsg.length})',
),
const WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
size: 18,
Icons.keyboard_arrow_right,
color: Colors.white,
),
),
],
Positioned(
top: 12,
right: 12,
child: Obx(() {
final isEmpty = liveRoomController.superChatMsg.isEmpty;
return AnimatedOpacity(
opacity: isEmpty ? 0 : 1,
duration: const Duration(milliseconds: 120),
child: GestureDetector(
onTap: isEmpty
? null
: () => liveRoomController.pageController.animateToPage(
1,
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
),
child: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8)),
color: const Color(0x2FFFFFFF),
border: Border.all(color: Colors.white24, width: 0.7),
),
padding: const EdgeInsets.fromLTRB(10, 4, 4, 4),
child: Text.rich(
style: const TextStyle(color: Colors.white, height: 1),
strutStyle: const StrutStyle(height: 1, leading: 0),
TextSpan(
children: [
TextSpan(
text: 'SC(${liveRoomController.superChatMsg.length})',
),
const WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
size: 18,
Icons.keyboard_arrow_right,
color: Colors.white,
),
),
],
),
),
),
);
}),
),
),
);
}),
),
Obx(
() => liveRoomController.disableAutoScroll.value
? Positioned(