Allow unsend message

This commit is contained in:
Ammar Githam 2021-01-15 03:28:30 +09:00
parent 6a163454f4
commit 8e3d0af9d3
10 changed files with 125 additions and 25 deletions

View File

@ -4,6 +4,7 @@ import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.AdapterListUpdateCallback;
@ -392,6 +393,8 @@ public final class DirectItemsAdapter extends RecyclerView.Adapter<RecyclerView.
void onReaction(DirectItem item, Emoji emoji);
void onReactionClick(DirectItem item, int position);
void onOptionSelect(DirectItem item, @IdRes int itemId);
}
public interface DirectItemInternalLongClickListener {

View File

@ -81,4 +81,9 @@ public class DirectItemActionLogViewHolder extends DirectItemViewHolder {
protected boolean showMessageInfo() {
return false;
}
@Override
protected boolean allowLongClick() {
return false;
}
}

View File

@ -30,4 +30,9 @@ public class DirectItemDefaultViewHolder extends DirectItemViewHolder {
final Context context = itemView.getContext();
binding.tvMessage.setText(context.getText(R.string.dms_inbox_raven_message_unknown));
}
@Override
protected boolean allowLongClick() {
return false;
}
}

View File

@ -33,4 +33,9 @@ public class DirectItemPlaceholderViewHolder extends DirectItemViewHolder {
protected boolean showBackground() {
return true;
}
@Override
protected boolean allowLongClick() {
return false;
}
}

View File

@ -71,4 +71,9 @@ public class DirectItemVideoCallEventViewHolder extends DirectItemViewHolder {
protected boolean showMessageInfo() {
return false;
}
@Override
protected boolean allowLongClick() {
return false;
}
}

View File

@ -22,6 +22,7 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.transition.TransitionManager;
import com.google.android.material.transition.MaterialFade;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.stream.Collectors;
@ -110,7 +111,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder {
final MessageDirection messageDirection = isSelf(item) ? MessageDirection.OUTGOING : MessageDirection.INCOMING;
itemView.post(() -> bindBase(item, messageDirection, position));
itemView.post(() -> bindItem(item, messageDirection));
itemView.post(() -> setupLongClickListener(position));
itemView.post(() -> setupLongClickListener(position, messageDirection));
// bindBase(item, messageDirection);
// bindItem(item, messageDirection);
// setupLongClickListener(position);
@ -479,7 +480,7 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder {
}
@SuppressLint("ClickableViewAccessibility")
private void setupLongClickListener(final int position) {
private void setupLongClickListener(final int position, final MessageDirection messageDirection) {
if (!allowLongClick()) return;
binding.getRoot().setOnItemLongClickListener(new DirectItemFrameLayout.OnItemLongClickListener() {
@Override
@ -498,17 +499,24 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder {
// longClickListener.onLongClick(position, this);
itemView.post(() -> grow());
setSelected(true);
showLongClickOptions(new Point((int) x, (int) y));
showLongClickOptions(new Point((int) x, (int) y), messageDirection);
}
});
}
private void showLongClickOptions(final Point location) {
final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), allowReaction(), getLongClickOptions());
private void showLongClickOptions(final Point location, final MessageDirection messageDirection) {
final List<DirectItemContextMenu.MenuItem> longClickOptions = getLongClickOptions();
final ImmutableList.Builder<DirectItemContextMenu.MenuItem> builder = ImmutableList.builder();
if (longClickOptions != null) {
builder.addAll(longClickOptions);
}
if (messageDirection == MessageDirection.OUTGOING) {
builder.add(new DirectItemContextMenu.MenuItem(R.id.unsend, R.string.dms_inbox_unsend));
}
final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), allowReaction(), builder.build());
menu.setOnDismissListener(() -> setSelected(false));
menu.setOnReactionClickListener(emoji -> {
callback.onReaction(item, emoji);
});
menu.setOnReactionClickListener(emoji -> callback.onReaction(item, emoji));
menu.setOnOptionSelectListener(itemId -> callback.onOptionSelect(item, itemId));
menu.show(itemView, location);
}

View File

