import 'package:comunic/helpers/conversations_helper.dart'; import 'package:comunic/helpers/events_helper.dart'; import 'package:comunic/models/conversation.dart'; import 'package:comunic/ui/dialogs/screen_dialog.dart'; import 'package:comunic/ui/routes/main_route/main_route.dart'; import 'package:comunic/ui/routes/update_conversation_route.dart'; import 'package:comunic/ui/screens/conversation_members_screen.dart'; import 'package:comunic/ui/screens/conversation_screen.dart'; import 'package:comunic/ui/widgets/safe_state.dart'; import 'package:comunic/ui/widgets/tablet_mode/conversations/conversation_window_container.dart'; import 'package:comunic/utils/account_utils.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; /// Single conversation window /// /// @author Pierre Hubert enum _Actions { OPEN_FULL_SCREEN, OPEN_MEMBERS, OPEN_SETTINGS } class ConversationWindow extends StatefulWidget { final int convID; final Function() onClose; const ConversationWindow({ Key? key, required this.convID, required this.onClose, }) : assert(convID != null), assert(onClose != null), super(key: key); @override _ConversationWindowState createState() => _ConversationWindowState(); } class _ConversationWindowState extends SafeState { Conversation? _conversation; late String _convTitle; bool _error = false; bool _collapsed = false; bool _hasNewMessages = false; int get _convID => widget.convID; final _convKey = UniqueKey(); void _setError(bool e) => setState(() => _error = e); void _toggleVisibility() => setState(() { _collapsed = !_collapsed; if (!_collapsed) _hasNewMessages = false; }); Future _refresh() async { try { _setError(false); final conversation = await ConversationsHelper().getSingle(_convID, force: true); assert(conversation != null); final name = await ConversationsHelper.getConversationNameAsync(conversation); assert(name != null); setState(() { _conversation = conversation; _convTitle = name; }); } catch (e, s) { _setError(true); print("Could not refresh the list of conversations! $e\n$s"); showSimpleSnack(context, tr("Could not load conversation information!")!); } } @override void initState() { super.initState(); _refresh(); listen((e) { if (e.msg.convID == _convID && _collapsed && e.msg.userID != userID()) setState(() => _hasNewMessages = true); }); } @override Widget build(BuildContext context) { // In case of error if (_error) return ConversationWindowContainer( icon: Icon(Icons.error), title: Text(tr("Error")!), onClose: widget.onClose, onToggleCollapse: _toggleVisibility, isCollapsed: _collapsed, body: buildErrorCard(tr("Could not load conversation information!"), actions: [ ElevatedButton( onPressed: _refresh, child: Text(tr("Try again")!.toUpperCase()), ) ]), ); // If it is still loading if (_conversation == null) return ConversationWindowContainer( icon: Icon(Icons.message), title: Text(tr("Loading...")!), onClose: widget.onClose, onToggleCollapse: _toggleVisibility, isCollapsed: _collapsed, body: buildCenteredProgressBar(), ); return ConversationWindowContainer( icon: _hasNewMessages ? Icon(Icons.trip_origin) : null, appBarBgColor: _hasNewMessages ? Colors.green : null, title: Text(_convTitle), onClose: widget.onClose, onToggleCollapse: _toggleVisibility, isCollapsed: _collapsed, action: (_conversation!.callCapabilities != CallCapabilities.NONE ? [IconButton(icon: Icon(Icons.call), onPressed: _startCall)] : []) ..addAll([ PopupMenuButton<_Actions>( itemBuilder: (c) => [ // Show in full screen PopupMenuItem( child: Text(tr("Open in full screen")!), value: _Actions.OPEN_FULL_SCREEN, ), // Show the list of members PopupMenuItem( child: Text(tr("Members")!), value: _Actions.OPEN_MEMBERS, ), // Show conversation settings PopupMenuItem( child: Text(tr("Settings")!), value: _Actions.OPEN_SETTINGS, ) ], onSelected: _menuCallback, ), ]), body: ConversationScreen( key: _convKey, conversationID: _convID, ), ); } void _menuCallback(_Actions value) { switch (value) { case _Actions.OPEN_FULL_SCREEN: _openFullScreen(); break; case _Actions.OPEN_MEMBERS: _openMembersList(); break; case _Actions.OPEN_SETTINGS: _openConversationSettings(); break; } } void _openFullScreen() { MainController.of(context)! .openConversation(_conversation!, fullScreen: true); widget.onClose(); } void _openMembersList() { showScreenDialog(context, ConversationMembersScreen(convID: _convID)); } void _openConversationSettings() async { await showScreenDialog( context, UpdateConversationRoute(conversationID: _convID)); _refresh(); } void _startCall() => MainController.of(context)!.startCall(_convID); }