2022-08-04 17:24:02 +08:00
import ' package:dash_chat_2/dash_chat_2.dart ' ;
2022-08-11 10:19:12 +08:00
import ' package:draggable_float_widget/draggable_float_widget.dart ' ;
2022-02-28 21:26:44 +08:00
import ' package:flutter/material.dart ' ;
2022-08-08 17:53:51 +08:00
import ' package:flutter_hbb/models/platform_model.dart ' ;
2022-08-22 20:12:58 +08:00
import ' package:window_manager/window_manager.dart ' ;
2022-03-03 14:58:57 +08:00
2022-05-24 23:33:00 +08:00
import ' ../../mobile/widgets/overlay.dart ' ;
2022-08-11 10:19:12 +08:00
import ' ../common.dart ' ;
2022-03-03 14:58:57 +08:00
import ' model.dart ' ;
2022-02-28 21:26:44 +08:00
2022-05-16 00:01:27 +08:00
class MessageBody {
ChatUser chatUser ;
List < ChatMessage > chatMessages ;
MessageBody ( this . chatUser , this . chatMessages ) ;
2022-08-04 17:24:02 +08:00
void insert ( ChatMessage cm ) {
this . chatMessages . insert ( 0 , cm ) ;
2022-05-16 00:01:27 +08:00
}
void clear ( ) {
this . chatMessages . clear ( ) ;
}
}
2022-02-28 21:26:44 +08:00
class ChatModel with ChangeNotifier {
2022-03-22 16:40:23 +08:00
static final clientModeID = - 1 ;
2022-08-11 10:19:12 +08:00
/// _overlayState:
/// Desktop: store session overlay by using [setOverlayState].
/// Mobile: always null, use global overlay.
/// see [_getOverlayState] in [showChatIconOverlay] or [showChatWindowOverlay]
OverlayState ? _overlayState ;
OverlayEntry ? chatIconOverlayEntry ;
OverlayEntry ? chatWindowOverlayEntry ;
2022-03-03 14:58:57 +08:00
final ChatUser me = ChatUser (
2022-08-04 17:24:02 +08:00
id: " " ,
firstName: " Me " ,
2022-03-03 14:58:57 +08:00
) ;
2022-05-16 00:01:27 +08:00
late final Map < int , MessageBody > _messages = Map ( )
. . [ clientModeID ] = MessageBody ( me , [ ] ) ;
2022-03-22 16:40:23 +08:00
var _currentID = clientModeID ;
2022-08-22 20:12:58 +08:00
late bool _isShowChatPage = false ;
2022-03-22 16:40:23 +08:00
2022-05-16 00:01:27 +08:00
Map < int , MessageBody > get messages = > _messages ;
2022-03-25 16:34:27 +08:00
int get currentID = > _currentID ;
2022-03-03 14:58:57 +08:00
2022-08-22 20:12:58 +08:00
bool get isShowChatPage = > _isShowChatPage ;
2022-06-13 21:07:26 +08:00
WeakReference < FFI > _ffi ;
/// Constructor
ChatModel ( this . _ffi ) ;
2022-05-16 00:01:27 +08:00
ChatUser get currentUser {
final user = messages [ currentID ] ? . chatUser ;
if ( user = = null ) {
_currentID = clientModeID ;
return me ;
} else {
return user ;
}
}
2022-04-04 14:54:00 +08:00
2022-08-11 10:19:12 +08:00
setOverlayState ( OverlayState ? os ) {
_overlayState = os ;
}
OverlayState ? _getOverlayState ( ) {
if ( _overlayState = = null ) {
if ( globalKey . currentState = = null | |
globalKey . currentState ! . overlay = = null ) return null ;
return globalKey . currentState ! . overlay ;
} else {
return _overlayState ;
}
}
showChatIconOverlay ( { Offset offset = const Offset ( 200 , 50 ) } ) {
if ( chatIconOverlayEntry ! = null ) {
chatIconOverlayEntry ! . remove ( ) ;
}
// mobile check navigationBar
final bar = navigationBarKey . currentWidget ;
if ( bar ! = null ) {
if ( ( bar as BottomNavigationBar ) . currentIndex = = 1 ) {
return ;
}
}
final overlayState = _getOverlayState ( ) ;
if ( overlayState = = null ) return ;
final overlay = OverlayEntry ( builder: ( context ) {
return DraggableFloatWidget (
config: DraggableFloatWidgetBaseConfig (
initPositionYInTop: false ,
initPositionYMarginBorder: 100 ,
borderTopContainTopBar: true ,
) ,
child: FloatingActionButton (
onPressed: ( ) {
if ( chatWindowOverlayEntry = = null ) {
showChatWindowOverlay ( ) ;
} else {
hideChatWindowOverlay ( ) ;
}
} ,
child: Icon ( Icons . message ) ) ) ;
} ) ;
overlayState . insert ( overlay ) ;
chatIconOverlayEntry = overlay ;
}
hideChatIconOverlay ( ) {
if ( chatIconOverlayEntry ! = null ) {
chatIconOverlayEntry ! . remove ( ) ;
chatIconOverlayEntry = null ;
}
}
showChatWindowOverlay ( ) {
if ( chatWindowOverlayEntry ! = null ) return ;
final overlayState = _getOverlayState ( ) ;
if ( overlayState = = null ) return ;
final overlay = OverlayEntry ( builder: ( context ) {
return DraggableChatWindow (
position: Offset ( 20 , 80 ) , width: 250 , height: 350 , chatModel: this ) ;
} ) ;
overlayState . insert ( overlay ) ;
chatWindowOverlayEntry = overlay ;
}
hideChatWindowOverlay ( ) {
if ( chatWindowOverlayEntry ! = null ) {
chatWindowOverlayEntry ! . remove ( ) ;
chatWindowOverlayEntry = null ;
return ;
}
}
toggleChatOverlay ( ) {
if ( chatIconOverlayEntry = = null | | chatWindowOverlayEntry = = null ) {
gFFI . invokeMethod ( " enable_soft_keyboard " , true ) ;
showChatIconOverlay ( ) ;
showChatWindowOverlay ( ) ;
} else {
hideChatIconOverlay ( ) ;
hideChatWindowOverlay ( ) ;
}
}
2022-08-22 20:12:58 +08:00
toggleCMChatPage ( int id ) async {
if ( gFFI . chatModel . currentID ! = id ) {
gFFI . chatModel . changeCurrentID ( id ) ;
}
if ( _isShowChatPage ) {
_isShowChatPage = ! _isShowChatPage ;
notifyListeners ( ) ;
await windowManager . setSize ( Size ( 400 , 600 ) ) ;
} else {
await windowManager . setSize ( Size ( 800 , 600 ) ) ;
await Future . delayed ( Duration ( milliseconds: 100 ) ) ;
_isShowChatPage = ! _isShowChatPage ;
notifyListeners ( ) ;
}
}
2022-04-05 00:51:47 +08:00
changeCurrentID ( int id ) {
if ( _messages . containsKey ( id ) ) {
2022-03-25 16:34:27 +08:00
_currentID = id ;
notifyListeners ( ) ;
2022-04-04 14:54:00 +08:00
} else {
2022-08-22 20:12:58 +08:00
final client = _ffi . target ? . serverModel . clients
. firstWhere ( ( client ) = > client . id = = id ) ;
2022-05-16 00:01:27 +08:00
if ( client = = null ) {
2022-04-05 00:51:47 +08:00
return debugPrint (
" Failed to changeCurrentID,remote user doesn't exist " ) ;
2022-04-04 14:54:00 +08:00
}
2022-05-16 00:01:27 +08:00
final chatUser = ChatUser (
2022-08-04 17:24:02 +08:00
id: client . peerId ,
firstName: client . name ,
2022-05-16 00:01:27 +08:00
) ;
_messages [ id ] = MessageBody ( chatUser , [ ] ) ;
2022-04-04 14:54:00 +08:00
_currentID = id ;
2022-05-16 00:01:27 +08:00
notifyListeners ( ) ;
2022-03-25 16:34:27 +08:00
}
}
2022-03-22 16:40:23 +08:00
2022-08-08 17:53:51 +08:00
receive ( int id , String text ) async {
2022-03-03 14:58:57 +08:00
if ( text . isEmpty ) return ;
2022-08-22 20:12:58 +08:00
// mobile: first message show overlay icon
2022-04-28 22:44:54 +08:00
if ( chatIconOverlayEntry = = null ) {
2022-03-03 14:58:57 +08:00
showChatIconOverlay ( ) ;
}
2022-08-22 20:12:58 +08:00
// desktop: show chat page
if ( ! _isShowChatPage ) {
toggleCMChatPage ( id ) ;
}
2022-08-24 21:52:21 +08:00
_ffi . target ? . serverModel . jumpTo ( id ) ;
2022-08-22 20:12:58 +08:00
2022-03-25 16:34:27 +08:00
late final chatUser ;
2022-04-05 00:51:47 +08:00
if ( id = = clientModeID ) {
2022-03-25 16:34:27 +08:00
chatUser = ChatUser (
2022-08-04 17:24:02 +08:00
firstName: _ffi . target ? . ffiModel . pi . username ,
2022-08-08 17:53:51 +08:00
id: await bind . mainGetLastRemoteId ( ) ,
2022-03-25 16:34:27 +08:00
) ;
2022-04-05 00:51:47 +08:00
} else {
2022-06-13 21:07:26 +08:00
final client = _ffi . target ? . serverModel . clients [ id ] ;
2022-05-16 00:01:27 +08:00
if ( client = = null ) {
return debugPrint ( " Failed to receive msg,user doesn't exist " ) ;
}
2022-08-04 17:24:02 +08:00
chatUser = ChatUser ( id: client . peerId , firstName: client . name ) ;
2022-03-25 16:34:27 +08:00
}
2022-05-16 00:01:27 +08:00
2022-04-05 00:51:47 +08:00
if ( ! _messages . containsKey ( id ) ) {
2022-05-16 00:01:27 +08:00
_messages [ id ] = MessageBody ( chatUser , [ ] ) ;
2022-03-22 16:40:23 +08:00
}
2022-08-04 17:24:02 +08:00
_messages [ id ] ! . insert (
ChatMessage ( text: text , user: chatUser , createdAt: DateTime . now ( ) ) ) ;
2022-03-22 16:40:23 +08:00
_currentID = id ;
2022-03-03 14:58:57 +08:00
notifyListeners ( ) ;
}
2022-03-22 16:40:23 +08:00
send ( ChatMessage message ) {
2022-08-04 17:24:02 +08:00
if ( message . text . isNotEmpty ) {
_messages [ _currentID ] ? . insert ( message ) ;
2022-03-22 16:40:23 +08:00
if ( _currentID = = clientModeID ) {
2022-08-08 22:27:27 +08:00
if ( _ffi . target ! = null ) {
bind . sessionSendChat ( id: _ffi . target ! . id , text: message . text ) ;
}
2022-03-22 16:40:23 +08:00
} else {
2022-08-17 17:23:55 +08:00
bind . cmSendChat ( connId: _currentID , msg: message . text ) ;
2022-03-22 16:40:23 +08:00
}
2022-03-03 14:58:57 +08:00
}
notifyListeners ( ) ;
}
2022-02-28 21:26:44 +08:00
2022-03-25 16:34:27 +08:00
close ( ) {
2022-03-03 14:58:57 +08:00
hideChatIconOverlay ( ) ;
hideChatWindowOverlay ( ) ;
2022-08-11 10:19:12 +08:00
_overlayState = null ;
2022-03-03 14:58:57 +08:00
notifyListeners ( ) ;
}
2022-05-16 00:01:27 +08:00
resetClientMode ( ) {
_messages [ clientModeID ] ? . clear ( ) ;
}
2022-03-22 16:40:23 +08:00
}