1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-22 12:59:21 +00:00

Can delete conversation messages

This commit is contained in:
Pierre HUBERT 2019-05-04 08:58:14 +02:00
parent 533d2a86a3
commit 1f0d70848f
4 changed files with 110 additions and 15 deletions

View File

@ -320,6 +320,27 @@ class ConversationsHelper {
return SendMessageResult.SUCCESS;
}
/// Delete permanently a message specified by its [id]
Future<bool> deleteMessage(int id) async {
// Delete the message online
final response = await APIRequest(
uri: "conversations/deleteMessage",
needLogin: true,
args: {
"messageID": id.toString()
}
).exec();
if(response.code != 200) return false;
// Delete the message locally
return await _conversationMessagesDatabaseHelper.delete(id);
}
/// Turn an API response into a ConversationMessage object
ConversationMessage _apiToConversationMessage({
@required int conversationID,

View File

@ -1,5 +1,6 @@
import 'package:comunic/helpers/database/database_contract.dart';
import 'package:comunic/models/cache_model.dart';
import 'package:comunic/utils/account_utils.dart' as account;
import 'package:meta/meta.dart';
/// Single conversation message
@ -33,6 +34,8 @@ class ConversationMessage extends CacheModel implements Comparable {
bool get hasImage => imageURL != null && imageURL != "null";
bool get isOwner => account.userID() == userID;
@override
int compareTo(other) {
return id.compareTo(other.id);

View File

@ -4,6 +4,7 @@ import 'package:comunic/helpers/conversations_helper.dart';
import 'package:comunic/helpers/users_helper.dart';
import 'package:comunic/lists/conversation_messages_list.dart';
import 'package:comunic/lists/users_list.dart';
import 'package:comunic/models/conversation_message.dart';
import 'package:comunic/models/new_conversation_message.dart';
import 'package:comunic/ui/tiles/conversation_message_tile.dart';
import 'package:comunic/ui/widgets/scroll_watcher.dart';
@ -288,6 +289,7 @@ class _ConversationScreenState extends State<ConversationScreen> {
userInfo: _usersInfo.getUser(_messages[i].userID),
isLastMessage: _isLastMessage(i),
isFirstMessage: _isFirstMessage(i),
onRequestMessageDelete: _deleteMessage,
);
}),
);
@ -386,4 +388,45 @@ class _ConversationScreenState extends State<ConversationScreen> {
],
);
}
/// Request message deletion
Future<void> _deleteMessage(ConversationMessage message) async {
final choice = await showDialog<bool>(
context: context,
builder: (c) => AlertDialog(
title: Text(tr("Confirm deletion")),
content: Text(
tr("Do you really want to delete this message ? The operation can not be cancelled !"),
textAlign: TextAlign.justify,
),
actions: <Widget>[
FlatButton(
child: Text(
tr("Cancel").toUpperCase(),
),
onPressed: () => Navigator.pop(c, false),
),
FlatButton(
child: Text(
tr("Confirm").toUpperCase(),
style: TextStyle(color: Colors.red),
),
onPressed: () => Navigator.pop(c, true),
),
],
),
);
if(choice == null || !choice)
return;
// Execute the request
if(!await _conversationsHelper.deleteMessage(message.id))
showSimpleSnack(context, tr("Could not delete conversation message!"));
// Remove the message from the list
setState(() {
_messages.remove(message);
});
}
}

View File

@ -3,8 +3,8 @@ import 'package:comunic/models/conversation_message.dart';
import 'package:comunic/models/user.dart';
import 'package:comunic/ui/widgets/account_image_widget.dart';
import 'package:comunic/ui/widgets/text_rich_content_widget.dart';
import 'package:comunic/utils/account_utils.dart';
import 'package:comunic/utils/date_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
@ -12,31 +12,48 @@ import 'package:flutter/material.dart';
///
/// @author Pierre HUBERT
enum _MenuChoices { DELETE }
typedef OnRequestMessageDelete = void Function(ConversationMessage);
class ConversationMessageTile extends StatelessWidget {
final ConversationMessage message;
final User userInfo;
final bool isLastMessage;
final bool isFirstMessage;
final OnRequestMessageDelete onRequestMessageDelete;
const ConversationMessageTile(
{Key key,
@required this.message,
@required this.userInfo,
@required this.isLastMessage,
@required this.isFirstMessage})
: assert(message != null),
const ConversationMessageTile({
Key key,
@required this.message,
@required this.userInfo,
@required this.isLastMessage,
@required this.isFirstMessage,
@required this.onRequestMessageDelete,
}) : assert(message != null),
assert(userInfo != null),
assert(isLastMessage != null),
assert(isFirstMessage != null),
assert(onRequestMessageDelete != null),
super(key: key);
/// Build account image
Widget _buildAccountImage() {
Widget _buildAccountImage(BuildContext context) {
return Container(
margin: EdgeInsets.all(10.0),
child: AccountImageWidget(
user: userInfo,
width: 35.0,
child: PopupMenuButton<_MenuChoices>(
child: AccountImageWidget(
user: userInfo,
width: 35.0,
),
itemBuilder: (c) => [
PopupMenuItem(
enabled: message.isOwner,
value: _MenuChoices.DELETE,
child: Text(tr("Delete")),
),
],
onSelected: _menuOptionSelected,
),
);
}
@ -141,7 +158,7 @@ class ConversationMessageTile extends StatelessWidget {
),
// Account image
_buildAccountImage()
_buildAccountImage(context)
],
),
@ -180,7 +197,7 @@ class ConversationMessageTile extends StatelessWidget {
Row(
children: <Widget>[
// Account image
_buildAccountImage(),
_buildAccountImage(context),
Column(
children: <Widget>[
@ -232,8 +249,19 @@ class ConversationMessageTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
return userID() == message.userID
return message.isOwner
? _buildRightMessage(context)
: _buildLeftMessage(context);
}
/// Process menu choice
void _menuOptionSelected(_MenuChoices value) {
switch(value){
case _MenuChoices.DELETE:
onRequestMessageDelete(message);
break;
}
}
}