mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-22 21:09:21 +00:00
236 lines
7.7 KiB
Dart
236 lines
7.7 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:comunic/enums/load_error_level.dart';
|
|
import 'package:comunic/enums/report_target_type.dart';
|
|
import 'package:comunic/helpers/conversations_helper.dart';
|
|
import 'package:comunic/helpers/events_helper.dart';
|
|
import 'package:comunic/helpers/groups_helper.dart';
|
|
import 'package:comunic/helpers/users_helper.dart';
|
|
import 'package:comunic/lists/conversations_list.dart';
|
|
import 'package:comunic/lists/groups_list.dart';
|
|
import 'package:comunic/lists/users_list.dart';
|
|
import 'package:comunic/models/conversation.dart';
|
|
import 'package:comunic/models/report_target.dart';
|
|
import 'package:comunic/ui/dialogs/report_dialog.dart';
|
|
import 'package:comunic/ui/routes/main_route/main_route.dart';
|
|
import 'package:comunic/ui/screens/create_conversation_screen.dart';
|
|
import 'package:comunic/ui/tiles/conversation_tile.dart';
|
|
import 'package:comunic/ui/widgets/safe_state.dart';
|
|
import 'package:comunic/utils/intl_utils.dart';
|
|
import 'package:comunic/utils/ui_utils.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// Conversations screen
|
|
///
|
|
/// @author Pierre HUBERT
|
|
|
|
class ConversationsListScreen extends StatefulWidget {
|
|
final bool useSmallFAB;
|
|
final Function()? onOpen;
|
|
|
|
const ConversationsListScreen({
|
|
Key? key,
|
|
this.useSmallFAB = false,
|
|
this.onOpen,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _ConversationScreenState();
|
|
}
|
|
|
|
class _ConversationScreenState extends SafeState<ConversationsListScreen> {
|
|
final ConversationsHelper _conversationsHelper = ConversationsHelper();
|
|
final UsersHelper _usersHelper = UsersHelper();
|
|
ConversationsList? _list;
|
|
late UsersList _users;
|
|
GroupsList? _groups;
|
|
LoadErrorLevel _error = LoadErrorLevel.NONE;
|
|
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
|
|
GlobalKey<RefreshIndicatorState>();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
this.listen<NewNumberUnreadConversations>(
|
|
(d) => _refreshIndicatorKey.currentState!.show());
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
_loadConversations();
|
|
}
|
|
|
|
void setError(LoadErrorLevel err) => setState(() => _error = err);
|
|
|
|
/// Get the list of conversations, once from the cache, once from the server
|
|
Future<void> _loadConversations() async {
|
|
await _loadConversationsList(true);
|
|
await _loadConversationsList(false);
|
|
}
|
|
|
|
/// Load the list of conversations
|
|
Future<void> _loadConversationsList(bool cached) async {
|
|
setError(LoadErrorLevel.NONE);
|
|
|
|
try {
|
|
ConversationsList list = cached
|
|
? await _conversationsHelper.getCachedList()
|
|
: await _conversationsHelper.downloadList();
|
|
|
|
// Get information about the members of the conversations
|
|
_users = await _usersHelper.getList(list.allUsersID);
|
|
|
|
_groups = await GroupsHelper().getListOrThrow(list.allGroupsID);
|
|
|
|
setState(() => _list = list);
|
|
} catch (e, s) {
|
|
debugPrint("Failed to get conversations list! $e => $s", wrapWidth: 1024);
|
|
setError(_list == null ? LoadErrorLevel.MAJOR : LoadErrorLevel.MINOR);
|
|
}
|
|
}
|
|
|
|
/// Build an error card
|
|
Widget _buildErrorCard() {
|
|
return buildErrorCard(
|
|
tr("Could not retrieve the list of conversations!"),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
onPressed: () => _refreshIndicatorKey.currentState!.show(),
|
|
child: Text(
|
|
tr("Retry")!.toUpperCase(),
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}
|
|
|
|
/// Open a conversation
|
|
void _openConversation(Conversation conv) {
|
|
MainController.of(context)!.openConversation(conv);
|
|
if (widget.onOpen != null) widget.onOpen!();
|
|
}
|
|
|
|
/// Create a new conversation
|
|
void _createConversation() {
|
|
MainController.of(context)!.push(
|
|
CreateConversationScreen(),
|
|
canShowAsDialog: true,
|
|
hideNavBar: true,
|
|
);
|
|
if (widget.onOpen != null) widget.onOpen!();
|
|
}
|
|
|
|
/// Handle conversations updated requests
|
|
void _updateConversation(Conversation conversation) {
|
|
MainController.of(context)!.openConversationSettingsRoute(conversation);
|
|
}
|
|
|
|
/// Handle conversation deletion request
|
|
Future<void> _requestLeaveConversation(Conversation conversation) async {
|
|
if (conversation.isGroupConversation) {
|
|
showAlert(
|
|
context: context,
|
|
title: tr("Group conversation"),
|
|
message: tr(
|
|
"This conversation is managed by a group. You can not leave it this way. If you do not want to receive notifications from this conversation anymore, you can stop following it in the conversation settings"));
|
|
return;
|
|
}
|
|
|
|
final result = await showConfirmDialog(
|
|
context: context,
|
|
message: conversation.isLastAdmin
|
|
? tr(
|
|
"Do you really want to leave this conversation ? As you are its last admin, it will be completely deleted!")
|
|
: tr("Do you really want to leave this conversation ?"));
|
|
|
|
if (!result) return;
|
|
|
|
// Request the conversation to be deleted now
|
|
try {
|
|
await _conversationsHelper.deleteConversation(conversation.id);
|
|
} catch (e, s) {
|
|
print("Failed to leave conversation! $e => $s");
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text(tr("Could not leave the conversation!")!)));
|
|
}
|
|
|
|
// Reload the list of conversations
|
|
_loadConversationsList(false);
|
|
}
|
|
|
|
/// Handle conversation report request
|
|
void _reportConversation(Conversation conversation) => showReportDialog(
|
|
ctx: context,
|
|
target: ReportTarget(ReportTargetType.Conversation, conversation.id!));
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard();
|
|
if (_list == null) return buildCenteredProgressBar();
|
|
|
|
// Show the list of conversations
|
|
return Stack(
|
|
children: <Widget>[
|
|
Column(
|
|
children: <Widget>[
|
|
Container(
|
|
child: _error == LoadErrorLevel.MINOR ? _buildErrorCard() : null,
|
|
),
|
|
Expanded(
|
|
child: RefreshIndicator(
|
|
onRefresh: () => _loadConversationsList(false),
|
|
key: _refreshIndicatorKey,
|
|
child: ListView.builder(
|
|
physics: AlwaysScrollableScrollPhysics(),
|
|
controller: ScrollController(),
|
|
itemBuilder: (context, index) {
|
|
if (_list!.isEmpty)
|
|
return Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Center(
|
|
child: Text(
|
|
tr("You do not have any conversation yet!")!)),
|
|
);
|
|
|
|
if (_list![index].isGroupConversation &&
|
|
!_list![index].following) return Container();
|
|
|
|
return ConversationTile(
|
|
conversation: _list!.elementAt(index),
|
|
usersList: _users,
|
|
groupsList: _groups,
|
|
onOpen: (c) {
|
|
_openConversation(c);
|
|
},
|
|
onRequestUpdate: _updateConversation,
|
|
onRequestLeave: _requestLeaveConversation,
|
|
onReport: _reportConversation,
|
|
);
|
|
},
|
|
itemCount: max(_list!.length, 1),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
// Add conversation button
|
|
Positioned(
|
|
right: widget.useSmallFAB ? 5.0 : 20.0,
|
|
bottom: widget.useSmallFAB ? 5.0 : 20.0,
|
|
child: FloatingActionButton(
|
|
mini: widget.useSmallFAB,
|
|
onPressed: () => _createConversation(),
|
|
child: Icon(Icons.add),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|