From 84e8850d9f57a8a575f6b1161a8197f7713296e7 Mon Sep 17 00:00:00 2001 From: M M Arif Date: Fri, 18 Mar 2022 09:57:24 +0100 Subject: [PATCH] My issues / update assignees list (#1087) Closes #745 Closes #200 Co-authored-by: M M Arif Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1087 Reviewed-by: qwerty287 --- app/build.gradle | 2 +- .../mian/gitnex/actions/AssigneesActions.java | 5 +- .../activities/CreateIssueActivity.java | 4 +- .../activities/CreatePullRequestActivity.java | 2 +- .../activities/IssueDetailActivity.java | 8 +- .../mian/gitnex/activities/MainActivity.java | 20 ++- .../gitnex/activities/RepoForksActivity.java | 21 +-- .../activities/SettingsGeneralActivity.java | 12 +- .../gitnex/adapters/AssigneesListAdapter.java | 2 + .../gitnex/adapters/ExploreIssuesAdapter.java | 15 +- .../fragments/ExploreIssuesFragment.java | 149 ++++++------------ .../gitnex/fragments/MyIssuesFragment.java | 89 +++++++++++ .../gitnex/fragments/ReleasesFragment.java | 71 ++++----- .../gitnex/fragments/RepoInfoFragment.java | 12 +- .../gitnex/viewmodels/IssuesViewModel.java | 103 ++++++++++++ app/src/main/res/drawable/ic_issue.xml | 15 +- app/src/main/res/drawable/ic_issue_closed.xml | 4 +- .../res/layout/bottom_sheet_issues_filter.xml | 2 +- .../bottom_sheet_pull_request_filter.xml | 2 +- .../custom_assignees_selection_dialog.xml | 4 +- .../layout/custom_labels_selection_dialog.xml | 4 +- app/src/main/res/menu/drawer_menu.xml | 5 + app/src/main/res/values/settings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 24 files changed, 357 insertions(+), 196 deletions(-) create mode 100644 app/src/main/java/org/mian/gitnex/fragments/MyIssuesFragment.java create mode 100644 app/src/main/java/org/mian/gitnex/viewmodels/IssuesViewModel.java diff --git a/app/build.gradle b/app/build.gradle index a75d3ec5..539293fb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,7 +109,7 @@ dependencies { implementation "androidx.work:work-runtime:$work_version" implementation "io.mikael:urlbuilder:2.0.9" implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2" - implementation "org.codeberg.gitnex:tea4j:1.1.1" + implementation "org.codeberg.gitnex:tea4j:1.1.3" coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5" implementation 'androidx.biometric:biometric:1.1.0' implementation 'com.github.chrisvest:stormpot:2.4.2' diff --git a/app/src/main/java/org/mian/gitnex/actions/AssigneesActions.java b/app/src/main/java/org/mian/gitnex/actions/AssigneesActions.java index 706d063b..99065ece 100644 --- a/app/src/main/java/org/mian/gitnex/actions/AssigneesActions.java +++ b/app/src/main/java/org/mian/gitnex/actions/AssigneesActions.java @@ -13,7 +13,6 @@ import org.mian.gitnex.adapters.AssigneesListAdapter; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding; import org.mian.gitnex.helpers.Toasty; -import org.mian.gitnex.helpers.contexts.AccountContext; import java.util.List; import retrofit2.Call; import retrofit2.Callback; @@ -66,7 +65,7 @@ public class AssigneesActions { Call> call = RetrofitClient .getApiInterface(ctx) - .getCollaborators(((BaseActivity) ctx).getAccount().getAuthorization(), repoOwner, repoName); + .getAllAssignees(((BaseActivity) ctx).getAccount().getAuthorization(), repoOwner, repoName); call.enqueue(new Callback>() { @@ -85,8 +84,6 @@ public class AssigneesActions { if(assigneesList_.size() > 0) { - AccountContext userInfo = ((BaseActivity) ctx).getAccount(); - assigneesList.add(new Collaborators(userInfo.getFullName(), userInfo.getAccount().getUserName(), userInfo.getUserInfo().getAvatar())); assigneesList.addAll(assigneesList_); } else { diff --git a/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java index 85f74fe5..937a65c5 100644 --- a/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/CreateIssueActivity.java @@ -175,7 +175,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis View view = assigneesBinding.getRoot(); dialogAssignees.setContentView(view); - assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> dialogAssignees.dismiss()); + assigneesBinding.save.setOnClickListener(assigneesBinding_ -> dialogAssignees.dismiss()); dialogAssignees.show(); AssigneesActions.getRepositoryAssignees(ctx, repository.getOwner(), repository.getName(), assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding); @@ -195,7 +195,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis View view = labelsBinding.getRoot(); dialogLabels.setContentView(view); - labelsBinding.cancel.setOnClickListener(labelsBinding_ -> dialogLabels.dismiss()); + labelsBinding.save.setOnClickListener(labelsBinding_ -> dialogLabels.dismiss()); dialogLabels.show(); LabelsActions.getRepositoryLabels(ctx, repository.getOwner(), repository.getName(), labelsList, dialogLabels, labelsAdapter, labelsBinding); diff --git a/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java index 5968ae9b..71328e3a 100644 --- a/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/CreatePullRequestActivity.java @@ -229,7 +229,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis View view = labelsBinding.getRoot(); dialogLabels.setContentView(view); - labelsBinding.cancel.setOnClickListener(editProperties -> dialogLabels.dismiss()); + labelsBinding.save.setOnClickListener(editProperties -> dialogLabels.dismiss()); dialogLabels.show(); LabelsActions.getRepositoryLabels(ctx, repository.getOwner(), repository.getName(), labelsList, dialogLabels, labelsAdapter, labelsBinding); diff --git a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java index 1b28138d..8f10429b 100644 --- a/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/IssueDetailActivity.java @@ -268,7 +268,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt assigneesAdapter.updateList(currentAssignees); dialogAssignees = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert); - dialogAssignees.setCancelable(false); + dialogAssignees.setCancelable(true); if (dialogAssignees.getWindow() != null) { @@ -280,7 +280,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt View view = assigneesBinding.getRoot(); dialogAssignees.setContentView(view); - assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> { + assigneesBinding.save.setOnClickListener(assigneesBinding_ -> { currentAssignees = new ArrayList<>(new LinkedHashSet<>(currentAssignees)); assigneesListData = new ArrayList<>(new LinkedHashSet<>(assigneesListData)); @@ -305,7 +305,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt labelsAdapter.updateList(currentLabelsIds); dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert); - dialogLabels.setCancelable(false); + dialogLabels.setCancelable(true); if (dialogLabels.getWindow() != null) { @@ -317,7 +317,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt View view = labelsBinding.getRoot(); dialogLabels.setContentView(view); - labelsBinding.cancel.setOnClickListener(labelsBinding_ -> { + labelsBinding.save.setOnClickListener(labelsBinding_ -> { currentLabelsIds = new ArrayList<>(new LinkedHashSet<>(currentLabelsIds)); labelsIds = new ArrayList<>(new LinkedHashSet<>(labelsIds)); diff --git a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java index 9b24101b..2c76d5c2 100644 --- a/app/src/main/java/org/mian/gitnex/activities/MainActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/MainActivity.java @@ -38,6 +38,7 @@ import org.mian.gitnex.fragments.AdministrationFragment; import org.mian.gitnex.fragments.BottomSheetDraftsFragment; import org.mian.gitnex.fragments.DraftsFragment; import org.mian.gitnex.fragments.ExploreFragment; +import org.mian.gitnex.fragments.MyIssuesFragment; import org.mian.gitnex.fragments.MyProfileFragment; import org.mian.gitnex.fragments.MyRepositoriesFragment; import org.mian.gitnex.fragments.NotificationsFragment; @@ -161,6 +162,9 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig else if(fragmentById instanceof AdministrationFragment) { toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration)); } + else if(fragmentById instanceof MyIssuesFragment) { + toolbarTitle.setText(getResources().getString(R.string.navMyIssues)); + } getNotificationsCount(instanceToken); @@ -211,7 +215,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig userEmail.setTypeface(myTypeface); userFullName.setTypeface(myTypeface); - if (getAccount().getUserInfo() != null) { String userEmailNav = getAccount().getUserInfo().getEmail(); String userFullNameNav = getAccount().getFullName(); @@ -272,6 +275,10 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig // hide first navigationView.getMenu().findItem(R.id.nav_administration).setVisible(false); } + + if(getAccount().requiresVersion("1.14.0")) { + navigationView.getMenu().findItem(R.id.nav_my_issues).setVisible(true); + } } @Override @@ -401,6 +408,12 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig navigationView.setCheckedItem(R.id.nav_notifications); break; + case 8: + toolbarTitle.setText(getResources().getString(R.string.navMyIssues)); + getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyIssuesFragment()).commit(); + navigationView.setCheckedItem(R.id.nav_my_issues); + break; + default: toolbarTitle.setText(getResources().getString(R.string.navMyRepos)); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit(); @@ -557,6 +570,11 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration)); getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit(); } + else if(id == R.id.nav_my_issues) { + + toolbarTitle.setText(getResources().getString(R.string.navMyIssues)); + getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyIssuesFragment()).commit(); + } drawer.closeDrawer(GravityCompat.START); return true; diff --git a/app/src/main/java/org/mian/gitnex/activities/RepoForksActivity.java b/app/src/main/java/org/mian/gitnex/activities/RepoForksActivity.java index f8f79791..7b3a5da2 100644 --- a/app/src/main/java/org/mian/gitnex/activities/RepoForksActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/RepoForksActivity.java @@ -26,6 +26,7 @@ import org.mian.gitnex.adapters.RepoForksAdapter; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.databinding.ActivityRepoForksBinding; import org.mian.gitnex.helpers.Constants; +import org.mian.gitnex.helpers.contexts.RepositoryContext; import java.util.ArrayList; import java.util.List; import retrofit2.Call; @@ -49,6 +50,8 @@ public class RepoForksActivity extends BaseActivity { private RepoForksAdapter adapter; private ProgressBar progressLoadMore; + private RepositoryContext repository; + @SuppressLint("DefaultLocale") @Override public void onCreate(Bundle savedInstanceState) { @@ -61,11 +64,9 @@ public class RepoForksActivity extends BaseActivity { Toolbar toolbar = activityRepoForksBinding.toolbar; setSupportActionBar(toolbar); - String repoFullNameForForks = getIntent().getStringExtra("repoFullNameForForks"); - assert repoFullNameForForks != null; - String[] parts = repoFullNameForForks.split("/"); - final String repoOwner = parts[0]; - final String repoName = parts[1]; + repository = RepositoryContext.fromIntent(getIntent()); + final String repoOwner = repository.getOwner(); + final String repoName = repository.getName(); activityRepoForksBinding.toolbarTitle.setText(ctx.getResources().getString(R.string.infoTabRepoForksCount)); @@ -75,10 +76,7 @@ public class RepoForksActivity extends BaseActivity { progressBar = activityRepoForksBinding.progressBar; SwipeRefreshLayout swipeRefresh = activityRepoForksBinding.pullToRefresh; - closeActivity.setOnClickListener(v -> { - getIntent().removeExtra("repoFullNameForForks"); - finish(); - }); + closeActivity.setOnClickListener(v -> finish()); // if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances) if(getAccount().requiresVersion("1.12")) { @@ -241,4 +239,9 @@ public class RepoForksActivity extends BaseActivity { adapter.updateList(userRepositories); } + @Override + public void onResume() { + super.onResume(); + repository.checkAccountSwitch(this); + } } diff --git a/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java b/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java index bc1f8052..b04fe5c5 100644 --- a/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java +++ b/app/src/main/java/org/mian/gitnex/activities/SettingsGeneralActivity.java @@ -2,13 +2,10 @@ package org.mian.gitnex.activities; import android.os.Bundle; import android.view.View; -import android.widget.CompoundButton; import androidx.appcompat.app.AlertDialog; -import com.google.android.material.switchmaterial.SwitchMaterial; import org.mian.gitnex.R; import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding; import org.mian.gitnex.helpers.Toasty; -import org.mian.gitnex.helpers.Version; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -50,6 +47,11 @@ public class SettingsGeneralActivity extends BaseActivity { } homeScreenList = new ArrayList<>(Arrays.asList(appHomeDefaultScreen)); + + if(!getAccount().requiresVersion("1.14.0")) { + homeScreenList.remove(8); + } + String[] homeScreenArray = new String[homeScreenList.size()]; homeScreenList.toArray(homeScreenArray); @@ -87,6 +89,10 @@ public class SettingsGeneralActivity extends BaseActivity { viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleNotifications)); } + else if(homeScreenSelectedChoice == 8) { + + viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navMyIssues)); + } viewBinding.homeScreenFrame.setOnClickListener(setDefaultHomeScreen -> { diff --git a/app/src/main/java/org/mian/gitnex/adapters/AssigneesListAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/AssigneesListAdapter.java index ff594d95..64c2c23f 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/AssigneesListAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/AssigneesListAdapter.java @@ -1,5 +1,6 @@ package org.mian.gitnex.adapters; +import android.annotation.SuppressLint; import android.content.Context; import android.text.Html; import android.view.LayoutInflater; @@ -131,6 +132,7 @@ public class AssigneesListAdapter extends RecyclerView.Adapter list) { currentAssignees = list; diff --git a/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java b/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java index 387238e8..8c1f9fd7 100644 --- a/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java +++ b/app/src/main/java/org/mian/gitnex/adapters/ExploreIssuesAdapter.java @@ -43,7 +43,7 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter searchedList; - private Runnable loadMoreListener; + private OnLoadMoreListener loadMoreListener; private boolean isLoading = false, isMoreDataAvailable = true; private final TinyDB tinyDb; @@ -69,7 +69,7 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) { isLoading = true; - loadMoreListener.run(); + loadMoreListener.onLoadMore(); } if(getItemViewType(position) == TYPE_LOAD) { @@ -204,15 +204,24 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter dataList; private ExploreIssuesAdapter adapter; - private int pageSize; + private int page = 1; private final String TAG = Constants.exploreIssues; - private final int resultLimit = Constants.resultLimitOldGiteaInstances; // search issues always return 10 records @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { viewBinding = FragmentSearchIssuesBinding.inflate(inflater, container, false); - context = getContext(); - - dataList = new ArrayList<>(); - adapter = new ExploreIssuesAdapter(dataList, context); viewBinding.searchKeyword.setOnEditorActionListener((v1, actionId, event) -> { if(actionId == EditorInfo.IME_ACTION_SEND) { @@ -60,111 +44,70 @@ public class ExploreIssuesFragment extends Fragment { imm.hideSoftInputFromWindow(viewBinding.searchKeyword.getWindowToken(), 0); viewBinding.progressBar.setVisibility(View.VISIBLE); - loadInitial(String.valueOf(viewBinding.searchKeyword.getText()), resultLimit); - - adapter.setLoadMoreListener(() -> viewBinding.recyclerViewSearchIssues.post(() -> { - if(dataList.size() == resultLimit || pageSize == resultLimit) { - int page = (dataList.size() + resultLimit) / resultLimit; - loadMore(String.valueOf(viewBinding.searchKeyword.getText()), resultLimit, page); - } - })); + fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization(), String.valueOf(viewBinding.searchKeyword.getText())); } } return false; }); viewBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> { + viewBinding.pullToRefresh.setRefreshing(false); - loadInitial("", resultLimit); - adapter.notifyDataChanged(); - }, 200)); - - adapter.setLoadMoreListener(() -> viewBinding.recyclerViewSearchIssues.post(() -> { - if(dataList.size() == resultLimit || pageSize == resultLimit) { - int page = (dataList.size() + resultLimit) / resultLimit; - loadMore(String.valueOf(viewBinding.searchKeyword.getText()), resultLimit, page); + if(!Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString().equals("")) { + fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization(), String.valueOf(viewBinding.searchKeyword.getText())); } - })); + else { + fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization(), ""); + } + viewBinding.progressBar.setVisibility(View.VISIBLE); - DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL); + }, 50)); + + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(requireActivity(), DividerItemDecoration.VERTICAL); viewBinding.recyclerViewSearchIssues.setHasFixedSize(true); viewBinding.recyclerViewSearchIssues.addItemDecoration(dividerItemDecoration); - viewBinding.recyclerViewSearchIssues.setLayoutManager(new LinearLayoutManager(context)); - viewBinding.recyclerViewSearchIssues.setAdapter(adapter); + viewBinding.recyclerViewSearchIssues.setLayoutManager(new LinearLayoutManager(requireActivity())); - loadInitial("", resultLimit); + fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization(), ""); return viewBinding.getRoot(); } - private void loadInitial(String searchKeyword, int resultLimit) { + private void fetchDataAsync(String instanceToken, String searchKeyword) { + + IssuesViewModel issuesModel = new ViewModelProvider(this).get(IssuesViewModel.class); + + issuesModel.getIssuesList(instanceToken, searchKeyword, "issues", null, "open", getContext()).observe(getViewLifecycleOwner(), issuesListMain -> { + + adapter = new ExploreIssuesAdapter(issuesListMain, getContext()); + adapter.setLoadMoreListener(new ExploreIssuesAdapter.OnLoadMoreListener() { + + @Override + public void onLoadMore() { + + page += 1; + IssuesViewModel.loadMoreIssues(instanceToken, searchKeyword, "issues", null, "open", page, getContext(), adapter); + viewBinding.progressBar.setVisibility(View.VISIBLE); + } + + @Override + public void onLoadFinished() { - Call> call = RetrofitClient - .getApiInterface(context).queryIssues(((BaseActivity) requireActivity()).getAccount().getAuthorization(), searchKeyword, "issues", "open", resultLimit, 1); - call.enqueue(new Callback>() { - @Override - public void onResponse(@NonNull Call> call, @NonNull Response> response) { - if(response.isSuccessful()) { - if(response.body() != null && response.body().size() > 0) { - dataList.clear(); - dataList.addAll(response.body()); - adapter.notifyDataChanged(); - viewBinding.noData.setVisibility(View.GONE); - } - else { - dataList.clear(); - adapter.notifyDataChanged(); - viewBinding.noData.setVisibility(View.VISIBLE); - } viewBinding.progressBar.setVisibility(View.GONE); } - else if(response.code() == 404) { - viewBinding.noData.setVisibility(View.VISIBLE); - viewBinding.progressBar.setVisibility(View.GONE); - } - else { - Log.e(TAG, String.valueOf(response.code())); - } + }); + + if(adapter.getItemCount() > 0) { + viewBinding.recyclerViewSearchIssues.setAdapter(adapter); + viewBinding.noData.setVisibility(View.GONE); + } + else { + adapter.notifyDataChanged(); + viewBinding.recyclerViewSearchIssues.setAdapter(adapter); + viewBinding.noData.setVisibility(View.VISIBLE); } - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - Log.e(TAG, t.toString()); - } - }); - } - - private void loadMore(String searchKeyword, int resultLimit, int page) { - - viewBinding.progressBar.setVisibility(View.VISIBLE); - Call> call = RetrofitClient.getApiInterface(context) - .queryIssues(((BaseActivity) requireActivity()).getAccount().getAuthorization(), searchKeyword, "issues", "open", resultLimit, page); - call.enqueue(new Callback>() { - @Override - public void onResponse(@NonNull Call> call, @NonNull Response> response) { - if(response.isSuccessful()) { - assert response.body() != null; - List result = response.body(); - if(result.size() > 0) { - pageSize = result.size(); - dataList.addAll(result); - } - else { - SnackBar.info(context, viewBinding.getRoot(), getString(R.string.noMoreData)); - adapter.setMoreDataAvailable(false); - } - adapter.notifyDataChanged(); - viewBinding.progressBar.setVisibility(View.GONE); - } - else { - Log.e(TAG, String.valueOf(response.code())); - } - } - - @Override - public void onFailure(@NonNull Call> call, @NonNull Throwable t) { - Log.e(TAG, t.toString()); - } + viewBinding.progressBar.setVisibility(View.GONE); }); } } diff --git a/app/src/main/java/org/mian/gitnex/fragments/MyIssuesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/MyIssuesFragment.java new file mode 100644 index 00000000..baf34222 --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/fragments/MyIssuesFragment.java @@ -0,0 +1,89 @@ +package org.mian.gitnex.fragments; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import org.mian.gitnex.activities.BaseActivity; +import org.mian.gitnex.adapters.ExploreIssuesAdapter; +import org.mian.gitnex.databinding.FragmentIssuesBinding; +import org.mian.gitnex.viewmodels.IssuesViewModel; + +/** + * @author M M Arif + */ + +public class MyIssuesFragment extends Fragment { + + private FragmentIssuesBinding fragmentIssuesBinding; + private ExploreIssuesAdapter adapter; + private int page = 1; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + fragmentIssuesBinding = FragmentIssuesBinding.inflate(inflater, container, false); + + fragmentIssuesBinding.recyclerView.setHasFixedSize(true); + fragmentIssuesBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(fragmentIssuesBinding.recyclerView.getContext(), + DividerItemDecoration.VERTICAL); + fragmentIssuesBinding.recyclerView.addItemDecoration(dividerItemDecoration); + + fragmentIssuesBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> { + + fragmentIssuesBinding.pullToRefresh.setRefreshing(false); + IssuesViewModel.loadIssuesList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), null, "issues", true, "open", getContext()); + fragmentIssuesBinding.progressBar.setVisibility(View.VISIBLE); + }, 50)); + + fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization()); + + return fragmentIssuesBinding.getRoot(); + }; + + private void fetchDataAsync(String instanceToken) { + + IssuesViewModel issuesModel = new ViewModelProvider(this).get(IssuesViewModel.class); + + issuesModel.getIssuesList(instanceToken, "", "issues", true, "open", getContext()).observe(getViewLifecycleOwner(), issuesListMain -> { + + adapter = new ExploreIssuesAdapter(issuesListMain, getContext()); + adapter.setLoadMoreListener(new ExploreIssuesAdapter.OnLoadMoreListener() { + + @Override + public void onLoadMore() { + + page += 1; + IssuesViewModel.loadMoreIssues(instanceToken, "", "issues", true, "open", page, getContext(), adapter); + fragmentIssuesBinding.progressBar.setVisibility(View.VISIBLE); + } + + @Override + public void onLoadFinished() { + + fragmentIssuesBinding.progressBar.setVisibility(View.GONE); + } + }); + + if(adapter.getItemCount() > 0) { + fragmentIssuesBinding.recyclerView.setAdapter(adapter); + fragmentIssuesBinding.noDataIssues.setVisibility(View.GONE); + } + else { + adapter.notifyDataChanged(); + fragmentIssuesBinding.recyclerView.setAdapter(adapter); + fragmentIssuesBinding.noDataIssues.setVisibility(View.VISIBLE); + } + + fragmentIssuesBinding.progressBar.setVisibility(View.GONE); + }); + } +} diff --git a/app/src/main/java/org/mian/gitnex/fragments/ReleasesFragment.java b/app/src/main/java/org/mian/gitnex/fragments/ReleasesFragment.java index 222b826d..806b0027 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/ReleasesFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/ReleasesFragment.java @@ -1,6 +1,5 @@ package org.mian.gitnex.fragments; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -9,15 +8,11 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.gitnex.tea4j.models.Releases; import org.mian.gitnex.R; import org.mian.gitnex.activities.BaseActivity; @@ -35,13 +30,10 @@ import java.util.List; public class ReleasesFragment extends Fragment { - private ProgressBar mProgressBar; private ReleasesAdapter adapter; private TagsAdapter tagsAdapter; - private RecyclerView mRecyclerView; - private TextView noDataReleases; - private RepositoryContext repository; + private FragmentReleasesBinding fragmentReleasesBinding; private String releaseTag; private int page = 1; private int pageReleases = 1; @@ -66,31 +58,23 @@ public class ReleasesFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - FragmentReleasesBinding fragmentReleasesBinding = FragmentReleasesBinding.inflate(inflater, container, false); + fragmentReleasesBinding = FragmentReleasesBinding.inflate(inflater, container, false); - noDataReleases = fragmentReleasesBinding.noDataReleases; - - final SwipeRefreshLayout swipeRefresh = fragmentReleasesBinding.pullToRefresh; - - mRecyclerView = fragmentReleasesBinding.recyclerView; - mRecyclerView.setHasFixedSize(true); - mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - - DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(), + fragmentReleasesBinding.recyclerView.setHasFixedSize(true); + fragmentReleasesBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(fragmentReleasesBinding.recyclerView.getContext(), DividerItemDecoration.VERTICAL); - mRecyclerView.addItemDecoration(dividerItemDecoration); + fragmentReleasesBinding.recyclerView.addItemDecoration(dividerItemDecoration); - mProgressBar = fragmentReleasesBinding.progressBar; + fragmentReleasesBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> { - swipeRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> { - - swipeRefresh.setRefreshing(false); + fragmentReleasesBinding.pullToRefresh.setRefreshing(false); if(repository.isReleasesViewTypeIsTag()) { ReleasesViewModel.loadTagsList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext()); } else { ReleasesViewModel.loadReleasesList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext()); } - mProgressBar.setVisibility(View.VISIBLE); + fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE); }, 50)); @@ -106,11 +90,10 @@ public class ReleasesFragment extends Fragment { } else { ReleasesViewModel.loadReleasesList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext()); } - mProgressBar.setVisibility(View.VISIBLE); + fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE); }); return fragmentReleasesBinding.getRoot(); - } private void fetchDataAsync(String instanceToken, String owner, String repo) { @@ -126,31 +109,31 @@ public class ReleasesFragment extends Fragment { public void onLoadMore() { pageReleases += 1; ReleasesViewModel.loadMoreReleases(instanceToken, owner, repo, pageReleases, getContext(), adapter); - mProgressBar.setVisibility(View.VISIBLE); + fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE); } @Override public void onLoadFinished() { - mProgressBar.setVisibility(View.GONE); + fragmentReleasesBinding.progressBar.setVisibility(View.GONE); } }); if(adapter.getItemCount() > 0) { - mRecyclerView.setAdapter(adapter); + fragmentReleasesBinding.recyclerView.setAdapter(adapter); if(releasesListMain != null && releaseTag != null) { int index = getReleaseIndex(releaseTag, releasesListMain); releaseTag = null; if(index != -1) { - mRecyclerView.scrollToPosition(index); + fragmentReleasesBinding.recyclerView.scrollToPosition(index); } } - noDataReleases.setVisibility(View.GONE); + fragmentReleasesBinding.noDataReleases.setVisibility(View.GONE); } else { - adapter.notifyDataSetChanged(); - mRecyclerView.setAdapter(adapter); - noDataReleases.setVisibility(View.VISIBLE); + adapter.notifyDataChanged(); + fragmentReleasesBinding.recyclerView.setAdapter(adapter); + fragmentReleasesBinding.noDataReleases.setVisibility(View.VISIBLE); } - mProgressBar.setVisibility(View.GONE); + fragmentReleasesBinding.progressBar.setVisibility(View.GONE); } }); @@ -163,24 +146,24 @@ public class ReleasesFragment extends Fragment { public void onLoadMore() { page += 1; ReleasesViewModel.loadMoreTags(instanceToken, owner, repo , page, getContext(), tagsAdapter); - mProgressBar.setVisibility(View.VISIBLE); + fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE); } @Override public void onLoadFinished() { - mProgressBar.setVisibility(View.GONE); + fragmentReleasesBinding.progressBar.setVisibility(View.GONE); } }); if(tagsAdapter.getItemCount() > 0) { - mRecyclerView.setAdapter(tagsAdapter); - noDataReleases.setVisibility(View.GONE); + fragmentReleasesBinding.recyclerView.setAdapter(tagsAdapter); + fragmentReleasesBinding.noDataReleases.setVisibility(View.GONE); } else { - tagsAdapter.notifyDataSetChanged(); - mRecyclerView.setAdapter(tagsAdapter); - noDataReleases.setVisibility(View.VISIBLE); + tagsAdapter.notifyDataChanged(); + fragmentReleasesBinding.recyclerView.setAdapter(tagsAdapter); + fragmentReleasesBinding.noDataReleases.setVisibility(View.VISIBLE); } - mProgressBar.setVisibility(View.GONE); + fragmentReleasesBinding.progressBar.setVisibility(View.GONE); } }); diff --git a/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java b/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java index 7a74e98d..ddc5f203 100644 --- a/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java +++ b/app/src/main/java/org/mian/gitnex/fragments/RepoInfoFragment.java @@ -1,7 +1,6 @@ package org.mian.gitnex.fragments; import android.content.Context; -import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -17,11 +16,18 @@ import org.gitnex.tea4j.models.UserRepositories; import org.mian.gitnex.R; import org.mian.gitnex.activities.BaseActivity; import org.mian.gitnex.activities.RepoDetailActivity; +import org.mian.gitnex.activities.RepoForksActivity; import org.mian.gitnex.activities.RepoStargazersActivity; import org.mian.gitnex.activities.RepoWatchersActivity; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.databinding.FragmentRepoInfoBinding; -import org.mian.gitnex.helpers.*; +import org.mian.gitnex.helpers.AlertDialogs; +import org.mian.gitnex.helpers.AppUtil; +import org.mian.gitnex.helpers.ClickListener; +import org.mian.gitnex.helpers.Markdown; +import org.mian.gitnex.helpers.TimeHelper; +import org.mian.gitnex.helpers.TinyDB; +import org.mian.gitnex.helpers.Toasty; import org.mian.gitnex.helpers.contexts.RepositoryContext; import java.util.Locale; import retrofit2.Call; @@ -85,6 +91,8 @@ public class RepoInfoFragment extends Fragment { binding.repoMetaWatchersFrame.setOnClickListener(metaWatchers -> ctx.startActivity(repository.getIntent(ctx, RepoWatchersActivity.class))); + binding.repoMetaForksFrame.setOnClickListener(metaForks -> ctx.startActivity(repository.getIntent(ctx, RepoForksActivity.class))); + binding.repoMetaPullRequestsFrame.setOnClickListener(metaPR -> ((RepoDetailActivity) requireActivity()).mViewPager.setCurrentItem(3)); return binding.getRoot(); diff --git a/app/src/main/java/org/mian/gitnex/viewmodels/IssuesViewModel.java b/app/src/main/java/org/mian/gitnex/viewmodels/IssuesViewModel.java new file mode 100644 index 00000000..6bdcd7df --- /dev/null +++ b/app/src/main/java/org/mian/gitnex/viewmodels/IssuesViewModel.java @@ -0,0 +1,103 @@ +package org.mian.gitnex.viewmodels; + +import android.content.Context; +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; +import org.gitnex.tea4j.models.Issues; +import org.mian.gitnex.activities.BaseActivity; +import org.mian.gitnex.adapters.ExploreIssuesAdapter; +import org.mian.gitnex.clients.RetrofitClient; +import org.mian.gitnex.helpers.Constants; +import java.util.List; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * Author M M Arif + */ + +public class IssuesViewModel extends ViewModel { + + private static MutableLiveData> issuesList; + private static int resultLimit = Constants.resultLimitOldGiteaInstances; + + public LiveData> getIssuesList(String token, String searchKeyword, String type, Boolean created, String state, Context ctx) { + + issuesList = new MutableLiveData<>(); + + // if gitea is 1.12 or higher use the new limit + if(((BaseActivity) ctx).getAccount().requiresVersion("1.12.0")) { + resultLimit = Constants.resultLimitNewGiteaInstances; + } + + loadIssuesList(token, searchKeyword, type, created, state, ctx); + + return issuesList; + } + + public static void loadIssuesList(String token, String searchKeyword, String type, Boolean created, String state, Context ctx) { + + Call> call = RetrofitClient + .getApiInterface(ctx) + .queryIssues(token, searchKeyword, type, created, state, resultLimit, 1); + + call.enqueue(new Callback>() { + + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + + if (response.isSuccessful()) { + issuesList.postValue(response.body()); + } + else { + Log.e("onResponse", String.valueOf(response.code())); + } + } + + @Override + public void onFailure(@NonNull Call> call, Throwable t) { + Log.e("onFailure", t.toString()); + } + }); + } + + public static void loadMoreIssues(String token, String searchKeyword, String type, Boolean created, String state, int page, Context ctx, ExploreIssuesAdapter adapter) { + + Call> call = RetrofitClient + .getApiInterface(ctx) + .queryIssues(token, searchKeyword, type, created, state, resultLimit, page); + + call.enqueue(new Callback>() { + + @Override + public void onResponse(@NonNull Call> call, @NonNull Response> response) { + + if (response.isSuccessful()) { + List list = issuesList.getValue(); + assert list != null; + assert response.body() != null; + + if(response.body().size() != 0) { + list.addAll(response.body()); + adapter.updateList(list); + } + else { + adapter.setMoreDataAvailable(false); + } + } + else { + Log.e("onResponse", String.valueOf(response.code())); + } + } + + @Override + public void onFailure(@NonNull Call> call, @NonNull Throwable t) { + Log.e("onFailure", t.toString()); + } + }); + } +} diff --git a/app/src/main/res/drawable/ic_issue.xml b/app/src/main/res/drawable/ic_issue.xml index 9a371b6b..a651eb29 100644 --- a/app/src/main/res/drawable/ic_issue.xml +++ b/app/src/main/res/drawable/ic_issue.xml @@ -11,17 +11,10 @@ android:strokeColor="?attr/iconsColor" android:strokeLineCap="round"/> - diff --git a/app/src/main/res/drawable/ic_issue_closed.xml b/app/src/main/res/drawable/ic_issue_closed.xml index 3633cbb5..06cb2a06 100644 --- a/app/src/main/res/drawable/ic_issue_closed.xml +++ b/app/src/main/res/drawable/ic_issue_closed.xml @@ -4,14 +4,14 @@ android:viewportWidth="24" android:viewportHeight="24"> + app:drawableStartCompat="@drawable/ic_issue_closed" /> diff --git a/app/src/main/res/layout/bottom_sheet_pull_request_filter.xml b/app/src/main/res/layout/bottom_sheet_pull_request_filter.xml index 80d67320..f628855f 100644 --- a/app/src/main/res/layout/bottom_sheet_pull_request_filter.xml +++ b/app/src/main/res/layout/bottom_sheet_pull_request_filter.xml @@ -46,7 +46,7 @@ android:text="@string/isClosed" android:textColor="?attr/primaryTextColor" android:textSize="16sp" - app:drawableStartCompat="@drawable/ic_done" /> + app:drawableStartCompat="@drawable/ic_issue_closed" /> diff --git a/app/src/main/res/layout/custom_assignees_selection_dialog.xml b/app/src/main/res/layout/custom_assignees_selection_dialog.xml index cc338de0..45a48d99 100644 --- a/app/src/main/res/layout/custom_assignees_selection_dialog.xml +++ b/app/src/main/res/layout/custom_assignees_selection_dialog.xml @@ -84,12 +84,12 @@ android:orientation="vertical" >