Can delete conversation messages

This commit is contained in:
Pierre HUBERT 2018-08-28 10:09:40 +02:00
parent 2b999c63a8
commit e92201b51d
9 changed files with 265 additions and 4 deletions

View File

@ -190,6 +190,20 @@ class ConversationMessagesDbHelper {
return list; return list;
} }
/**
* Delete a message from the local database
*
* @param messageID The ID of the message to delete
* @return The result of the operation
*/
boolean deleteMessage(int messageID){
SQLiteDatabase db = dbHelper.getWritableDatabase();
String conditions = ConversationsMessagesSchema.COLUMN_NAME_MESSAGE_ID + " = ?";
String[] args = {messageID+""};
return db.delete(TABLE_NAME, conditions, args) > 0;
}
/** /**
* Insert a single message into the database * Insert a single message into the database
* *

View File

@ -2,7 +2,6 @@ package org.communiquons.android.comunic.client.data.helpers;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
@ -41,6 +40,15 @@ public class ConversationMessagesHelper {
*/ */
private Context mContext; private Context mContext;
/**
* Constructor of the helper
*
* @param context The context of the application
*/
public ConversationMessagesHelper(Context context){
this(context.getApplicationContext(), DatabaseHelper.getInstance(context));
}
/** /**
* Public constructor of the helper * Public constructor of the helper
* *
@ -276,6 +284,32 @@ public class ConversationMessagesHelper {
return list; return list;
} }
/**
* Delete a conversation message
*
* @param messageID The ID of the message to delete
* @return TRUE for a success / FALSE else
*/
public boolean deleteMessage(int messageID){
//Make a request on the server
APIRequest request = new APIRequest(mContext, "conversations/deleteMessage");
request.addInt("messageID", messageID);
try {
APIResponse response = new APIRequestHelper().exec(request);
if(response.getResponse_code() != 200) return false;
//Delete the message in the local database
return mDbHelper.deleteMessage(messageID);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/** /**
* Convert a JSON object into a conversation message element * Convert a JSON object into a conversation message element
* *

View File

@ -4,6 +4,7 @@ import android.content.Context;
import android.support.annotation.CallSuper; import android.support.annotation.CallSuper;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -15,6 +16,7 @@ import org.communiquons.android.comunic.client.data.models.ConversationMessage;
import org.communiquons.android.comunic.client.data.models.UserInfo; import org.communiquons.android.comunic.client.data.models.UserInfo;
import org.communiquons.android.comunic.client.data.utils.StringsUtils; import org.communiquons.android.comunic.client.data.utils.StringsUtils;
import org.communiquons.android.comunic.client.data.utils.Utilities; import org.communiquons.android.comunic.client.data.utils.Utilities;
import org.communiquons.android.comunic.client.ui.listeners.OnConversationMessageActionsListener;
import org.communiquons.android.comunic.client.ui.views.EnlargeableWebImageView; import org.communiquons.android.comunic.client.ui.views.EnlargeableWebImageView;
import org.communiquons.android.comunic.client.ui.views.WebUserAccountImage; import org.communiquons.android.comunic.client.ui.views.WebUserAccountImage;
@ -53,6 +55,11 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
*/ */
private ConversationMessagesList mList; private ConversationMessagesList mList;
/**
* Conversation messages listener
*/
private OnConversationMessageActionsListener mOnConversationMessageActionsListener;
private Utilities utils; private Utilities utils;
/** /**
@ -85,6 +92,10 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
: VIEW_TYPE_MESSAGE_RECEIVED; : VIEW_TYPE_MESSAGE_RECEIVED;
} }
public void setOnConversationMessageActionsListener(OnConversationMessageActionsListener listener) {
this.mOnConversationMessageActionsListener = listener;
}
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) {
@ -122,7 +133,8 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
/** /**
* Base messages holder * Base messages holder
*/ */
private class BaseMessageHolder extends RecyclerView.ViewHolder { private class BaseMessageHolder extends RecyclerView.ViewHolder
implements View.OnLongClickListener{
private TextView mMessage; private TextView mMessage;
private TextView mSentDate; private TextView mSentDate;
@ -134,6 +146,9 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
mMessage = itemView.findViewById(R.id.message_body); mMessage = itemView.findViewById(R.id.message_body);
mImage = itemView.findViewById(R.id.messageImage); mImage = itemView.findViewById(R.id.messageImage);
mSentDate = itemView.findViewById(R.id.text_message_time); mSentDate = itemView.findViewById(R.id.text_message_time);
itemView.setOnLongClickListener(this);
mImage.setOnLongClickListener(this);
} }
/** /**
@ -174,6 +189,15 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
else else
mSentDate.setVisibility(View.VISIBLE); mSentDate.setVisibility(View.VISIBLE);
} }
@Override
public boolean onLongClick(View v) {
if(mOnConversationMessageActionsListener != null)
mOnConversationMessageActionsListener.onOpenContextMenu(getLayoutPosition(), v);
return true;
}
} }
/** /**

View File

@ -0,0 +1,23 @@
package org.communiquons.android.comunic.client.ui.asynctasks;
import android.content.Context;
import org.communiquons.android.comunic.client.data.asynctasks.SafeAsyncTask;
import org.communiquons.android.comunic.client.data.helpers.ConversationMessagesHelper;
/**
* Delete conversation message async task
*
* @author Pierre HUBERT
*/
public class DeleteConversationMessageTask extends SafeAsyncTask<Integer, Void, Boolean> {
public DeleteConversationMessageTask(Context context) {
super(context);
}
@Override
protected Boolean doInBackground(Integer... integers) {
return new ConversationMessagesHelper(getContext()).deleteMessage(integers[0]);
}
}

View File

@ -1,6 +1,7 @@
package org.communiquons.android.comunic.client.ui.fragments; package org.communiquons.android.comunic.client.ui.fragments;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -14,16 +15,19 @@ import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.PopupMenu;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import org.communiquons.android.comunic.client.R; import org.communiquons.android.comunic.client.R;
import org.communiquons.android.comunic.client.data.arrays.ConversationMessagesList; import org.communiquons.android.comunic.client.data.arrays.ConversationMessagesList;
import org.communiquons.android.comunic.client.data.asynctasks.SafeAsyncTask;
import org.communiquons.android.comunic.client.data.helpers.ConversationMessagesHelper; import org.communiquons.android.comunic.client.data.helpers.ConversationMessagesHelper;
import org.communiquons.android.comunic.client.data.helpers.ConversationsListHelper; import org.communiquons.android.comunic.client.data.helpers.ConversationsListHelper;
import org.communiquons.android.comunic.client.data.helpers.DatabaseHelper; import org.communiquons.android.comunic.client.data.helpers.DatabaseHelper;
@ -35,6 +39,8 @@ import org.communiquons.android.comunic.client.data.runnables.ConversationRefres
import org.communiquons.android.comunic.client.data.utils.AccountUtils; import org.communiquons.android.comunic.client.data.utils.AccountUtils;
import org.communiquons.android.comunic.client.ui.activities.MainActivity; import org.communiquons.android.comunic.client.ui.activities.MainActivity;
import org.communiquons.android.comunic.client.ui.adapters.ConversationMessageAdapter; import org.communiquons.android.comunic.client.ui.adapters.ConversationMessageAdapter;
import org.communiquons.android.comunic.client.ui.asynctasks.DeleteConversationMessageTask;
import org.communiquons.android.comunic.client.ui.listeners.OnConversationMessageActionsListener;
import org.communiquons.android.comunic.client.ui.listeners.OnScrollChangeDetectListener; import org.communiquons.android.comunic.client.ui.listeners.OnScrollChangeDetectListener;
import org.communiquons.android.comunic.client.ui.utils.BitmapUtils; import org.communiquons.android.comunic.client.ui.utils.BitmapUtils;
import org.communiquons.android.comunic.client.ui.utils.UiUtils; import org.communiquons.android.comunic.client.ui.utils.UiUtils;
@ -57,7 +63,8 @@ import static android.app.Activity.RESULT_OK;
public class ConversationFragment extends Fragment public class ConversationFragment extends Fragment
implements ConversationRefreshRunnable.onMessagesChangeListener, implements ConversationRefreshRunnable.onMessagesChangeListener,
OnScrollChangeDetectListener { OnScrollChangeDetectListener, OnConversationMessageActionsListener,
PopupMenu.OnMenuItemClickListener {
/** /**
* Pick image request number * Pick image request number
@ -89,6 +96,11 @@ public class ConversationFragment extends Fragment
*/ */
private int last_message_id = 0; private int last_message_id = 0;
/**
* Current user ID
*/
private int userID;
/** /**
* The list of messages of the conversation * The list of messages of the conversation
*/ */
@ -174,6 +186,16 @@ public class ConversationFragment extends Fragment
*/ */
private AsyncTask mGetOlderMessagesTask; private AsyncTask mGetOlderMessagesTask;
/**
* Current conversation message in context menu
*/
private int mMessageInContextMenu;
/**
* Safely delete message
*/
private DeleteConversationMessageTask mDeleteMessageAsyncTask;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -237,7 +259,7 @@ public class ConversationFragment extends Fragment
mAppBar = view.findViewById(R.id.appbar); mAppBar = view.findViewById(R.id.appbar);
//Need user ID //Need user ID
int userID = new AccountUtils(getActivity()).get_current_user_id(); userID = new AccountUtils(getActivity()).get_current_user_id();
//Initialize toolbar //Initialize toolbar
mAppBar.addBackButton(new View.OnClickListener() { mAppBar.addBackButton(new View.OnClickListener() {
@ -258,6 +280,7 @@ public class ConversationFragment extends Fragment
//Create the adapter //Create the adapter
convMessAdapter = new ConversationMessageAdapter(getActivity(), convMessAdapter = new ConversationMessageAdapter(getActivity(),
messagesList, userID); messagesList, userID);
convMessAdapter.setOnConversationMessageActionsListener(this);
//Apply adapter //Apply adapter
mLinearLayoutManager = new LinearLayoutManager(getActivity()); mLinearLayoutManager = new LinearLayoutManager(getActivity());
@ -369,6 +392,14 @@ public class ConversationFragment extends Fragment
} }
@Override
public void onDestroy() {
super.onDestroy();
if(mDeleteMessageAsyncTask != null)
mDeleteMessageAsyncTask.setOnPostExecuteListener(null);
}
@Override @Override
public void onNoMessage() { public void onNoMessage() {
@ -730,4 +761,92 @@ public class ConversationFragment extends Fragment
//Refresh user information if required //Refresh user information if required
refreshUserInfo(); refreshUserInfo();
} }
@Override
public void onOpenContextMenu(int pos, View v) {
mMessageInContextMenu = pos;
ConversationMessage message = messagesList.get(pos);
PopupMenu popup = new PopupMenu(getActivity(), v);
popup.inflate(R.menu.menu_conversation_message);
if(message.getUser_id() != userID)
popup.getMenu().findItem(R.id.action_delete).setEnabled(false);
popup.setOnMenuItemClickListener(this);
popup.show();
}
@Override
public boolean onMenuItemClick(MenuItem item) {
if(item.getItemId() == R.id.action_delete){
onConfirmDeleteConversationMessage(mMessageInContextMenu);
return true;
}
return false;
}
@Override
public void onConfirmDeleteConversationMessage(final int pos) {
new AlertDialog.Builder(getActivity())
.setTitle(R.string.dialog_delete_conversation_message_title)
.setMessage(R.string.dialog_delete_conversation_message_message)
.setNegativeButton(R.string.dialog_delete_conversation_message_cancel, null)
.setPositiveButton(R.string.dialog_delete_conversation_message_confirm,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
deleteConversationMessage(pos);
}
})
.show();
}
/**
* Delete conversation message at a specified position
*
* @param pos The position of the message to delete
*/
private void deleteConversationMessage(final int pos){
mDeleteMessageAsyncTask = new DeleteConversationMessageTask(getActivity());
mDeleteMessageAsyncTask.setOnPostExecuteListener(new SafeAsyncTask.OnPostExecuteListener<Boolean>() {
@Override
public void OnPostExecute(Boolean result) {
deleteConversationMessagesCallback(pos, result);
}
});
mDeleteMessageAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
messagesList.get(pos).getId());
}
/**
* Delete conversation message callback
*
* @param pos The position of the message
* @param result Result of the operation
*/
private void deleteConversationMessagesCallback(int pos, boolean result){
if(getActivity() == null)
return;
if(!result) {
Toast.makeText(getActivity(), R.string.err_delete_conversation_message,
Toast.LENGTH_SHORT).show();
return;
}
messagesList.remove(pos);
convMessAdapter.notifyDataSetChanged();
}
} }

View File

@ -0,0 +1,29 @@
package org.communiquons.android.comunic.client.ui.listeners;
import android.view.View;
import org.communiquons.android.comunic.client.data.models.ConversationMessage;
/**
* Listener for actions on conversation messages
*
* @author Pierre HUBERT
*/
public interface OnConversationMessageActionsListener {
/**
* Open messages context menu for message at a specified position
*
* @param pos The position of the context menu
* @param v The view to display the context menu
*/
void onOpenContextMenu(int pos, View v);
/**
* Ask the user to confirm the deletion of a conversation message
*
* @param pos The position of the message to delete
*/
void onConfirmDeleteConversationMessage(int pos);
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_delete"
android:title="@string/action_delete" />
</menu>

View File

@ -244,4 +244,8 @@
<string name="action_follow">Suivre</string> <string name="action_follow">Suivre</string>
<string name="button_follow">Suivre</string> <string name="button_follow">Suivre</string>
<string name="button_following">Suivi</string> <string name="button_following">Suivi</string>
<string name="action_delete">Supprimer</string>
<string name="activity_about_title">A propos</string>
<string name="dialog_open_source_licenses_title">Licences Open Source</string>
<string name="btn_open_source_licences">Licences Open Source</string>
</resources> </resources>

View File

@ -246,4 +246,10 @@
<string name="action_follow">Follow</string> <string name="action_follow">Follow</string>
<string name="button_follow">Follow</string> <string name="button_follow">Follow</string>
<string name="button_following">Following</string> <string name="button_following">Following</string>
<string name="action_delete">Delete</string>
<string name="dialog_delete_conversation_message_title">Delete message</string>
<string name="dialog_delete_conversation_message_message">Do you really want to delete this conversation message? Note: This may not have any effect if the other members of the conversation have already downloaded the message!</string>
<string name="dialog_delete_conversation_message_cancel">Cancel</string>
<string name="dialog_delete_conversation_message_confirm">Delete</string>
<string name="err_delete_conversation_message">Could not delete conversation message!</string>
</resources> </resources>