| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  | import 'package:auto_size_text/auto_size_text.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							|  |  |  | import 'package:flutter_hbb/common.dart'; | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  | import 'package:get/get.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 23:05:11 +08:00
										 |  |  | import 'package:provider/provider.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-26 21:13:32 +09:00
										 |  |  | import '../../consts.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  | import '../../desktop/widgets/tabbar_widget.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-11 10:19:12 +08:00
										 |  |  | import '../../models/chat_model.dart'; | 
					
						
							| 
									
										
										
										
											2022-09-27 23:05:11 +08:00
										 |  |  | import '../../models/model.dart'; | 
					
						
							| 
									
										
										
										
											2022-10-25 21:36:01 +09:00
										 |  |  | import 'chat_page.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class DraggableChatWindow extends StatelessWidget { | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |   const DraggableChatWindow( | 
					
						
							|  |  |  |       {Key? key, | 
					
						
							|  |  |  |       this.position = Offset.zero, | 
					
						
							| 
									
										
										
										
											2022-08-11 10:19:12 +08:00
										 |  |  |       required this.width, | 
					
						
							|  |  |  |       required this.height, | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |       required this.chatModel}) | 
					
						
							|  |  |  |       : super(key: key); | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   final Offset position; | 
					
						
							|  |  |  |   final double width; | 
					
						
							|  |  |  |   final double height; | 
					
						
							| 
									
										
										
										
											2022-08-11 10:19:12 +08:00
										 |  |  |   final ChatModel chatModel; | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return Draggable( | 
					
						
							|  |  |  |         checkKeyboard: true, | 
					
						
							|  |  |  |         position: position, | 
					
						
							|  |  |  |         width: width, | 
					
						
							|  |  |  |         height: height, | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |         builder: (context, onPanUpdate) { | 
					
						
							| 
									
										
										
										
											2023-07-09 10:35:10 +08:00
										 |  |  |           final child = isIOS | 
					
						
							| 
									
										
										
										
											2022-08-11 10:19:12 +08:00
										 |  |  |               ? ChatPage(chatModel: chatModel) | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |               : Scaffold( | 
					
						
							|  |  |  |                   resizeToAvoidBottomInset: false, | 
					
						
							|  |  |  |                   appBar: CustomAppBar( | 
					
						
							|  |  |  |                     onPanUpdate: onPanUpdate, | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |                     appBar: isDesktop | 
					
						
							| 
									
										
										
										
											2022-10-14 23:50:13 +09:00
										 |  |  |                         ? _buildDesktopAppBar(context) | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |                         : _buildMobileAppBar(context), | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |                   ), | 
					
						
							| 
									
										
										
										
											2022-08-11 10:19:12 +08:00
										 |  |  |                   body: ChatPage(chatModel: chatModel), | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2023-07-09 10:35:10 +08:00
										 |  |  |           return Container( | 
					
						
							|  |  |  |               decoration: | 
					
						
							|  |  |  |                   BoxDecoration(border: Border.all(color: MyTheme.border)), | 
					
						
							|  |  |  |               child: child); | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |   Widget _buildMobileAppBar(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |     return Container( | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |       color: Theme.of(context).colorScheme.primary, | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |       height: 50, | 
					
						
							|  |  |  |       child: Row( | 
					
						
							|  |  |  |         mainAxisAlignment: MainAxisAlignment.spaceBetween, | 
					
						
							|  |  |  |         children: [ | 
					
						
							|  |  |  |           Padding( | 
					
						
							|  |  |  |               padding: const EdgeInsets.symmetric(horizontal: 15), | 
					
						
							|  |  |  |               child: Text( | 
					
						
							|  |  |  |                 translate("Chat"), | 
					
						
							|  |  |  |                 style: const TextStyle( | 
					
						
							|  |  |  |                     color: Colors.white, | 
					
						
							|  |  |  |                     fontFamily: 'WorkSans', | 
					
						
							|  |  |  |                     fontWeight: FontWeight.bold, | 
					
						
							|  |  |  |                     fontSize: 20), | 
					
						
							|  |  |  |               )), | 
					
						
							|  |  |  |           Row( | 
					
						
							|  |  |  |             crossAxisAlignment: CrossAxisAlignment.center, | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               IconButton( | 
					
						
							|  |  |  |                   onPressed: () { | 
					
						
							|  |  |  |                     chatModel.hideChatWindowOverlay(); | 
					
						
							|  |  |  |                   }, | 
					
						
							| 
									
										
										
										
											2023-05-29 09:44:38 +08:00
										 |  |  |                   icon: const Icon( | 
					
						
							|  |  |  |                     Icons.keyboard_arrow_down, | 
					
						
							|  |  |  |                     color: Colors.white, | 
					
						
							|  |  |  |                   )), | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |               IconButton( | 
					
						
							|  |  |  |                   onPressed: () { | 
					
						
							|  |  |  |                     chatModel.hideChatWindowOverlay(); | 
					
						
							|  |  |  |                     chatModel.hideChatIconOverlay(); | 
					
						
							|  |  |  |                   }, | 
					
						
							| 
									
										
										
										
											2023-05-29 09:44:38 +08:00
										 |  |  |                   icon: const Icon( | 
					
						
							|  |  |  |                     Icons.close, | 
					
						
							|  |  |  |                     color: Colors.white, | 
					
						
							|  |  |  |                   )) | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |             ], | 
					
						
							|  |  |  |           ) | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-14 23:50:13 +09:00
										 |  |  |   Widget _buildDesktopAppBar(BuildContext context) { | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |     return Container( | 
					
						
							| 
									
										
										
										
											2022-10-14 23:50:13 +09:00
										 |  |  |       decoration: BoxDecoration( | 
					
						
							|  |  |  |           border: Border( | 
					
						
							|  |  |  |               bottom: BorderSide( | 
					
						
							|  |  |  |                   color: Theme.of(context).hintColor.withOpacity(0.4)))), | 
					
						
							|  |  |  |       height: 38, | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  |       child: Row( | 
					
						
							|  |  |  |         mainAxisAlignment: MainAxisAlignment.spaceBetween, | 
					
						
							|  |  |  |         children: [ | 
					
						
							|  |  |  |           Padding( | 
					
						
							|  |  |  |               padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), | 
					
						
							|  |  |  |               child: Obx(() => Opacity( | 
					
						
							|  |  |  |                   opacity: chatModel.isWindowFocus.value ? 1.0 : 0.4, | 
					
						
							| 
									
										
										
										
											2023-02-06 09:54:21 +09:00
										 |  |  |                   child: Row(children: [ | 
					
						
							|  |  |  |                     Icon(Icons.chat_bubble_outline, | 
					
						
							|  |  |  |                         size: 20, color: Theme.of(context).colorScheme.primary), | 
					
						
							|  |  |  |                     SizedBox(width: 6), | 
					
						
							|  |  |  |                     Text(translate("Chat")) | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  |                   ])))), | 
					
						
							|  |  |  |           Padding( | 
					
						
							|  |  |  |               padding: EdgeInsets.all(2), | 
					
						
							|  |  |  |               child: ActionIcon( | 
					
						
							|  |  |  |                 message: 'Close', | 
					
						
							|  |  |  |                 icon: IconFont.close, | 
					
						
							|  |  |  |                 onTap: chatModel.hideChatWindowOverlay, | 
					
						
							|  |  |  |                 isClose: true, | 
					
						
							|  |  |  |                 boxSize: 32, | 
					
						
							|  |  |  |               )) | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       ), | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { | 
					
						
							|  |  |  |   final GestureDragUpdateCallback onPanUpdate; | 
					
						
							|  |  |  |   final Widget appBar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const CustomAppBar( | 
					
						
							|  |  |  |       {Key? key, required this.onPanUpdate, required this.appBar}) | 
					
						
							|  |  |  |       : super(key: key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return GestureDetector(onPanUpdate: onPanUpdate, child: appBar); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |   Size get preferredSize => const Size.fromHeight(kToolbarHeight); | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// floating buttons of back/home/recent actions for android
 | 
					
						
							|  |  |  | class DraggableMobileActions extends StatelessWidget { | 
					
						
							|  |  |  |   DraggableMobileActions( | 
					
						
							|  |  |  |       {this.position = Offset.zero, | 
					
						
							|  |  |  |       this.onBackPressed, | 
					
						
							|  |  |  |       this.onRecentPressed, | 
					
						
							|  |  |  |       this.onHomePressed, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |       this.onHidePressed, | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |       required this.width, | 
					
						
							|  |  |  |       required this.height}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   final Offset position; | 
					
						
							|  |  |  |   final double width; | 
					
						
							|  |  |  |   final double height; | 
					
						
							|  |  |  |   final VoidCallback? onBackPressed; | 
					
						
							|  |  |  |   final VoidCallback? onHomePressed; | 
					
						
							|  |  |  |   final VoidCallback? onRecentPressed; | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |   final VoidCallback? onHidePressed; | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     return Draggable( | 
					
						
							|  |  |  |         position: position, | 
					
						
							|  |  |  |         width: width, | 
					
						
							|  |  |  |         height: height, | 
					
						
							|  |  |  |         builder: (_, onPanUpdate) { | 
					
						
							|  |  |  |           return GestureDetector( | 
					
						
							|  |  |  |               onPanUpdate: onPanUpdate, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |               child: Card( | 
					
						
							|  |  |  |                   color: Colors.transparent, | 
					
						
							|  |  |  |                   shadowColor: Colors.transparent, | 
					
						
							|  |  |  |                   child: Container( | 
					
						
							|  |  |  |                     decoration: BoxDecoration( | 
					
						
							|  |  |  |                         color: MyTheme.accent.withOpacity(0.4), | 
					
						
							|  |  |  |                         borderRadius: BorderRadius.all(Radius.circular(15))), | 
					
						
							|  |  |  |                     child: Row( | 
					
						
							|  |  |  |                       mainAxisAlignment: MainAxisAlignment.spaceAround, | 
					
						
							|  |  |  |                       children: [ | 
					
						
							|  |  |  |                         IconButton( | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |                             color: Colors.white, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             onPressed: onBackPressed, | 
					
						
							| 
									
										
										
										
											2022-10-26 21:13:32 +09:00
										 |  |  |                             splashRadius: kDesktopIconButtonSplashRadius, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             icon: const Icon(Icons.arrow_back)), | 
					
						
							|  |  |  |                         IconButton( | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |                             color: Colors.white, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             onPressed: onHomePressed, | 
					
						
							| 
									
										
										
										
											2022-10-26 21:13:32 +09:00
										 |  |  |                             splashRadius: kDesktopIconButtonSplashRadius, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             icon: const Icon(Icons.home)), | 
					
						
							|  |  |  |                         IconButton( | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |                             color: Colors.white, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             onPressed: onRecentPressed, | 
					
						
							| 
									
										
										
										
											2022-10-26 21:13:32 +09:00
										 |  |  |                             splashRadius: kDesktopIconButtonSplashRadius, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             icon: const Icon(Icons.more_horiz)), | 
					
						
							|  |  |  |                         const VerticalDivider( | 
					
						
							|  |  |  |                           width: 0, | 
					
						
							|  |  |  |                           thickness: 2, | 
					
						
							|  |  |  |                           indent: 10, | 
					
						
							|  |  |  |                           endIndent: 10, | 
					
						
							|  |  |  |                         ), | 
					
						
							|  |  |  |                         IconButton( | 
					
						
							| 
									
										
										
										
											2022-09-23 16:31:50 +08:00
										 |  |  |                             color: Colors.white, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             onPressed: onHidePressed, | 
					
						
							| 
									
										
										
										
											2022-10-26 21:13:32 +09:00
										 |  |  |                             splashRadius: kDesktopIconButtonSplashRadius, | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                             icon: const Icon(Icons.keyboard_arrow_down)), | 
					
						
							|  |  |  |                       ], | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |                     ), | 
					
						
							| 
									
										
										
										
											2022-09-08 22:18:02 +08:00
										 |  |  |                   ))); | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Draggable extends StatefulWidget { | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |   const Draggable( | 
					
						
							|  |  |  |       {Key? key, | 
					
						
							|  |  |  |       this.checkKeyboard = false, | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |       this.checkScreenSize = false, | 
					
						
							|  |  |  |       this.position = Offset.zero, | 
					
						
							|  |  |  |       required this.width, | 
					
						
							|  |  |  |       required this.height, | 
					
						
							| 
									
										
										
										
											2022-09-13 09:29:19 +08:00
										 |  |  |       required this.builder}) | 
					
						
							|  |  |  |       : super(key: key); | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   final bool checkKeyboard; | 
					
						
							|  |  |  |   final bool checkScreenSize; | 
					
						
							|  |  |  |   final Offset position; | 
					
						
							|  |  |  |   final double width; | 
					
						
							|  |  |  |   final double height; | 
					
						
							|  |  |  |   final Widget Function(BuildContext, GestureDragUpdateCallback) builder; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   State<StatefulWidget> createState() => _DraggableState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class _DraggableState extends State<Draggable> { | 
					
						
							|  |  |  |   late Offset _position; | 
					
						
							|  |  |  |   bool _keyboardVisible = false; | 
					
						
							|  |  |  |   double _saveHeight = 0; | 
					
						
							|  |  |  |   double _lastBottomHeight = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   void initState() { | 
					
						
							|  |  |  |     super.initState(); | 
					
						
							|  |  |  |     _position = widget.position; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onPanUpdate(DragUpdateDetails d) { | 
					
						
							|  |  |  |     final offset = d.delta; | 
					
						
							|  |  |  |     final size = MediaQuery.of(context).size; | 
					
						
							|  |  |  |     double x = 0; | 
					
						
							|  |  |  |     double y = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_position.dx + offset.dx + widget.width > size.width) { | 
					
						
							|  |  |  |       x = size.width - widget.width; | 
					
						
							|  |  |  |     } else if (_position.dx + offset.dx < 0) { | 
					
						
							|  |  |  |       x = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       x = _position.dx + offset.dx; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (_position.dy + offset.dy + widget.height > size.height) { | 
					
						
							|  |  |  |       y = size.height - widget.height; | 
					
						
							|  |  |  |     } else if (_position.dy + offset.dy < 0) { | 
					
						
							|  |  |  |       y = 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       y = _position.dy + offset.dy; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     setState(() { | 
					
						
							|  |  |  |       _position = Offset(x, y); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   checkScreenSize() {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   checkKeyboard() { | 
					
						
							|  |  |  |     final bottomHeight = MediaQuery.of(context).viewInsets.bottom; | 
					
						
							|  |  |  |     final currentVisible = bottomHeight != 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // save
 | 
					
						
							|  |  |  |     if (!_keyboardVisible && currentVisible) { | 
					
						
							|  |  |  |       _saveHeight = _position.dy; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // reset
 | 
					
						
							|  |  |  |     if (_lastBottomHeight > 0 && bottomHeight == 0) { | 
					
						
							|  |  |  |       setState(() { | 
					
						
							|  |  |  |         _position = Offset(_position.dx, _saveHeight); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // onKeyboardVisible
 | 
					
						
							|  |  |  |     if (_keyboardVisible && currentVisible) { | 
					
						
							|  |  |  |       final sumHeight = bottomHeight + widget.height; | 
					
						
							|  |  |  |       final contextHeight = MediaQuery.of(context).size.height; | 
					
						
							|  |  |  |       if (sumHeight + _position.dy > contextHeight) { | 
					
						
							|  |  |  |         final y = contextHeight - sumHeight; | 
					
						
							|  |  |  |         setState(() { | 
					
						
							|  |  |  |           _position = Offset(_position.dx, y); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _keyboardVisible = currentVisible; | 
					
						
							|  |  |  |     _lastBottomHeight = bottomHeight; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     if (widget.checkKeyboard) { | 
					
						
							|  |  |  |       checkKeyboard(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-06 09:54:21 +09:00
										 |  |  |     if (widget.checkScreenSize) { | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |       checkScreenSize(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-02-06 09:54:21 +09:00
										 |  |  |     return Stack(children: [ | 
					
						
							|  |  |  |       Positioned( | 
					
						
							|  |  |  |           top: _position.dy, | 
					
						
							|  |  |  |           left: _position.dx, | 
					
						
							|  |  |  |           width: widget.width, | 
					
						
							|  |  |  |           height: widget.height, | 
					
						
							|  |  |  |           child: widget.builder(context, onPanUpdate)) | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2022-05-02 16:02:49 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-09-27 23:05:11 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class QualityMonitor extends StatelessWidget { | 
					
						
							|  |  |  |   final QualityMonitorModel qualityMonitorModel; | 
					
						
							|  |  |  |   QualityMonitor(this.qualityMonitorModel); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 19:36:36 +08:00
										 |  |  |   Widget _row(String info, String? value, {Color? rightColor}) { | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |     return Row( | 
					
						
							|  |  |  |       children: [ | 
					
						
							|  |  |  |         Expanded( | 
					
						
							|  |  |  |             flex: 8, | 
					
						
							|  |  |  |             child: AutoSizeText(info, | 
					
						
							| 
									
										
										
										
											2023-03-13 08:17:16 +08:00
										 |  |  |                 style: TextStyle(color: Color.fromARGB(255, 210, 210, 210)), | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |                 textAlign: TextAlign.right, | 
					
						
							|  |  |  |                 maxLines: 1)), | 
					
						
							|  |  |  |         Spacer(flex: 1), | 
					
						
							|  |  |  |         Expanded( | 
					
						
							|  |  |  |             flex: 8, | 
					
						
							|  |  |  |             child: AutoSizeText(value ?? '', | 
					
						
							| 
									
										
										
										
											2023-02-01 19:36:36 +08:00
										 |  |  |                 style: TextStyle(color: rightColor ?? Colors.white), | 
					
						
							|  |  |  |                 maxLines: 1)), | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |       ], | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 23:05:11 +08:00
										 |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) => ChangeNotifierProvider.value( | 
					
						
							|  |  |  |       value: qualityMonitorModel, | 
					
						
							|  |  |  |       child: Consumer<QualityMonitorModel>( | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |           builder: (context, qualityMonitorModel, child) => qualityMonitorModel | 
					
						
							|  |  |  |                   .show | 
					
						
							|  |  |  |               ? Container( | 
					
						
							|  |  |  |                   constraints: BoxConstraints(maxWidth: 200), | 
					
						
							|  |  |  |                   padding: const EdgeInsets.all(8), | 
					
						
							| 
									
										
										
										
											2023-03-13 08:17:16 +08:00
										 |  |  |                   color: MyTheme.canvasColor.withAlpha(150), | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |                   child: Column( | 
					
						
							|  |  |  |                     crossAxisAlignment: CrossAxisAlignment.start, | 
					
						
							|  |  |  |                     children: [ | 
					
						
							| 
									
										
										
										
											2023-02-01 19:36:36 +08:00
										 |  |  |                       _row("Speed", qualityMonitorModel.data.speed ?? '-'), | 
					
						
							|  |  |  |                       _row("FPS", qualityMonitorModel.data.fps ?? '-'), | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |                       _row( | 
					
						
							| 
									
										
										
										
											2023-02-01 19:36:36 +08:00
										 |  |  |                           "Delay", "${qualityMonitorModel.data.delay ?? '-'}ms", | 
					
						
							|  |  |  |                           rightColor: Colors.green), | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |                       _row("Target Bitrate", | 
					
						
							| 
									
										
										
										
											2023-02-01 19:36:36 +08:00
										 |  |  |                           "${qualityMonitorModel.data.targetBitrate ?? '-'}kb"), | 
					
						
							|  |  |  |                       _row( | 
					
						
							|  |  |  |                           "Codec", qualityMonitorModel.data.codecFormat ?? '-'), | 
					
						
							| 
									
										
										
										
											2023-01-30 21:40:13 +08:00
										 |  |  |                     ], | 
					
						
							|  |  |  |                   ), | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |               : const SizedBox.shrink())); | 
					
						
							| 
									
										
										
										
											2022-09-27 23:05:11 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:01:15 +09:00
										 |  |  | class BlockableOverlayState extends OverlayKeyState { | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  |   final _middleBlocked = false.obs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   VoidCallback? onMiddleBlockedClick; // to-do use listener
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RxBool get middleBlocked => _middleBlocked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void addMiddleBlockedListener(void Function(bool) cb) { | 
					
						
							|  |  |  |     _middleBlocked.listen(cb); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setMiddleBlocked(bool blocked) { | 
					
						
							|  |  |  |     if (blocked != _middleBlocked.value) { | 
					
						
							|  |  |  |       _middleBlocked.value = blocked; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-04-04 09:51:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void applyFfi(FFI ffi) { | 
					
						
							|  |  |  |     ffi.dialogManager.setOverlayState(this); | 
					
						
							|  |  |  |     ffi.chatModel.setOverlayState(this); | 
					
						
							|  |  |  |     // make remote page penetrable automatically, effective for chat over remote
 | 
					
						
							|  |  |  |     onMiddleBlockedClick = () { | 
					
						
							|  |  |  |       setMiddleBlocked(false); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:01:15 +09:00
										 |  |  | class BlockableOverlay extends StatelessWidget { | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  |   final Widget underlying; | 
					
						
							|  |  |  |   final List<OverlayEntry>? upperLayer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:01:15 +09:00
										 |  |  |   final BlockableOverlayState state; | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:01:15 +09:00
										 |  |  |   BlockableOverlay( | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  |       {required this.underlying, required this.state, this.upperLayer}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   @override | 
					
						
							|  |  |  |   Widget build(BuildContext context) { | 
					
						
							|  |  |  |     final initialEntries = [ | 
					
						
							|  |  |  |       OverlayEntry(builder: (_) => underlying), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /// middle layer
 | 
					
						
							|  |  |  |       OverlayEntry( | 
					
						
							|  |  |  |           builder: (context) => Obx(() => Listener( | 
					
						
							|  |  |  |               onPointerDown: (_) { | 
					
						
							|  |  |  |                 state.onMiddleBlockedClick?.call(); | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               child: Container( | 
					
						
							| 
									
										
										
										
											2023-02-08 22:05:11 +09:00
										 |  |  |                   color: | 
					
						
							|  |  |  |                       state.middleBlocked.value ? Colors.transparent : null)))), | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (upperLayer != null) { | 
					
						
							|  |  |  |       initialEntries.addAll(upperLayer!); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-08 22:01:15 +09:00
										 |  |  |     /// set key
 | 
					
						
							|  |  |  |     return Overlay(key: state.key, initialEntries: initialEntries); | 
					
						
							| 
									
										
										
										
											2023-02-07 00:11:48 +09:00
										 |  |  |   } | 
					
						
							|  |  |  | } |