Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-05-11 10:06:11 +08:00
parent 49c6cd0ab8
commit 32eeef7866
15 changed files with 253 additions and 320 deletions

View File

@@ -34,10 +34,7 @@ Widget? addWidget(
? null
: () => PiliScheme.routePushFromUrl(ugc.jumpUrl!),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8,
),
padding: const .symmetric(horizontal: 12, vertical: 8),
child: Row(
children: [
NetworkImgLayer(
@@ -48,13 +45,9 @@ Widget? addWidget(
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: [
Text(
ugc.title!,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Text(ugc.title!),
const SizedBox(height: 4),
Text(
ugc.descSecond!,
@@ -78,18 +71,14 @@ Widget? addWidget(
onTap: () {},
borderRadius: borderRadius,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
padding: const .symmetric(horizontal: 12, vertical: 10),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: [
Text(
reserve.title!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(reserve.title!),
const SizedBox(height: 1),
Text.rich(
TextSpan(
@@ -109,7 +98,7 @@ Widget? addWidget(
if (reserve.desc3?.text?.isNotEmpty == true) ...[
const TextSpan(text: '\n'),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
alignment: .middle,
child: Icon(
size: 17,
Icons.card_giftcard,
@@ -158,16 +147,12 @@ Widget? addWidget(
alpha: 0.12,
)
: null,
visualDensity: VisualDensity.compact,
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: .compact,
tapTargetSize: .shrinkWrap,
padding: const .symmetric(horizontal: 16),
),
onPressed: canJump
? () => PiliScheme.routePushFromUrl(
btn.jumpUrl!,
)
? () => PiliScheme.routePushFromUrl(btn.jumpUrl!)
: btn.disable == 1
? null
: () async {
@@ -216,14 +201,14 @@ Widget? addWidget(
? null
: () => PiliScheme.routePushFromUrl(content.jumpUrl!),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
padding: const .symmetric(horizontal: 12, vertical: 8),
child: Row(
children: [
Expanded(
child: Column(
spacing: 2,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
if (content.title?.isNotEmpty == true)
Text(content.title!),
@@ -240,7 +225,7 @@ Widget? addWidget(
TextSpan(
children: [
WidgetSpan(
alignment: PlaceholderAlignment.middle,
alignment: .middle,
child: Icon(
size: 17,
Icons.card_giftcard,
@@ -276,14 +261,14 @@ Widget? addWidget(
),
style: FilledButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6)),
borderRadius: .all(.circular(6)),
),
padding: const EdgeInsets.symmetric(horizontal: 10),
padding: const .symmetric(horizontal: 10),
visualDensity: const VisualDensity(
horizontal: -2,
vertical: -3,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
tapTargetSize: .shrinkWrap,
),
child: Text(
content.button!.jumpStyle?.text ??
@@ -302,16 +287,13 @@ Widget? addWidget(
final content = additional.goods!;
if (content.items?.isNotEmpty == true) {
child = Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: content.items!.map((e) {
return InkWell(
borderRadius: borderRadius,
onTap: () => PiliScheme.routePushFromUrl(e.jumpUrl!),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8,
),
padding: const .symmetric(horizontal: 12, vertical: 8),
child: Row(
children: [
if (e.cover?.isNotEmpty == true) ...[
@@ -319,20 +301,18 @@ Widget? addWidget(
width: 45,
height: 45,
src: e.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
),
borderRadius: const .all(.circular(6)),
),
const SizedBox(width: 10),
],
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: [
Text(
e.name!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
overflow: .ellipsis,
),
if (e.price?.isNotEmpty == true)
Text.rich(
@@ -361,18 +341,14 @@ Widget? addWidget(
PiliScheme.routePushFromUrl(e.jumpUrl!),
style: FilledButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(6),
),
),
padding: const EdgeInsets.symmetric(
horizontal: 10,
borderRadius: .all(.circular(6)),
),
padding: const .symmetric(horizontal: 10),
visualDensity: const VisualDensity(
horizontal: -2,
vertical: -3,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
tapTargetSize: .shrinkWrap,
),
child: Text(e.jumpDesc!),
),
@@ -399,7 +375,7 @@ Widget? addWidget(
: null,
),
child: Padding(
padding: const EdgeInsets.symmetric(
padding: const .symmetric(
horizontal: 12,
vertical: 8,
),
@@ -410,9 +386,7 @@ Widget? addWidget(
color: floor == 1
? theme.colorScheme.surface
: theme.dividerColor.withValues(alpha: 0.08),
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
borderRadius: const .all(.circular(8)),
),
width: 70,
height: 50,
@@ -424,18 +398,11 @@ Widget? addWidget(
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: [
if (vote.title case final title?)
Text(
title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
if (vote.title case final title?) Text(title),
Text(
'${NumUtils.numFormat(vote.joinNum)}人参与',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
color: theme.colorScheme.outline,
@@ -457,14 +424,14 @@ Widget? addWidget(
),
style: FilledButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6)),
borderRadius: .all(.circular(6)),
),
padding: const EdgeInsets.symmetric(horizontal: 10),
padding: const .symmetric(horizontal: 10),
visualDensity: const VisualDensity(
horizontal: -2,
vertical: -3,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
tapTargetSize: .shrinkWrap,
),
child: const Text('参与'),
),
@@ -481,7 +448,7 @@ Widget? addWidget(
? null
: () => PiliScheme.routePushFromUrl(content.jumpUrl!),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
padding: const .symmetric(horizontal: 12, vertical: 8),
child: Row(
children: [
if (content.cover?.isNotEmpty == true) ...[
@@ -489,8 +456,8 @@ Widget? addWidget(
width: 45,
height: 45,
src: content.cover,
borderRadius: const BorderRadius.all(
Radius.circular(6),
borderRadius: const .all(
.circular(6),
),
),
const SizedBox(width: 10),
@@ -498,8 +465,8 @@ Widget? addWidget(
Expanded(
child: Column(
spacing: 2,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
if (content.title?.isNotEmpty == true)
Text(content.title!),
@@ -530,14 +497,14 @@ Widget? addWidget(
),
style: FilledButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6)),
borderRadius: .all(.circular(6)),
),
padding: const EdgeInsets.symmetric(horizontal: 10),
padding: const .symmetric(horizontal: 10),
visualDensity: const VisualDensity(
horizontal: -2,
vertical: -3,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
tapTargetSize: .shrinkWrap,
),
child: Text(content.button!.jumpStyle?.text ?? ''),
),
@@ -586,7 +553,7 @@ Widget? addWidget(
}
if (content.matchInfo?.subTitle?.isNotEmpty == true) {
title = Column(
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
?title,
Text(
@@ -605,7 +572,7 @@ Widget? addWidget(
? null
: () => PiliScheme.routePushFromUrl(content.jumpUrl!),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
padding: const .symmetric(horizontal: 12, vertical: 8),
child: Row(
children: [
?title,
@@ -620,11 +587,11 @@ Widget? addWidget(
if (content.matchInfo?.centerTop?.isNotEmpty == true)
Container(
height: 35,
alignment: Alignment.center,
alignment: .center,
child: Text(
content.matchInfo!.centerTop!.join(' '),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontWeight: .bold,
fontSize: 16,
),
),
@@ -651,14 +618,14 @@ Widget? addWidget(
PiliScheme.routePushFromUrl(button.jumpUrl!),
style: FilledButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6)),
borderRadius: .all(.circular(6)),
),
padding: const EdgeInsets.symmetric(horizontal: 10),
padding: const .symmetric(horizontal: 10),
visualDensity: const VisualDensity(
horizontal: -2,
vertical: -3,
),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
tapTargetSize: .shrinkWrap,
),
child: Text(button.jumpStyle?.text ?? ''),
),
@@ -669,7 +636,7 @@ Widget? addWidget(
}
if (child != null) {
return Padding(
padding: const EdgeInsets.only(top: 6),
padding: const .only(top: 6),
child: Material(
borderRadius: borderRadius,
color: bgColor,
@@ -681,7 +648,7 @@ Widget? addWidget(
}
} catch (e) {
return Padding(
padding: const EdgeInsets.all(12),
padding: const .all(12),
child: SelectableText(
'''
additional panel error

View File

@@ -109,7 +109,7 @@ Widget livePanelSub(
if (live.title case final title?)
Text(
title,
maxLines: isDetail ? null : 1,
maxLines: isDetail ? null : 2,
style: const TextStyle(fontWeight: FontWeight.bold),
overflow: isDetail ? null : TextOverflow.ellipsis,
),

View File

@@ -104,7 +104,7 @@ Widget liveRcmdPanel(
if (liveRcmd.title case final title?)
Text(
title,
maxLines: isDetail ? null : 1,
maxLines: isDetail ? null : 2,
style: const TextStyle(fontWeight: FontWeight.bold),
overflow: isDetail ? null : TextOverflow.ellipsis,
),

View File

@@ -138,7 +138,7 @@ Widget videoSeasonWidget(
if (video.title case final title?)
Text(
title,
maxLines: isDetail ? null : 1,
maxLines: isDetail ? null : 2,
style: const TextStyle(fontWeight: FontWeight.bold),
overflow: isDetail ? null : TextOverflow.ellipsis,
),

View File

@@ -771,15 +771,17 @@ class _CreateDynPanelState extends CommonRichTextPubPageState<CreateDynPanel> {
}
final reserveCard = _reserveCard.value;
final publishTime = _publishTime.value;
final isPrivate = _isPrivate.value;
final res = await DynamicsHttp.createDynamic(
mid: Accounts.main.mid,
rawText: hasRichText ? null : editController.text,
pics: pictures,
publishTime: _publishTime.value != null
? _publishTime.value!.millisecondsSinceEpoch ~/ 1000
publishTime: publishTime != null
? publishTime.millisecondsSinceEpoch ~/ 1000
: null,
replyOption: _replyOption.value,
privatePub: _isPrivate.value ? 1 : null,
privatePub: isPrivate ? 1 : null,
title: _titleEditCtr.text,
topic: _topic.value,
extraContent: extraContent,
@@ -801,7 +803,7 @@ class _CreateDynPanelState extends CommonRichTextPubPageState<CreateDynPanel> {
SmartDialog.showToast('发布成功');
final id = response?['dyn_id'];
RequestUtils.insertCreatedDyn(id);
if (!_isPrivate.value && _publishTime.value == null) {
if (!isPrivate && publishTime == null) {
RequestUtils.checkCreatedDyn(
id: id,
dynText: editController.rawText,

View File

@@ -1,3 +1,5 @@
import 'dart:async' show StreamSubscription;
import 'package:PiliPlus/http/dynamics.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/msg.dart';
@@ -20,11 +22,20 @@ class DynamicsTabController
int? mid;
late final MainController mainController = Get.find<MainController>();
final dynamicsController = Get.find<DynamicsController>();
StreamSubscription? _listener;
@override
void onInit() {
super.onInit();
queryData();
if (dynamicsType == .up) {
_listener = dynamicsController.mid.listen((mid) {
if (mid != -1) {
this.mid = mid;
onReload();
}
});
}
}
@override
@@ -92,4 +103,10 @@ class DynamicsTabController
@override
void onChangeAccount(bool isLogin) => onReload();
@override
void onClose() {
_listener?.cancel();
super.onClose();
}
}

View File

@@ -1,5 +1,3 @@
import 'dart:async';
import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart';
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/http/loading_state.dart';
@@ -27,8 +25,6 @@ class DynamicsTabPage extends StatefulWidget {
class _DynamicsTabPageState extends State<DynamicsTabPage>
with AutomaticKeepAliveClientMixin, DynMixin {
StreamSubscription? _listener;
DynamicsController dynamicsController = Get.putOrFind(DynamicsController.new);
late final DynamicsTabController controller;
@@ -44,21 +40,6 @@ class _DynamicsTabPageState extends State<DynamicsTabPage>
..mid = dynamicsController.mid.value,
tag: widget.dynamicsType.name,
);
if (widget.dynamicsType == .up) {
_listener = dynamicsController.mid.listen((mid) {
if (mid != -1) {
controller
..mid = mid
..onReload();
}
});
}
}
@override
void dispose() {
_listener?.cancel();
super.dispose();
}
@override

View File

@@ -50,9 +50,7 @@ class LiveRoomController extends GetxController {
int roomId = Get.arguments;
int? ruid;
DanmakuController<DanmakuExtra>? danmakuController;
final plPlayerController = PlPlayerController.getInstance(
isLive: true,
);
final plPlayerController = PlPlayerController.getInstance(isLive: true);
final isLoaded = false.obs;
final roomInfoH5 = Rxn<RoomInfoH5Data>();
@@ -89,10 +87,7 @@ class LiveRoomController extends GetxController {
}
return Text(
text,
style: const TextStyle(
fontSize: 12,
color: Colors.white,
),
style: const TextStyle(fontSize: 12, color: Colors.white),
);
});
@@ -107,6 +102,7 @@ class LiveRoomController extends GetxController {
final disableAutoScroll = false.obs;
bool autoScroll = true;
LiveMessageStream? _msgStream;
LiveMessageStream? get msgStream => _msgStream;
late final ScrollController scrollController;
late final RxInt pageIndex = 0.obs;
late final PageController pageController;
@@ -150,7 +146,7 @@ class LiveRoomController extends GetxController {
final account = Accounts.main;
isLogin = account.isLogin;
mid = account.mid;
queryLiveUrl(autoFullScreenFlag: true);
queryLiveUrl();
queryLiveInfoH5();
if (Accounts.heartbeat.isLogin && !Pref.historyPause) {
VideoHttp.roomEntryAction(roomId: roomId);
@@ -158,10 +154,7 @@ class LiveRoomController extends GetxController {
pageController = PageController();
}
Future<void>? playerInit({
bool autoplay = true,
bool autoFullScreenFlag = false,
}) {
Future<void>? playerInit({bool autoplay = true}) {
if (videoUrl == null) {
return null;
}
@@ -173,7 +166,7 @@ class LiveRoomController extends GetxController {
);
}
Future<void> queryLiveUrl({bool autoFullScreenFlag = false}) async {
Future<void> queryLiveUrl() async {
currentQn ??= await ConnectivityUtils.isWiFi
? Pref.liveQuality
: Pref.liveQualityCellular;
@@ -195,7 +188,12 @@ class LiveRoomController extends GetxController {
if (response.roomId != null) {
roomId = response.roomId!;
}
liveTime.value = response.liveTime;
final liveTime = response.liveTime;
if (liveTime != null &&
DateTime.now().millisecondsSinceEpoch ~/ 1000 - liveTime <
Duration.secondsPerDay * 2) {
this.liveTime.value = liveTime;
}
startLiveTimer();
isPortrait.value = response.isPortrait ?? false;
List<CodecItem> codec =
@@ -212,7 +210,7 @@ class LiveRoomController extends GetxController {
currentQnDesc.value =
LiveQuality.fromCode(currentQn)?.desc ?? currentQn.toString();
videoUrl = VideoUtils.getLiveCdnUrl(item);
await playerInit(autoFullScreenFlag: autoFullScreenFlag);
await playerInit();
isLoaded.value = true;
} else {
_showDialog(res.toString());
@@ -323,10 +321,6 @@ class LiveRoomController extends GetxController {
}
}
void clearSC() {
superChatMsg.removeWhere((e) => e.expired);
}
void startLiveMsg() {
if (messages.isEmpty) {
prefetch();
@@ -530,7 +524,7 @@ class LiveRoomController extends GetxController {
void onLikeTapDown([_]) {
cancelLikeTimer();
likeClickTime.value++;
likeClickTime.value += 2;
}
void onLikeTapUp([_]) {
@@ -568,19 +562,22 @@ class LiveRoomController extends GetxController {
PublishRoute(
barrierColor: Colors.transparent,
pageBuilder: (context, animation, secondaryAnimation) {
return LiveSendDmPanel(
fromEmote: fromEmote,
liveRoomController: this,
items: savedDanmaku,
autofocus: !fromEmote,
onSave: (msg) {
if (msg.isEmpty) {
savedDanmaku?.clear();
savedDanmaku = null;
} else {
savedDanmaku = msg.toList();
}
},
return Theme(
data: ThemeUtils.darkTheme,
child: LiveSendDmPanel(
fromEmote: fromEmote,
liveRoomController: this,
items: savedDanmaku,
autofocus: !fromEmote,
onSave: (msg) {
if (msg.isEmpty) {
savedDanmaku?.clear();
savedDanmaku = null;
} else {
savedDanmaku = msg.toList();
}
},
),
);
},
transitionDuration: fromEmote

View File

@@ -44,6 +44,7 @@ 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/theme_utils.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
@@ -53,6 +54,8 @@ import 'package:flutter/material.dart' hide PageView;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
const baseWhite = Color(0xFFEEEEEE);
class LiveRoomPage extends StatefulWidget {
const LiveRoomPage({super.key});
@@ -66,6 +69,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
late final LiveRoomController _liveRoomController;
late final PlPlayerController plPlayerController;
bool get isFullScreen => plPlayerController.isFullScreen.value;
final colorScheme = ThemeUtils.darkTheme.colorScheme;
late final GlobalKey pageKey = GlobalKey();
late final GlobalKey chatKey = GlobalKey();
@@ -212,7 +216,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
child: child,
);
}
return child;
return Theme(data: ThemeUtils.darkTheme, child: child);
}
Widget videoPlayerPanel(
@@ -518,28 +522,24 @@ class _LiveRoomPageState extends State<LiveRoomPage>
}
PreferredSizeWidget _buildAppBar(bool isFullScreen) {
final color = Theme.of(context).colorScheme.onSurfaceVariant;
return AppBar(
toolbarHeight: isFullScreen ? 0 : null,
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
titleTextStyle: const TextStyle(color: Colors.white),
title: isFullScreen || plPlayerController.isDesktopPip
? null
: Obx(
() {
RoomInfoH5Data? roomInfoH5 =
_liveRoomController.roomInfoH5.value;
final roomInfoH5 = _liveRoomController.roomInfoH5.value;
if (roomInfoH5 == null) {
return const SizedBox.shrink();
}
return GestureDetector(
behavior: HitTestBehavior.opaque,
behavior: .opaque,
onTap: () =>
Get.toNamed('/member?mid=${roomInfoH5.roomInfo?.uid}'),
child: Row(
spacing: 10,
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
NetworkImgLayer(
width: 34,
@@ -550,12 +550,12 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Flexible(
child: Column(
spacing: 1,
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: [
Row(
spacing: 10,
mainAxisSize: .min,
crossAxisAlignment: CrossAxisAlignment.end,
crossAxisAlignment: .end,
children: [
Flexible(
child: Text(
@@ -586,11 +586,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
},
),
actions: [
// IconButton(
// tooltip: '刷新',
// onPressed: _liveRoomController.queryLiveUrl,
// icon: const Icon(Icons.refresh, size: 20),
// ),
PopupMenuButton(
icon: const Icon(Icons.more_vert, size: 20),
itemBuilder: (BuildContext context) {
@@ -599,32 +594,24 @@ class _LiveRoomPageState extends State<LiveRoomPage>
return <PopupMenuEntry>[
PopupMenuItem(
onTap: () => Utils.copyText(liveUrl),
child: Row(
child: const Row(
spacing: 10,
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
Icon(
Icons.copy,
size: 19,
color: color,
),
const Text('复制链接'),
Icon(Icons.copy, size: 19),
Text('复制链接'),
],
),
),
if (PlatformUtils.isMobile)
PopupMenuItem(
onTap: () => ShareUtils.shareText(liveUrl),
child: Row(
child: const Row(
spacing: 10,
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
Icon(
Icons.share,
size: 19,
color: color,
),
const Text('分享直播间'),
Icon(Icons.share, size: 19),
Text('分享直播间'),
],
),
),
@@ -651,16 +638,12 @@ class _LiveRoomPageState extends State<LiveRoomPage>
SmartDialog.showToast(e.toString());
}
},
child: Row(
child: const Row(
spacing: 10,
mainAxisSize: MainAxisSize.min,
mainAxisSize: .min,
children: [
Icon(
Icons.forward_to_inbox,
size: 19,
color: color,
),
const Text('分享至消息'),
Icon(Icons.forward_to_inbox, size: 19),
Text('分享至消息'),
],
),
),
@@ -683,14 +666,14 @@ class _LiveRoomPageState extends State<LiveRoomPage>
: videoHeight;
return Padding(
padding: isFullScreen
? EdgeInsets.zero
: EdgeInsets.only(left: padding.left, right: padding.right),
? .zero
: .only(left: padding.left, right: padding.right),
child: Row(
children: [
Container(
width: width,
height: height,
margin: EdgeInsets.only(bottom: padding.bottom),
margin: .only(bottom: padding.bottom),
child: videoPlayerPanel(
isFullScreen,
fill: Colors.transparent,
@@ -712,7 +695,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
}
Widget get _buildBottomWidget => Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: [
Expanded(child: _buildChatWidget()),
_buildInputWidget,
@@ -737,7 +720,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
..onSendDanmaku(),
);
return Padding(
padding: EdgeInsets.only(bottom: 12, top: isPortrait ? 12 : 0),
padding: .only(bottom: 12, top: isPortrait ? 12 : 0),
child: PageView<CustomHorizontalDragGestureRecognizer>(
key: pageKey,
controller: _liveRoomController.pageController,
@@ -758,7 +741,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Widget get _buildInputWidget {
final child = Container(
padding: EdgeInsets.only(
padding: .only(
top: 5,
left: 10,
right: 10,
@@ -766,15 +749,15 @@ class _LiveRoomPageState extends State<LiveRoomPage>
),
height: 70 + padding.bottom,
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
borderRadius: .vertical(top: .circular(20)),
border: Border(top: BorderSide(color: Color(0x1AFFFFFF))),
color: Color(0x1AFFFFFF),
),
child: GestureDetector(
onTap: _liveRoomController.onSendDanmaku,
behavior: HitTestBehavior.opaque,
behavior: .opaque,
child: Padding(
padding: const EdgeInsets.only(top: 5, bottom: 10),
padding: const .only(top: 5, bottom: 10),
child: Align(
alignment: Alignment.topCenter,
child: Row(
@@ -788,8 +771,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
width: 34,
height: 34,
child: IconButton(
style: IconButton.styleFrom(
padding: EdgeInsets.zero,
style: const ButtonStyle(
padding: WidgetStatePropertyAll(.zero),
),
onPressed: () {
final newVal = !enableShowLiveDanmaku;
@@ -803,80 +786,74 @@ class _LiveRoomPageState extends State<LiveRoomPage>
? const Icon(
size: 22,
CustomIcons.dm_on,
color: Color(0xFFEEEEEE),
color: baseWhite,
)
: const Icon(
size: 22,
CustomIcons.dm_off,
color: Color(0xFFEEEEEE),
color: baseWhite,
),
),
);
},
),
const Expanded(
child: Text(
'发送弹幕',
style: TextStyle(color: Color(0xFFEEEEEE)),
),
child: Text('发送弹幕', style: TextStyle(color: baseWhite)),
),
Builder(
builder: (context) {
final colorScheme = Theme.of(context).colorScheme;
return Material(
type: MaterialType.transparency,
child: Stack(
clipBehavior: Clip.none,
children: [
InkWell(
overlayColor: overlayColor(colorScheme),
customBorder: const CircleBorder(),
onTapDown: _liveRoomController.onLikeTapDown,
onTapUp: _liveRoomController.onLikeTapUp,
onTapCancel: _liveRoomController.onLikeTapUp,
child: const SizedBox.square(
dimension: 34,
child: Icon(
size: 22,
color: Color(0xFFEEEEEE),
Icons.thumb_up_off_alt,
),
),
Material(
type: .transparency,
child: Stack(
clipBehavior: .none,
children: [
InkWell(
overlayColor: overlayColor(colorScheme),
customBorder: const CircleBorder(),
onTapDown: _liveRoomController.onLikeTapDown,
onTapUp: _liveRoomController.onLikeTapUp,
onTapCancel: _liveRoomController.onLikeTapUp,
child: const SizedBox.square(
dimension: 34,
child: Icon(
size: 22,
color: baseWhite,
Icons.thumb_up_off_alt,
),
Positioned(
left: 30,
top: -12,
child: Obx(() {
final likeClickTime =
_liveRoomController.likeClickTime.value;
if (likeClickTime == 0) {
return const SizedBox.shrink();
}
return Text(
'x$likeClickTime',
style: TextStyle(
fontSize: 16,
color: colorScheme.isDark
? colorScheme.primary
: colorScheme.inversePrimary,
),
);
}),
),
],
),
),
);
},
Positioned(
left: 30,
top: -12,
child: Obx(() {
final likeClickTime =
_liveRoomController.likeClickTime.value;
if (likeClickTime == 0) {
return const SizedBox.shrink();
}
return Text(
'x$likeClickTime',
style: TextStyle(
fontSize: 16,
color: colorScheme.isDark
? colorScheme.primary
: colorScheme.inversePrimary,
),
);
}),
),
],
),
),
SizedBox(
width: 34,
height: 34,
child: IconButton(
style: IconButton.styleFrom(padding: EdgeInsets.zero),
style: const ButtonStyle(
padding: WidgetStatePropertyAll(.zero),
),
onPressed: () => _liveRoomController.onSendDanmaku(true),
icon: const Icon(
size: 22,
color: Color(0xFFEEEEEE),
color: baseWhite,
Icons.emoji_emotions_outlined,
),
),
@@ -888,6 +865,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
),
);
return Stack(
clipBehavior: .none,
children: [
child,
Positioned(
@@ -896,11 +874,21 @@ class _LiveRoomPageState extends State<LiveRoomPage>
right: 0,
child: Obx(
() => _BorderIndicator(
radius: const Radius.circular(20),
radius: const .circular(20),
isLeft: _liveRoomController.pageIndex.value == 0,
),
),
),
Positioned(
top: -6,
right: 6,
child: Obx(
() => Badge.count(
isLabelVisible: _liveRoomController.superChatMsg.isNotEmpty,
count: _liveRoomController.superChatMsg.length,
),
),
),
],
);
}
@@ -1001,7 +989,7 @@ class _RenderBorderIndicator extends RenderBox {
width,
size.height,
),
borderRadius: BorderRadius.only(
borderRadius: .only(
topLeft: _isLeft ? _radius : .zero,
topRight: _isLeft ? .zero : _radius,
),

View File

@@ -164,53 +164,6 @@ class LiveRoomChatPanel extends StatelessWidget {
),
),
],
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(
@@ -225,6 +178,38 @@ class LiveRoomChatPanel extends StatelessWidget {
)
: const SizedBox.shrink(),
),
Positioned(
top: 0,
right: 12,
width: 32,
height: 32,
child: PopupMenuButton(
iconSize: 19,
padding: .zero,
itemBuilder: (context) => [
if (liveRoomController.msgStream != null)
PopupMenuItem(
height: 35,
onTap: liveRoomController.closeLiveMsg,
child: const Text('Pause'),
)
else
PopupMenuItem(
height: 35,
onTap: liveRoomController.startLiveMsg,
child: const Text('Resume'),
),
PopupMenuItem(
height: 35,
onTap: () => liveRoomController
..danmakuController?.clear()
..messages.clear()
..disableAutoScroll.value = false,
child: const Text('Clear'),
),
],
),
),
],
);
}
@@ -274,10 +259,7 @@ class LiveRoomChatPanel extends StatelessWidget {
spanChildren.add(
TextSpan(
text: nonMatchStr,
style: const TextStyle(
color: Colors.white,
fontSize: 14,
),
style: const TextStyle(color: Colors.white, fontSize: 14),
),
);
return '';
@@ -287,10 +269,7 @@ class LiveRoomChatPanel extends StatelessWidget {
} else {
return TextSpan(
text: obj.text,
style: const TextStyle(
color: Colors.white,
fontSize: 14,
),
style: const TextStyle(color: Colors.white, fontSize: 14),
);
}
}

View File

@@ -669,11 +669,9 @@ class VideoDetailController extends GetxController
playerInit();
}
Future<void>? _initPlayerIfNeeded(bool autoFullScreenFlag) {
Future<void>? _initPlayerIfNeeded() {
if (_autoPlay.value) {
return playerInit(
autoFullScreenFlag: autoFullScreenFlag && _autoPlay.value,
);
return playerInit();
}
return null;
}
@@ -685,7 +683,6 @@ class VideoDetailController extends GetxController
Duration? duration,
bool? autoplay,
Volume? volume,
bool autoFullScreenFlag = false,
}) async {
Duration? seek = seekToTime ?? defaultST ?? playedTime;
if (seek == null || seek == Duration.zero) {
@@ -762,10 +759,9 @@ class VideoDetailController extends GetxController
Future<void> queryVideoUrl({
Duration? defaultST,
bool fromReset = false,
bool autoFullScreenFlag = false,
}) async {
if (isFileSource) {
return _initPlayerIfNeeded(autoFullScreenFlag);
return _initPlayerIfNeeded();
}
if (isQuerying) {
return;
@@ -839,7 +835,7 @@ class VideoDetailController extends GetxController
_setVideoHeight();
currentDecodeFormats = VideoDecodeFormatType.fromString('avc1');
currentVideoQa.value = videoQuality;
await _initPlayerIfNeeded(autoFullScreenFlag);
await _initPlayerIfNeeded();
isQuerying = false;
return;
}
@@ -938,7 +934,7 @@ class VideoDetailController extends GetxController
} else {
audioUrl = '';
}
await _initPlayerIfNeeded(autoFullScreenFlag);
await _initPlayerIfNeeded();
} else {
_autoPlay.value = false;
videoState.value = false;

View File

@@ -153,7 +153,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
// 获取视频资源,初始化播放器
void videoSourceInit() {
videoDetailController.queryVideoUrl(autoFullScreenFlag: true);
videoDetailController.queryVideoUrl();
if (videoDetailController.autoPlay) {
plPlayerController = videoDetailController.plPlayerController;
plPlayerController!
@@ -284,10 +284,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
plPlayerController
..addStatusLister(playerListener)
..addPositionListener(positionListener);
return videoDetailController.playerInit(
autoplay: true,
autoFullScreenFlag: true,
);
return videoDetailController.playerInit(autoplay: true);
}
@override