@ -222,6 +222,14 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
public void onReactionClick(final DirectItem item, final int position) {
showReactionsDialog(item);
}
@Override
public void onOptionSelect(final DirectItem item, final int itemId) {
if (itemId == R.id.unsend) {
handleSentMessage(viewModel.unsend(item));
return;
}
}
};
private final DirectItemLongClickListener directItemLongClickListener = position -> {

View File

@ -56,4 +56,10 @@ public interface DirectMessagesRepository {
@POST("/api/v1/direct_v2/threads/{threadId}/remove_admins/")
Call<String> removeAdmins(@Path("threadId") String threadId,
@FieldMap final Map<String, String> form);
@FormUrlEncoded
@POST("/api/v1/direct_v2/threads/{threadId}/items/{itemId}/delete/")
Call<String> deleteItem(@Path("threadId") String threadId,
@Path("itemId") String itemId,
@FieldMap final Map<String, String> form);
}

View File

@ -186,14 +186,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
reactions.setEmojis(emojis);
List<DirectItem> list = this.items.getValue();
list = list == null ? new LinkedList<>() : new LinkedList<>(list);
int index = -1;
for (int i = 0; i < list.size(); i++) {
final DirectItem directItem = list.get(i);
if (directItem.getItemId().equals(item.getItemId())) {
index = i;
break;
}
}
int index = getItemIndex(item, list);
if (index >= 0) {
try {
final DirectItem clone = (DirectItem) list.get(index).clone();
@ -255,14 +248,7 @@ public class DirectThreadViewModel extends AndroidViewModel {
itemClone.setReactions(reactionsClone);
List<DirectItem> list = this.items.getValue();
list = list == null ? new LinkedList<>() : new LinkedList<>(list);
int index = -1;
for (int i = 0; i < list.size(); i++) {
final DirectItem directItem = list.get(i);
if (directItem.getItemId().equals(item.getItemId())) {
index = i;
break;
}
}
int index = getItemIndex(item, list);
if (index >= 0) {
list.set(index, itemClone);
}
@ -272,6 +258,30 @@ public class DirectThreadViewModel extends AndroidViewModel {
}
}
private int removeItem(final DirectItem item) {
if (item == null) return 0;
List<DirectItem> list = this.items.getValue();
list = list == null ? new LinkedList<>() : new LinkedList<>(list);
int index = getItemIndex(item, list);
if (index >= 0) {
list.remove(index);
this.items.postValue(list);
}
return index;
}
private int getItemIndex(final DirectItem item, final List<DirectItem> list) {
int index = -1;
for (int i = 0; i < list.size(); i++) {
final DirectItem directItem = list.get(i);
if (directItem.getItemId().equals(item.getItemId())) {
index = i;
break;
}
}
return index;
}
private void updateItemSent(final String clientContext, final long timestamp) {
if (clientContext == null) return;
List<DirectItem> list = this.items.getValue();
@ -675,7 +685,10 @@ public class DirectThreadViewModel extends AndroidViewModel {
public LiveData<Resource<DirectItem>> sendReaction(final DirectItem item, final Emoji emoji) {
final MutableLiveData<Resource<DirectItem>> data = new MutableLiveData<>();
final Long userId = handleCurrentUser(data);
if (userId == null) return data;
if (userId == null) {
data.postValue(Resource.error("userId is null", null));
return data;
}
final String clientContext = UUID.randomUUID().toString();
// Log.d(TAG, "sendText: sending: itemId: " + directItem.getItemId());
data.postValue(Resource.loading(item));
@ -710,6 +723,39 @@ public class DirectThreadViewModel extends AndroidViewModel {
return data;
}
public LiveData<Resource<DirectItem>> unsend(final DirectItem item) {
final MutableLiveData<Resource<DirectItem>> data = new MutableLiveData<>();
if (item == null) {
data.postValue(Resource.error("item is null", null));
return data;
}
final int index = removeItem(item);
final Call<String> request = service.deleteItem(threadId, item.getItemId());
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
if (response.isSuccessful()) {
// Log.d(TAG, "onResponse: " + response.body());
return;
}
// add the item back if unsuccessful
addItems(index, Collections.singletonList(item));
if (response.errorBody() != null) {
handleErrorBody(call, response, data, item);
return;
}
data.postValue(Resource.error("request was not successful and response error body was null", item));
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
data.postValue(Resource.error(t.getMessage(), item));
Log.e(TAG, "enqueueRequest: onFailure: ", t);
}
});
return data;
}
private void handleBroadcastReactionRequest(final MutableLiveData<Resource<DirectItem>> data,
final DirectItem item,
@NonNull final Call<DirectThreadBroadcastResponse> request) {

View File

@ -238,4 +238,13 @@ public class DirectMessagesService extends BaseService {
);
return repository.removeAdmins(threadId, form);
}
public Call<String> deleteItem(final String threadId,
final String itemId) {
final ImmutableMap<String, String> form = ImmutableMap.of(
"_csrftoken", csrfToken,
"_uuid", deviceUuid
);
return repository.deleteItem(threadId, itemId, form);
}
}