356 lines
11 KiB
Java
356 lines
11 KiB
Java
package org.mian.gitnex.fragments;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.view.LayoutInflater;
|
|
import android.view.Menu;
|
|
import android.view.MenuInflater;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.fragment.app.Fragment;
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.gitnex.tea4j.v2.models.NotificationThread;
|
|
import org.mian.gitnex.R;
|
|
import org.mian.gitnex.activities.IssueDetailActivity;
|
|
import org.mian.gitnex.activities.RepoDetailActivity;
|
|
import org.mian.gitnex.adapters.NotificationsAdapter;
|
|
import org.mian.gitnex.clients.RetrofitClient;
|
|
import org.mian.gitnex.databinding.FragmentNotificationsBinding;
|
|
import org.mian.gitnex.helpers.AppUtil;
|
|
import org.mian.gitnex.helpers.Constants;
|
|
import org.mian.gitnex.helpers.SimpleCallback;
|
|
import org.mian.gitnex.helpers.SnackBar;
|
|
import org.mian.gitnex.helpers.contexts.IssueContext;
|
|
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
|
|
|
/**
|
|
* @author opyale
|
|
* @author M M Arif
|
|
*/
|
|
public class NotificationsFragment extends Fragment
|
|
implements NotificationsAdapter.OnNotificationClickedListener,
|
|
NotificationsAdapter.OnMoreClickedListener {
|
|
|
|
private final List<NotificationThread> notificationThreads = new ArrayList<>();
|
|
private FragmentNotificationsBinding viewBinding;
|
|
private NotificationsAdapter notificationsAdapter;
|
|
|
|
private Activity activity;
|
|
private Context context;
|
|
private Menu menu;
|
|
|
|
private int pageCurrentIndex = 1;
|
|
private int pageResultLimit;
|
|
private String currentFilterMode = "unread";
|
|
public static String emptyErrorResponse;
|
|
|
|
@Override
|
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
|
|
|
super.onCreate(savedInstanceState);
|
|
}
|
|
|
|
@Nullable @Override
|
|
public View onCreateView(
|
|
@NonNull LayoutInflater inflater,
|
|
@Nullable ViewGroup container,
|
|
@Nullable Bundle savedInstanceState) {
|
|
|
|
viewBinding = FragmentNotificationsBinding.inflate(inflater, container, false);
|
|
setHasOptionsMenu(true);
|
|
|
|
activity = requireActivity();
|
|
context = getContext();
|
|
|
|
pageResultLimit = Constants.getCurrentResultLimit(context);
|
|
|
|
notificationsAdapter = new NotificationsAdapter(context, notificationThreads, this, this);
|
|
|
|
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context);
|
|
|
|
viewBinding.notifications.setHasFixedSize(true);
|
|
viewBinding.notifications.setLayoutManager(linearLayoutManager);
|
|
viewBinding.notifications.setAdapter(notificationsAdapter);
|
|
|
|
viewBinding.notifications.addOnScrollListener(
|
|
new RecyclerView.OnScrollListener() {
|
|
|
|
@Override
|
|
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
|
|
|
if (!recyclerView.canScrollVertically(1) && dy != 0) {
|
|
pageCurrentIndex++;
|
|
loadNotifications(true);
|
|
}
|
|
|
|
if (currentFilterMode.equalsIgnoreCase("unread")) {
|
|
if (dy > 0 && viewBinding.markAllAsRead.isShown()) {
|
|
viewBinding.markAllAsRead.setVisibility(View.GONE);
|
|
} else if (dy < 0) {
|
|
viewBinding.markAllAsRead.setVisibility(View.VISIBLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onScrollStateChanged(
|
|
@NonNull RecyclerView recyclerView, int newState) {
|
|
super.onScrollStateChanged(recyclerView, newState);
|
|
}
|
|
});
|
|
|
|
viewBinding.markAllAsRead.setOnClickListener(
|
|
v1 ->
|
|
RetrofitClient.getApiInterface(context)
|
|
.notifyReadList(
|
|
null, "false", Arrays.asList("unread", "pinned"), "read")
|
|
.enqueue(
|
|
(SimpleCallback<List<NotificationThread>>)
|
|
(call, voidResponse) -> {
|
|
if (voidResponse.isPresent()
|
|
&& voidResponse.get().isSuccessful()) {
|
|
SnackBar.success(
|
|
context,
|
|
requireActivity()
|
|
.findViewById(
|
|
android.R.id
|
|
.content),
|
|
getString(
|
|
R.string
|
|
.markedNotificationsAsRead));
|
|
pageCurrentIndex = 1;
|
|
loadNotifications(false);
|
|
} else {
|
|
|
|
if (!emptyErrorResponse.isEmpty()) {
|
|
if (emptyErrorResponse.contains(
|
|
"205")) {
|
|
|
|
SnackBar.success(
|
|
context,
|
|
requireActivity()
|
|
.findViewById(
|
|
android.R.id
|
|
.content),
|
|
getString(
|
|
R.string
|
|
.markedNotificationsAsRead));
|
|
pageCurrentIndex = 1;
|
|
loadNotifications(false);
|
|
}
|
|
} else {
|
|
|
|
activity.runOnUiThread(
|
|
() ->
|
|
SnackBar.error(
|
|
context,
|
|
requireActivity()
|
|
.findViewById(
|
|
android
|
|
.R
|
|
.id
|
|
.content),
|
|
getString(
|
|
R.string
|
|
.genericError)));
|
|
}
|
|
}
|
|
}));
|
|
|
|
viewBinding.pullToRefresh.setOnRefreshListener(
|
|
() -> {
|
|
viewBinding.pullToRefresh.setRefreshing(false);
|
|
pageCurrentIndex = 1;
|
|
loadNotifications(false);
|
|
});
|
|
|
|
loadNotifications(true);
|
|
return viewBinding.getRoot();
|
|
}
|
|
|
|
private void loadNotifications(boolean append) {
|
|
|
|
viewBinding.noDataNotifications.setVisibility(View.GONE);
|
|
viewBinding.progressBar.setVisibility(View.VISIBLE);
|
|
String[] filter =
|
|
currentFilterMode.equals("read")
|
|
? new String[] {"pinned", "read"}
|
|
: new String[] {"pinned", "unread"};
|
|
|
|
RetrofitClient.getApiInterface(context)
|
|
.notifyGetList(
|
|
false,
|
|
Arrays.asList(filter),
|
|
null,
|
|
null,
|
|
null,
|
|
pageCurrentIndex,
|
|
pageResultLimit)
|
|
.enqueue(
|
|
(SimpleCallback<List<NotificationThread>>)
|
|
(call1, listResponse) -> {
|
|
if (listResponse.isPresent()
|
|
&& listResponse.get().isSuccessful()
|
|
&& listResponse.get().body() != null) {
|
|
if (!append) {
|
|
notificationThreads.clear();
|
|
}
|
|
|
|
if (listResponse.get().body() != null) {
|
|
notificationThreads.addAll(
|
|
Objects.requireNonNull(
|
|
listResponse.get().body()));
|
|
} else {
|
|
notificationsAdapter.setMoreDataAvailable(false);
|
|
}
|
|
|
|
if (!append
|
|
|| Objects.requireNonNull(listResponse.get().body())
|
|
.size()
|
|
> 0) {
|
|
notificationsAdapter.notifyDataChanged();
|
|
}
|
|
}
|
|
|
|
AppUtil.setMultiVisibility(View.GONE, viewBinding.progressBar);
|
|
|
|
if (notificationThreads.isEmpty()) {
|
|
viewBinding.noDataNotifications.setVisibility(View.VISIBLE);
|
|
} else {
|
|
viewBinding.noDataNotifications.setVisibility(View.GONE);
|
|
}
|
|
|
|
if (currentFilterMode.equalsIgnoreCase("unread")) {
|
|
if (notificationThreads.isEmpty()) {
|
|
viewBinding.markAllAsRead.setVisibility(View.GONE);
|
|
} else {
|
|
viewBinding.markAllAsRead.setVisibility(View.VISIBLE);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private void changeFilterMode() {
|
|
|
|
int filterIcon =
|
|
currentFilterMode.equalsIgnoreCase("read")
|
|
? R.drawable.ic_filter_closed
|
|
: R.drawable.ic_filter;
|
|
|
|
menu.getItem(0).setIcon(filterIcon);
|
|
|
|
if (currentFilterMode.equalsIgnoreCase("read")) {
|
|
viewBinding.markAllAsRead.setVisibility(View.GONE);
|
|
} else {
|
|
viewBinding.markAllAsRead.setVisibility(View.VISIBLE);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
|
|
|
this.menu = menu;
|
|
inflater.inflate(R.menu.filter_menu_notifications, menu);
|
|
changeFilterMode();
|
|
|
|
super.onCreateOptionsMenu(menu, inflater);
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
|
|
|
if (item.getItemId() == R.id.filterNotifications) {
|
|
|
|
BottomSheetNotificationsFilterFragment bottomSheetNotificationsFilterFragment =
|
|
new BottomSheetNotificationsFilterFragment();
|
|
bottomSheetNotificationsFilterFragment.show(
|
|
getChildFragmentManager(), "notificationsFilterBottomSheet");
|
|
bottomSheetNotificationsFilterFragment.setOnClickListener(
|
|
(text) -> {
|
|
currentFilterMode = text;
|
|
changeFilterMode();
|
|
pageCurrentIndex = 1;
|
|
loadNotifications(false);
|
|
});
|
|
return true;
|
|
}
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
|
|
@Override
|
|
public void onNotificationClicked(NotificationThread notificationThread) {
|
|
|
|
if (notificationThread.isUnread() && !notificationThread.isPinned()) {
|
|
RetrofitClient.getApiInterface(context)
|
|
.notifyReadThread(String.valueOf(notificationThread.getId()), "read")
|
|
.enqueue(
|
|
(SimpleCallback<NotificationThread>)
|
|
(call, voidResponse) -> {
|
|
// reload without any checks, because Gitea returns a 205
|
|
// and Java expects this to be empty
|
|
// but Gitea send a response -> results in a call of
|
|
// onFailure and no response is present
|
|
// if(voidResponse.isPresent() &&
|
|
// voidResponse.get().isSuccessful()) {
|
|
pageCurrentIndex = 1;
|
|
loadNotifications(false);
|
|
// }
|
|
});
|
|
}
|
|
|
|
if (StringUtils.containsAny(
|
|
notificationThread.getSubject().getType().toLowerCase(), "pull", "issue")) {
|
|
|
|
RepositoryContext repo =
|
|
new RepositoryContext(
|
|
notificationThread.getRepository().getOwner().getLogin(),
|
|
notificationThread.getRepository().getName(),
|
|
context); // we can't use the repository object here directly because
|
|
// the permissions are missing
|
|
String issueUrl = notificationThread.getSubject().getUrl();
|
|
|
|
repo.saveToDB(context);
|
|
|
|
Intent intent =
|
|
new IssueContext(
|
|
repo,
|
|
Integer.parseInt(
|
|
issueUrl.substring(issueUrl.lastIndexOf("/") + 1)),
|
|
notificationThread.getSubject().getType())
|
|
.getIntent(context, IssueDetailActivity.class);
|
|
intent.putExtra("openedFromLink", "true");
|
|
startActivity(intent);
|
|
} else if (notificationThread.getSubject().getType().equalsIgnoreCase("repository")) {
|
|
startActivity(
|
|
new RepositoryContext(notificationThread.getRepository(), context)
|
|
.getIntent(context, RepoDetailActivity.class));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onMoreClicked(NotificationThread notificationThread) {
|
|
BottomSheetNotificationsFragment bottomSheetNotificationsFragment =
|
|
new BottomSheetNotificationsFragment();
|
|
bottomSheetNotificationsFragment.onAttach(
|
|
context,
|
|
notificationThread,
|
|
() -> {
|
|
pageCurrentIndex = 1;
|
|
loadNotifications(false);
|
|
});
|
|
bottomSheetNotificationsFragment.show(
|
|
getChildFragmentManager(), "notificationsBottomSheet");
|
|
}
|
|
}
|