Browse Source

Add manual mark as seen menu item in thread when auto mark is disabled

renovate/org.robolectric-robolectric-4.x
Ammar Githam 4 years ago
parent
commit
9cdbd89328
  1. 59
      app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java
  2. 14
      app/src/main/java/awais/instagrabber/managers/ThreadManager.java
  3. 34
      app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java
  4. 2
      app/src/main/res/menu/dm_thread_menu.xml
  5. 1
      app/src/main/res/values/strings.xml

59
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.repositories.responses.directmessages.RankedRecipient;
import awais.instagrabber.utils.AppExecutors; import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DMUtils;
import awais.instagrabber.utils.DownloadUtils; import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.PermissionUtils; import awais.instagrabber.utils.PermissionUtils;
import awais.instagrabber.utils.ResponseBodyUtils; import awais.instagrabber.utils.ResponseBodyUtils;
@ -317,6 +318,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
backStackSavedStateResultLiveData.postValue(null); backStackSavedStateResultLiveData.postValue(null);
}; };
private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0); private final MutableLiveData<Integer> inputLength = new MutableLiveData<>(0);
private MenuItem markAsSeenMenuItem;
@Override @Override
public void onCreate(@Nullable final Bundle savedInstanceState) { public void onCreate(@Nullable final Bundle savedInstanceState) {
@ -367,9 +369,13 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
@Override @Override
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
inflater.inflate(R.menu.dm_thread_menu, menu); 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) { 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; return true;
} }
if (itemId == R.id.mark_as_seen) { if (itemId == R.id.mark_as_seen) {
// new ThreadAction().execute("seen", lastMessage);
item.setVisible(false);
handleMarkAsSeen(item);
return true; return true;
} }
if (itemId == R.id.refresh && viewModel != null) { if (itemId == R.id.refresh && viewModel != null) {
@ -396,6 +401,40 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private void handleMarkAsSeen(@NonNull final MenuItem item) {
final LiveData<Resource<Object>> resourceLiveData = viewModel.markAsSeen();
resourceLiveData.observe(getViewLifecycleOwner(), new Observer<Resource<Object>>() {
@Override
public void onChanged(final Resource<Object> 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 @Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
@ -908,9 +947,15 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
} }
private void submitItemsToAdapter(final List<DirectItem> items) { private void submitItemsToAdapter(final List<DirectItem> 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; if (itemsAdapter == null) return;
itemsAdapter.submitList(items, () -> { itemsAdapter.submitList(items, () -> {
itemOrHeaders = itemsAdapter.getList(); itemOrHeaders = itemsAdapter.getList();

14
app/src/main/java/awais/instagrabber/managers/ThreadManager.java

@ -1797,18 +1797,23 @@ public final class ThreadManager {
return inviter; return inviter;
} }
public void markAsSeen(@NonNull final DirectItem directItem) {
public LiveData<Resource<Object>> markAsSeen(@NonNull final DirectItem directItem) {
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
data.postValue(Resource.loading(null));
final Call<DirectItemSeenResponse> request = service.markAsSeen(threadId, directItem); final Call<DirectItemSeenResponse> request = service.markAsSeen(threadId, directItem);
request.enqueue(new Callback<DirectItemSeenResponse>() { request.enqueue(new Callback<DirectItemSeenResponse>() {
@Override @Override
public void onResponse(@NonNull final Call<DirectItemSeenResponse> call, public void onResponse(@NonNull final Call<DirectItemSeenResponse> call,
@NonNull final Response<DirectItemSeenResponse> response) { @NonNull final Response<DirectItemSeenResponse> response) {
if (!response.isSuccessful()) { if (!response.isSuccessful()) {
handleErrorBody(call, response, null);
handleErrorBody(call, response, data);
return; return;
} }
final DirectItemSeenResponse seenResponse = response.body(); 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(); inboxManager.fetchUnseenCount();
final DirectItemSeenResponsePayload payload = seenResponse.getPayload(); final DirectItemSeenResponsePayload payload = seenResponse.getPayload();
if (payload == null) return; if (payload == null) return;
@ -1820,14 +1825,17 @@ public final class ThreadManager {
lastSeenAt.put(currentUser.getPk(), new DirectThreadLastSeenAt(timestamp, directItem.getItemId())); lastSeenAt.put(currentUser.getPk(), new DirectThreadLastSeenAt(timestamp, directItem.getItemId()));
thread.setLastSeenAt(lastSeenAt); thread.setLastSeenAt(lastSeenAt);
setThread(thread, true); setThread(thread, true);
data.postValue(Resource.success(new Object()));
} }
@Override @Override
public void onFailure(@NonNull final Call<DirectItemSeenResponse> call, public void onFailure(@NonNull final Call<DirectItemSeenResponse> call,
@NonNull final Throwable t) { @NonNull final Throwable t) {
Log.e(TAG, "onFailure: ", t); Log.e(TAG, "onFailure: ", t);
data.postValue(Resource.error(t.getMessage(), null));
} }
}); });
return data;
} }
private interface OnSuccessAction { private interface OnSuccessAction {

34
app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java

@ -278,16 +278,24 @@ public class DirectThreadViewModel extends AndroidViewModel {
return threadManager.declineRequest(); return threadManager.declineRequest();
} }
public void markAsSeen() {
if (currentUser == null) return;
public LiveData<Resource<Object>> markAsSeen() {
if (currentUser == null) {
return getSuccessEventResObjectLiveData();
}
final DirectThread thread = getThread().getValue(); final DirectThread thread = getThread().getValue();
if (thread == null) return;
if (thread == null) {
return getSuccessEventResObjectLiveData();
}
final List<DirectItem> items = thread.getItems(); final List<DirectItem> items = thread.getItems();
if (items == null || items.isEmpty()) return;
if (items == null || items.isEmpty()) {
return getSuccessEventResObjectLiveData();
}
final Optional<DirectItem> itemOptional = items.stream() final Optional<DirectItem> itemOptional = items.stream()
.filter(item -> item.getUserId() != currentUser.getPk()) .filter(item -> item.getUserId() != currentUser.getPk())
.findFirst(); .findFirst();
if (!itemOptional.isPresent()) return;
if (!itemOptional.isPresent()) {
return getSuccessEventResObjectLiveData();
}
final DirectItem directItem = itemOptional.get(); final DirectItem directItem = itemOptional.get();
final Map<Long, DirectThreadLastSeenAt> lastSeenAt = thread.getLastSeenAt(); final Map<Long, DirectThreadLastSeenAt> lastSeenAt = thread.getLastSeenAt();
if (lastSeenAt != null) { if (lastSeenAt != null) {
@ -296,11 +304,20 @@ public class DirectThreadViewModel extends AndroidViewModel {
if (seenAt != null if (seenAt != null
&& (Objects.equals(seenAt.getItemId(), directItem.getItemId()) && (Objects.equals(seenAt.getItemId(), directItem.getItemId())
|| Long.parseLong(seenAt.getTimestamp()) >= directItem.getTimestamp())) { || 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<Resource<Object>> getSuccessEventResObjectLiveData() {
final MutableLiveData<Resource<Object>> data = new MutableLiveData<>();
data.postValue(Resource.success(new Object()));
return data;
} }
public void deleteThreadIfRequired() { public void deleteThreadIfRequired() {
@ -311,4 +328,5 @@ public class DirectThreadViewModel extends AndroidViewModel {
inboxManager.removeThread(threadId); inboxManager.removeThread(threadId);
} }
} }
} }

2
app/src/main/res/menu/dm_thread_menu.xml

@ -8,7 +8,7 @@
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item <item
android:id="@+id/mark_as_seen" android:id="@+id/mark_as_seen"
android:icon="@drawable/ic_outline_views_24"
android:icon="@drawable/ic_check_all_24"
android:title="@string/mark_as_seen" android:title="@string/mark_as_seen"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item <item

1
app/src/main/res/values/strings.xml

@ -466,4 +466,5 @@
<string name="generic_null_response">Response is null!</string> <string name="generic_null_response">Response is null!</string>
<string name="generic_not_ok_response">Response status is not ok!</string> <string name="generic_not_ok_response">Response status is not ok!</string>
<string name="generic_failed_request">Request failed!</string> <string name="generic_failed_request">Request failed!</string>
<string name="marked_as_seen">Marked as seen</string>
</resources> </resources>
Loading…
Cancel
Save