From 9cdbd8932837a413a90f2e69699dfe93e1165f64 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Sat, 20 Mar 2021 21:04:49 +0900 Subject: [PATCH] Add manual mark as seen menu item in thread when auto mark is disabled --- .../DirectMessageThreadFragment.java | 59 ++++++++++++++++--- .../instagrabber/managers/ThreadManager.java | 14 ++++- .../viewmodels/DirectThreadViewModel.java | 34 ++++++++--- app/src/main/res/menu/dm_thread_menu.xml | 2 +- app/src/main/res/values/strings.xml | 1 + 5 files changed, 91 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java index 26b57fa5..d1e4b5f9 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java @@ -100,6 +100,7 @@ import awais.instagrabber.repositories.responses.directmessages.DirectThread; import awais.instagrabber.repositories.responses.directmessages.RankedRecipient; import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.Constants; +import awais.instagrabber.utils.DMUtils; import awais.instagrabber.utils.DownloadUtils; import awais.instagrabber.utils.PermissionUtils; import awais.instagrabber.utils.ResponseBodyUtils; @@ -317,6 +318,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact backStackSavedStateResultLiveData.postValue(null); }; private final MutableLiveData inputLength = new MutableLiveData<>(0); + private MenuItem markAsSeenMenuItem; @Override public void onCreate(@Nullable final Bundle savedInstanceState) { @@ -367,9 +369,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact @Override public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) { inflater.inflate(R.menu.dm_thread_menu, menu); - final MenuItem markAsSeenMenuItem = menu.findItem(R.id.mark_as_seen); + markAsSeenMenuItem = menu.findItem(R.id.mark_as_seen); if (markAsSeenMenuItem != null) { - markAsSeenMenuItem.setVisible(false); + if (autoMarkAsSeen) { + markAsSeenMenuItem.setVisible(false); + } else { + markAsSeenMenuItem.setEnabled(false); + } } } @@ -385,8 +391,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact return true; } if (itemId == R.id.mark_as_seen) { - // new ThreadAction().execute("seen", lastMessage); - item.setVisible(false); + handleMarkAsSeen(item); return true; } if (itemId == R.id.refresh && viewModel != null) { @@ -396,6 +401,40 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact return super.onOptionsItemSelected(item); } + private void handleMarkAsSeen(@NonNull final MenuItem item) { + final LiveData> resourceLiveData = viewModel.markAsSeen(); + resourceLiveData.observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(final Resource resource) { + try { + if (resource == null) return; + final Context context = getContext(); + if (context == null) return; + switch (resource.status) { + case SUCCESS: + Toast.makeText(context, R.string.marked_as_seen, Toast.LENGTH_SHORT).show(); + case LOADING: + item.setEnabled(false); + break; + case ERROR: + item.setEnabled(true); + if (resource.message != null) { + Snackbar.make(context, binding.getRoot(), resource.message, Snackbar.LENGTH_LONG).show(); + return; + } + if (resource.resId != 0) { + Snackbar.make(binding.getRoot(), resource.resId, Snackbar.LENGTH_LONG).show(); + return; + } + break; + } + } finally { + resourceLiveData.removeObserver(this); + } + } + }); + } + @Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); @@ -908,9 +947,15 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact } private void submitItemsToAdapter(final List items) { - if (autoMarkAsSeen) { - binding.chats.post(() -> viewModel.markAsSeen()); - } + binding.chats.post(() -> { + if (autoMarkAsSeen) { + viewModel.markAsSeen(); + return; + } + final DirectThread thread = threadLiveData.getValue(); + if (thread == null) return; + markAsSeenMenuItem.setEnabled(!DMUtils.isRead(thread)); + }); if (itemsAdapter == null) return; itemsAdapter.submitList(items, () -> { itemOrHeaders = itemsAdapter.getList(); diff --git a/app/src/main/java/awais/instagrabber/managers/ThreadManager.java b/app/src/main/java/awais/instagrabber/managers/ThreadManager.java index 00457980..90d67df3 100644 --- a/app/src/main/java/awais/instagrabber/managers/ThreadManager.java +++ b/app/src/main/java/awais/instagrabber/managers/ThreadManager.java @@ -1797,18 +1797,23 @@ public final class ThreadManager { return inviter; } - public void markAsSeen(@NonNull final DirectItem directItem) { + public LiveData> markAsSeen(@NonNull final DirectItem directItem) { + final MutableLiveData> data = new MutableLiveData<>(); + data.postValue(Resource.loading(null)); final Call request = service.markAsSeen(threadId, directItem); request.enqueue(new Callback() { @Override public void onResponse(@NonNull final Call call, @NonNull final Response response) { if (!response.isSuccessful()) { - handleErrorBody(call, response, null); + handleErrorBody(call, response, data); return; } final DirectItemSeenResponse seenResponse = response.body(); - if (seenResponse == null) return; + if (seenResponse == null) { + data.postValue(Resource.error(R.string.generic_null_response, null)); + return; + } inboxManager.fetchUnseenCount(); final DirectItemSeenResponsePayload payload = seenResponse.getPayload(); if (payload == null) return; @@ -1820,14 +1825,17 @@ public final class ThreadManager { lastSeenAt.put(currentUser.getPk(), new DirectThreadLastSeenAt(timestamp, directItem.getItemId())); thread.setLastSeenAt(lastSeenAt); setThread(thread, true); + data.postValue(Resource.success(new Object())); } @Override public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { Log.e(TAG, "onFailure: ", t); + data.postValue(Resource.error(t.getMessage(), null)); } }); + return data; } private interface OnSuccessAction { diff --git a/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java index dab20a92..3e2a3603 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java @@ -278,16 +278,24 @@ public class DirectThreadViewModel extends AndroidViewModel { return threadManager.declineRequest(); } - public void markAsSeen() { - if (currentUser == null) return; + public LiveData> markAsSeen() { + if (currentUser == null) { + return getSuccessEventResObjectLiveData(); + } final DirectThread thread = getThread().getValue(); - if (thread == null) return; + if (thread == null) { + return getSuccessEventResObjectLiveData(); + } final List items = thread.getItems(); - if (items == null || items.isEmpty()) return; + if (items == null || items.isEmpty()) { + return getSuccessEventResObjectLiveData(); + } final Optional itemOptional = items.stream() .filter(item -> item.getUserId() != currentUser.getPk()) .findFirst(); - if (!itemOptional.isPresent()) return; + if (!itemOptional.isPresent()) { + return getSuccessEventResObjectLiveData(); + } final DirectItem directItem = itemOptional.get(); final Map lastSeenAt = thread.getLastSeenAt(); if (lastSeenAt != null) { @@ -296,11 +304,20 @@ public class DirectThreadViewModel extends AndroidViewModel { if (seenAt != null && (Objects.equals(seenAt.getItemId(), directItem.getItemId()) || Long.parseLong(seenAt.getTimestamp()) >= directItem.getTimestamp())) { - return; + return getSuccessEventResObjectLiveData(); } - } catch (Exception ignored) {} + } catch (Exception ignored) { + return getSuccessEventResObjectLiveData(); + } } - threadManager.markAsSeen(directItem); + return threadManager.markAsSeen(directItem); + } + + @NonNull + private MutableLiveData> getSuccessEventResObjectLiveData() { + final MutableLiveData> data = new MutableLiveData<>(); + data.postValue(Resource.success(new Object())); + return data; } public void deleteThreadIfRequired() { @@ -311,4 +328,5 @@ public class DirectThreadViewModel extends AndroidViewModel { inboxManager.removeThread(threadId); } } + } diff --git a/app/src/main/res/menu/dm_thread_menu.xml b/app/src/main/res/menu/dm_thread_menu.xml index 34d72c66..25c19c93 100644 --- a/app/src/main/res/menu/dm_thread_menu.xml +++ b/app/src/main/res/menu/dm_thread_menu.xml @@ -8,7 +8,7 @@ app:showAsAction="ifRoom" /> Response is null! Response status is not ok! Request failed! + Marked as seen