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.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; 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.database.api.BaseApi; import org.mian.gitnex.database.api.RepositoriesApi; import org.mian.gitnex.database.models.Repository; 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.TinyDB; import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.contexts.IssueContext; import org.mian.gitnex.helpers.contexts.RepositoryContext; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; /** * Author opyale * Modified M M Arif */ public class NotificationsFragment extends Fragment implements NotificationsAdapter.OnNotificationClickedListener, NotificationsAdapter.OnMoreClickedListener { private FragmentNotificationsBinding viewBinding; private final List notificationThreads = new ArrayList<>(); private NotificationsAdapter notificationsAdapter; private Activity activity; private Context context; private Menu menu; private int pageCurrentIndex = 1; private int pageResultLimit; private String currentFilterMode = "unread"; @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); DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(viewBinding.notifications.getContext(), DividerItemDecoration.VERTICAL); viewBinding.notifications.setHasFixedSize(true); viewBinding.notifications.setLayoutManager(linearLayoutManager); viewBinding.notifications.setAdapter(notificationsAdapter); viewBinding.notifications.addItemDecoration(dividerItemDecoration); 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(new Date(), "true", Arrays.asList("unread", "pinned"), "read") .enqueue((SimpleCallback>) (call, voidResponse) -> { if(voidResponse.isPresent() && voidResponse.get().isSuccessful()) { Toasty.success(context, getString(R.string.markedNotificationsAsRead)); pageCurrentIndex = 1; loadNotifications(false); } else { activity.runOnUiThread(() -> Toasty.error(context, 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>) (call1, listResponse) -> { if(listResponse.isPresent() && listResponse.get().isSuccessful() && listResponse.get().body() != null) { if(!append) { notificationThreads.clear(); } if(listResponse.get().body().size() > 0) { notificationThreads.addAll(listResponse.get().body()); } else { notificationsAdapter.setMoreDataAvailable(false); } if(!append || listResponse.get().body().size() > 0) { notificationsAdapter.notifyDataSetChanged(); } } 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) (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"); } }