mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-24 20:35:50 +08:00
feat: send live emote
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -4,7 +4,6 @@ import 'package:PiliPlus/http/video.dart';
|
||||
import 'package:PiliPlus/models/live/danmu_info.dart';
|
||||
import 'package:PiliPlus/models/live/quality.dart';
|
||||
import 'package:PiliPlus/pages/mine/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/widgets/send_danmaku_panel.dart';
|
||||
import 'package:PiliPlus/services/service_locator.dart';
|
||||
import 'package:PiliPlus/tcp/live.dart';
|
||||
import 'package:PiliPlus/utils/danmaku.dart';
|
||||
@@ -13,13 +12,11 @@ import 'package:canvas_danmaku/canvas_danmaku.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/http/constants.dart';
|
||||
import 'package:PiliPlus/http/live.dart';
|
||||
import 'package:PiliPlus/models/live/room_info.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/index.dart';
|
||||
import 'package:get/get_navigation/src/dialog/dialog_route.dart';
|
||||
import '../../models/live/room_info_h5.dart';
|
||||
import '../../utils/video_utils.dart';
|
||||
|
||||
@@ -248,41 +245,4 @@ class LiveRoomController extends GetxController {
|
||||
.description;
|
||||
await queryLiveInfo();
|
||||
}
|
||||
|
||||
void onSendDanmaku() {
|
||||
if (!isLogin) {
|
||||
SmartDialog.showToast('未登录');
|
||||
return;
|
||||
}
|
||||
Navigator.of(Get.context!).push(
|
||||
GetDialogRoute(
|
||||
pageBuilder: (buildContext, animation, secondaryAnimation) {
|
||||
return SendDanmakuPanel(
|
||||
roomId: roomId,
|
||||
initialValue: savedDanmaku,
|
||||
onSave: (danmaku) => savedDanmaku = danmaku,
|
||||
callback: (danmakuModel) {
|
||||
savedDanmaku = null;
|
||||
plPlayerController.danmakuController?.addDanmaku(danmakuModel);
|
||||
},
|
||||
darkVideoPage: false,
|
||||
);
|
||||
},
|
||||
transitionDuration: const Duration(milliseconds: 500),
|
||||
transitionBuilder: (context, animation, secondaryAnimation, child) {
|
||||
const begin = Offset(0.0, 1.0);
|
||||
const end = Offset.zero;
|
||||
const curve = Curves.linear;
|
||||
|
||||
var tween =
|
||||
Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
|
||||
|
||||
return SlideTransition(
|
||||
position: animation.drive(tween),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
247
lib/pages/live_room/send_dm_panel.dart
Normal file
247
lib/pages/live_room/send_dm_panel.dart
Normal file
@@ -0,0 +1,247 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:PiliPlus/http/live.dart';
|
||||
import 'package:PiliPlus/pages/common/common_publish_page.dart';
|
||||
import 'package:PiliPlus/pages/live_emote/controller.dart';
|
||||
import 'package:PiliPlus/pages/live_emote/view.dart';
|
||||
import 'package:PiliPlus/pages/live_room/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/reply_new/toolbar_icon_button.dart';
|
||||
import 'package:canvas_danmaku/models/danmaku_content_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart' hide MultipartFile;
|
||||
|
||||
class LiveSendDmPanel extends CommonPublishPage {
|
||||
final bool fromEmote;
|
||||
final LiveRoomController liveRoomController;
|
||||
|
||||
const LiveSendDmPanel({
|
||||
super.key,
|
||||
super.initialValue,
|
||||
super.onSave,
|
||||
this.fromEmote = false,
|
||||
required this.liveRoomController,
|
||||
});
|
||||
|
||||
@override
|
||||
State<LiveSendDmPanel> createState() => _ReplyPageState();
|
||||
}
|
||||
|
||||
class _ReplyPageState extends CommonPublishPageState<LiveSendDmPanel> {
|
||||
LiveRoomController get liveRoomController => widget.liveRoomController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.fromEmote) {
|
||||
selectKeyboard.value = false;
|
||||
updatePanelType(PanelType.emoji);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
Get.delete<LiveEmotePanelController>(
|
||||
tag: liveRoomController.roomId.toString());
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MediaQuery.removePadding(
|
||||
removeTop: true,
|
||||
context: context,
|
||||
child: GestureDetector(
|
||||
onTap: Get.back,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
bool isH = constraints.maxWidth > constraints.maxHeight;
|
||||
late double padding = constraints.maxWidth * 0.12;
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: isH ? padding : 0),
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
body: GestureDetector(
|
||||
onTap: () {},
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
buildInputView(),
|
||||
buildPanelContainer(
|
||||
Theme.of(context).colorScheme.surface),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget? customPanel(double height) => SizedBox(
|
||||
height: height,
|
||||
child: LiveEmotePanel(
|
||||
onChoose: onChooseEmote,
|
||||
roomId: liveRoomController.roomId,
|
||||
onSendEmoticonUnique: (emote) {
|
||||
onCustomPublish(
|
||||
message: emote.emoticonUnique!,
|
||||
dmType: 1,
|
||||
emoticonOptions: '[object Object]',
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
Widget buildInputView() {
|
||||
return Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(12),
|
||||
topRight: Radius.circular(12),
|
||||
),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 12, right: 15, left: 15, bottom: 10),
|
||||
child: Form(
|
||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||
child: Listener(
|
||||
onPointerUp: (event) {
|
||||
if (readOnly.value) {
|
||||
updatePanelType(PanelType.keyboard);
|
||||
selectKeyboard.value = true;
|
||||
}
|
||||
},
|
||||
child: Obx(
|
||||
() => TextField(
|
||||
controller: editController,
|
||||
minLines: 1,
|
||||
maxLines: 2,
|
||||
autofocus: false,
|
||||
readOnly: readOnly.value,
|
||||
onChanged: (value) {
|
||||
bool isEmpty = value.trim().isEmpty;
|
||||
if (!isEmpty && !enablePublish.value) {
|
||||
enablePublish.value = true;
|
||||
} else if (isEmpty && enablePublish.value) {
|
||||
enablePublish.value = false;
|
||||
}
|
||||
liveRoomController.savedDanmaku = value;
|
||||
},
|
||||
focusNode: focusNode,
|
||||
decoration: InputDecoration(
|
||||
hintText: "输入弹幕内容",
|
||||
border: InputBorder.none,
|
||||
hintStyle: TextStyle(fontSize: 14)),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
inputFormatters: [LengthLimitingTextInputFormatter(20)],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
height: 1,
|
||||
color: Theme.of(context).dividerColor.withOpacity(0.1),
|
||||
),
|
||||
Container(
|
||||
height: 52,
|
||||
padding: const EdgeInsets.only(left: 12, right: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Obx(
|
||||
() => ToolbarIconButton(
|
||||
tooltip: '输入',
|
||||
onPressed: () {
|
||||
if (!selectKeyboard.value) {
|
||||
selectKeyboard.value = true;
|
||||
updatePanelType(PanelType.keyboard);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.keyboard, size: 22),
|
||||
selected: selectKeyboard.value,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Obx(
|
||||
() => ToolbarIconButton(
|
||||
tooltip: '表情',
|
||||
onPressed: () {
|
||||
if (selectKeyboard.value) {
|
||||
selectKeyboard.value = false;
|
||||
updatePanelType(PanelType.emoji);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.emoji_emotions, size: 22),
|
||||
selected: !selectKeyboard.value,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Obx(
|
||||
() => FilledButton.tonal(
|
||||
onPressed: enablePublish.value ? onPublish : null,
|
||||
style: FilledButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20, vertical: 10),
|
||||
visualDensity: const VisualDensity(
|
||||
horizontal: -2,
|
||||
vertical: -2,
|
||||
),
|
||||
),
|
||||
child: const Text('发送'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future onCustomPublish({
|
||||
required String message,
|
||||
List? pictures,
|
||||
int? dmType,
|
||||
emoticonOptions,
|
||||
}) async {
|
||||
if (!liveRoomController.isLogin) {
|
||||
SmartDialog.showToast('未登录');
|
||||
return;
|
||||
}
|
||||
final res = await LiveHttp.sendLiveMsg(
|
||||
roomId: liveRoomController.roomId,
|
||||
msg: message,
|
||||
dmType: dmType,
|
||||
emoticonOptions: emoticonOptions,
|
||||
);
|
||||
if (res['status']) {
|
||||
Get.back();
|
||||
liveRoomController.savedDanmaku = null;
|
||||
SmartDialog.showToast('发送成功');
|
||||
liveRoomController.plPlayerController.danmakuController?.addDanmaku(
|
||||
DanmakuContentItem(
|
||||
message,
|
||||
type: DanmakuItemType.scroll,
|
||||
selfSend: true,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:PiliPlus/http/live.dart';
|
||||
import 'package:PiliPlus/pages/live_room/send_dm_panel.dart';
|
||||
import 'package:PiliPlus/pages/live_room/widgets/chat.dart';
|
||||
import 'package:PiliPlus/pages/live_room/widgets/header_control.dart';
|
||||
import 'package:PiliPlus/services/service_locator.dart';
|
||||
@@ -13,7 +13,6 @@ import 'package:canvas_danmaku/canvas_danmaku.dart';
|
||||
import 'package:floating/floating.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPlus/common/widgets/network_img_layer.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/index.dart';
|
||||
@@ -44,8 +43,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
bool isPlay = true;
|
||||
Floating? floating;
|
||||
|
||||
late final _node = FocusNode();
|
||||
late final _ctr = TextEditingController();
|
||||
StreamSubscription? _listener;
|
||||
|
||||
int latestAddedPosition = -1;
|
||||
@@ -128,10 +125,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
PlPlayerController.setPlayCallBack(null);
|
||||
_liveRoomController.msgStream?.close();
|
||||
// floating?.dispose();
|
||||
_node.dispose();
|
||||
plPlayerController.removeStatusLister(playerListener);
|
||||
plPlayerController.dispose();
|
||||
_ctr.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -157,66 +152,60 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
plPlayerController.triggerFullScreen(status: false);
|
||||
}
|
||||
},
|
||||
child: Listener(
|
||||
onPointerDown: (_) {
|
||||
_node.unfocus();
|
||||
},
|
||||
child: FutureBuilder(
|
||||
key: videoPlayerKey,
|
||||
future: _futureBuilderFuture,
|
||||
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||
if (snapshot.hasData && snapshot.data['status']) {
|
||||
return PLVideoPlayer(
|
||||
key: playerKey,
|
||||
fill: fill,
|
||||
alignment: alignment,
|
||||
child: FutureBuilder(
|
||||
key: videoPlayerKey,
|
||||
future: _futureBuilderFuture,
|
||||
builder: (BuildContext context, AsyncSnapshot snapshot) {
|
||||
if (snapshot.hasData && snapshot.data['status']) {
|
||||
return PLVideoPlayer(
|
||||
key: playerKey,
|
||||
fill: fill,
|
||||
alignment: alignment,
|
||||
plPlayerController: plPlayerController,
|
||||
headerControl: LiveHeaderControl(
|
||||
plPlayerController: plPlayerController,
|
||||
headerControl: LiveHeaderControl(
|
||||
plPlayerController: plPlayerController,
|
||||
floating: floating,
|
||||
onSendDanmaku: _liveRoomController.onSendDanmaku,
|
||||
),
|
||||
bottomControl: BottomControl(
|
||||
plPlayerController: plPlayerController,
|
||||
liveRoomCtr: _liveRoomController,
|
||||
onRefresh: () {
|
||||
_futureBuilderFuture = _liveRoomController.queryLiveInfo();
|
||||
},
|
||||
),
|
||||
danmuWidget: Obx(
|
||||
() => AnimatedOpacity(
|
||||
opacity: plPlayerController.isOpenDanmu.value ? 1 : 0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: DanmakuScreen(
|
||||
createdController: (DanmakuController e) {
|
||||
plPlayerController.danmakuController =
|
||||
_liveRoomController.controller = e;
|
||||
},
|
||||
option: DanmakuOption(
|
||||
fontSize: _getFontSize(isFullScreen),
|
||||
fontWeight: plPlayerController.fontWeight,
|
||||
area: plPlayerController.showArea,
|
||||
opacity: plPlayerController.opacity,
|
||||
hideTop: plPlayerController.blockTypes.contains(5),
|
||||
hideScroll: plPlayerController.blockTypes.contains(2),
|
||||
hideBottom: plPlayerController.blockTypes.contains(4),
|
||||
duration: plPlayerController.danmakuDuration /
|
||||
plPlayerController.playbackSpeed,
|
||||
staticDuration:
|
||||
plPlayerController.danmakuStaticDuration /
|
||||
plPlayerController.playbackSpeed,
|
||||
strokeWidth: plPlayerController.strokeWidth,
|
||||
lineHeight: plPlayerController.danmakuLineHeight,
|
||||
),
|
||||
floating: floating,
|
||||
onSendDanmaku: onSendDanmaku,
|
||||
),
|
||||
bottomControl: BottomControl(
|
||||
plPlayerController: plPlayerController,
|
||||
liveRoomCtr: _liveRoomController,
|
||||
onRefresh: () {
|
||||
_futureBuilderFuture = _liveRoomController.queryLiveInfo();
|
||||
},
|
||||
),
|
||||
danmuWidget: Obx(
|
||||
() => AnimatedOpacity(
|
||||
opacity: plPlayerController.isOpenDanmu.value ? 1 : 0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: DanmakuScreen(
|
||||
createdController: (DanmakuController e) {
|
||||
plPlayerController.danmakuController =
|
||||
_liveRoomController.controller = e;
|
||||
},
|
||||
option: DanmakuOption(
|
||||
fontSize: _getFontSize(isFullScreen),
|
||||
fontWeight: plPlayerController.fontWeight,
|
||||
area: plPlayerController.showArea,
|
||||
opacity: plPlayerController.opacity,
|
||||
hideTop: plPlayerController.blockTypes.contains(5),
|
||||
hideScroll: plPlayerController.blockTypes.contains(2),
|
||||
hideBottom: plPlayerController.blockTypes.contains(4),
|
||||
duration: plPlayerController.danmakuDuration /
|
||||
plPlayerController.playbackSpeed,
|
||||
staticDuration: plPlayerController.danmakuStaticDuration /
|
||||
plPlayerController.playbackSpeed,
|
||||
strokeWidth: plPlayerController.strokeWidth,
|
||||
lineHeight: plPlayerController.danmakuLineHeight,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -361,7 +350,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
);
|
||||
}
|
||||
|
||||
Color get _color => Color(0xFFEEEEEE);
|
||||
final Color _color = Color(0xFFEEEEEE);
|
||||
|
||||
PreferredSizeWidget get _buildAppBar => AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
@@ -381,7 +370,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
_node.unfocus();
|
||||
dynamic uid =
|
||||
_liveRoomController.roomInfoH5.value.roomInfo?.uid;
|
||||
Get.toNamed(
|
||||
@@ -481,15 +469,12 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: SafeArea(
|
||||
left: false,
|
||||
top: false,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: _buildBottomWidget,
|
||||
),
|
||||
child: SafeArea(
|
||||
left: false,
|
||||
top: false,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: _buildBottomWidget,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -517,18 +502,13 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
_buildInputWidget,
|
||||
];
|
||||
|
||||
Widget _buildChatWidget([bool? isPP]) => Listener(
|
||||
onPointerDown: (_) {
|
||||
_node.unfocus();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: LiveRoomChat(
|
||||
key: chatKey,
|
||||
isPP: isPP,
|
||||
roomId: _roomId,
|
||||
liveRoomController: _liveRoomController,
|
||||
),
|
||||
Widget _buildChatWidget([bool? isPP]) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: LiveRoomChat(
|
||||
key: chatKey,
|
||||
isPP: isPP,
|
||||
roomId: _roomId,
|
||||
liveRoomController: _liveRoomController,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -568,60 +548,43 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
focusNode: _node,
|
||||
controller: _ctr,
|
||||
textInputAction: TextInputAction.send,
|
||||
cursorColor: _color,
|
||||
style: TextStyle(color: _color),
|
||||
onSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
_onSendMsg(value);
|
||||
}
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: '发送弹幕',
|
||||
hintStyle: TextStyle(
|
||||
color: Colors.white.withOpacity(0.6),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: onSendDanmaku,
|
||||
child: Text(
|
||||
'发送弹幕',
|
||||
style: TextStyle(color: _color),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
if (_ctr.text.isNotEmpty) {
|
||||
_onSendMsg(_ctr.text);
|
||||
}
|
||||
onSendDanmaku(true);
|
||||
},
|
||||
icon: Icon(Icons.send, color: _color),
|
||||
icon: Icon(Icons.emoji_emotions_outlined, color: _color),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
void _onSendMsg(msg) async {
|
||||
if (!_liveRoomController.isLogin) {
|
||||
SmartDialog.showToast('未登录');
|
||||
return;
|
||||
}
|
||||
dynamic res = await LiveHttp.sendLiveMsg(
|
||||
roomId: _liveRoomController.roomId, msg: msg);
|
||||
if (res['status']) {
|
||||
if (mounted) {
|
||||
FocusScope.of(context).unfocus();
|
||||
}
|
||||
SmartDialog.showToast('发送成功');
|
||||
plPlayerController.danmakuController?.addDanmaku(
|
||||
DanmakuContentItem(
|
||||
_ctr.text,
|
||||
type: DanmakuItemType.scroll,
|
||||
selfSend: true,
|
||||
),
|
||||
);
|
||||
_ctr.clear();
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
}
|
||||
void onSendDanmaku([bool fromEmote = false]) {
|
||||
Get.generalDialog(
|
||||
pageBuilder: (context, animation, secondaryAnimation) {
|
||||
return LiveSendDmPanel(
|
||||
fromEmote: fromEmote,
|
||||
liveRoomController: _liveRoomController,
|
||||
initialValue: _liveRoomController.savedDanmaku,
|
||||
onSave: (msg) => _liveRoomController.savedDanmaku = msg,
|
||||
);
|
||||
},
|
||||
transitionDuration: const Duration(milliseconds: 500),
|
||||
transitionBuilder: (context, animation, secondaryAnimation, child) {
|
||||
var tween = Tween(begin: Offset(0.0, 1.0), end: Offset.zero)
|
||||
.chain(CurveTween(curve: Curves.linear));
|
||||
return SlideTransition(
|
||||
position: animation.drive(tween),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user