mirror of
https://codeberg.org/gitnex/GitNex.git
synced 2024-12-16 15:48:13 +08:00
My issues / update assignees list (#1087)
Closes #745 Closes #200 Co-authored-by: M M Arif <mmarif@swatian.com> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/1087 Reviewed-by: qwerty287 <qwerty287@noreply.codeberg.org>
This commit is contained in:
parent
5761c3519e
commit
84e8850d9f
@ -109,7 +109,7 @@ dependencies {
|
|||||||
implementation "androidx.work:work-runtime:$work_version"
|
implementation "androidx.work:work-runtime:$work_version"
|
||||||
implementation "io.mikael:urlbuilder:2.0.9"
|
implementation "io.mikael:urlbuilder:2.0.9"
|
||||||
implementation "org.codeberg.gitnex-garage:emoji-java:v5.1.2"
|
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"
|
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
||||||
implementation 'androidx.biometric:biometric:1.1.0'
|
implementation 'androidx.biometric:biometric:1.1.0'
|
||||||
implementation 'com.github.chrisvest:stormpot:2.4.2'
|
implementation 'com.github.chrisvest:stormpot:2.4.2'
|
||||||
|
@ -13,7 +13,6 @@ import org.mian.gitnex.adapters.AssigneesListAdapter;
|
|||||||
import org.mian.gitnex.clients.RetrofitClient;
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
|
import org.mian.gitnex.databinding.CustomAssigneesSelectionDialogBinding;
|
||||||
import org.mian.gitnex.helpers.Toasty;
|
import org.mian.gitnex.helpers.Toasty;
|
||||||
import org.mian.gitnex.helpers.contexts.AccountContext;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
@ -66,7 +65,7 @@ public class AssigneesActions {
|
|||||||
|
|
||||||
Call<List<Collaborators>> call = RetrofitClient
|
Call<List<Collaborators>> call = RetrofitClient
|
||||||
.getApiInterface(ctx)
|
.getApiInterface(ctx)
|
||||||
.getCollaborators(((BaseActivity) ctx).getAccount().getAuthorization(), repoOwner, repoName);
|
.getAllAssignees(((BaseActivity) ctx).getAccount().getAuthorization(), repoOwner, repoName);
|
||||||
|
|
||||||
call.enqueue(new Callback<List<Collaborators>>() {
|
call.enqueue(new Callback<List<Collaborators>>() {
|
||||||
|
|
||||||
@ -85,8 +84,6 @@ public class AssigneesActions {
|
|||||||
|
|
||||||
if(assigneesList_.size() > 0) {
|
if(assigneesList_.size() > 0) {
|
||||||
|
|
||||||
AccountContext userInfo = ((BaseActivity) ctx).getAccount();
|
|
||||||
assigneesList.add(new Collaborators(userInfo.getFullName(), userInfo.getAccount().getUserName(), userInfo.getUserInfo().getAvatar()));
|
|
||||||
assigneesList.addAll(assigneesList_);
|
assigneesList.addAll(assigneesList_);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -175,7 +175,7 @@ public class CreateIssueActivity extends BaseActivity implements View.OnClickLis
|
|||||||
View view = assigneesBinding.getRoot();
|
View view = assigneesBinding.getRoot();
|
||||||
dialogAssignees.setContentView(view);
|
dialogAssignees.setContentView(view);
|
||||||
|
|
||||||
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> dialogAssignees.dismiss());
|
assigneesBinding.save.setOnClickListener(assigneesBinding_ -> dialogAssignees.dismiss());
|
||||||
|
|
||||||
dialogAssignees.show();
|
dialogAssignees.show();
|
||||||
AssigneesActions.getRepositoryAssignees(ctx, repository.getOwner(), repository.getName(), assigneesList, dialogAssignees, assigneesAdapter, assigneesBinding);
|
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();
|
View view = labelsBinding.getRoot();
|
||||||
dialogLabels.setContentView(view);
|
dialogLabels.setContentView(view);
|
||||||
|
|
||||||
labelsBinding.cancel.setOnClickListener(labelsBinding_ -> dialogLabels.dismiss());
|
labelsBinding.save.setOnClickListener(labelsBinding_ -> dialogLabels.dismiss());
|
||||||
|
|
||||||
dialogLabels.show();
|
dialogLabels.show();
|
||||||
LabelsActions.getRepositoryLabels(ctx, repository.getOwner(), repository.getName(), labelsList, dialogLabels, labelsAdapter, labelsBinding);
|
LabelsActions.getRepositoryLabels(ctx, repository.getOwner(), repository.getName(), labelsList, dialogLabels, labelsAdapter, labelsBinding);
|
||||||
|
@ -229,7 +229,7 @@ public class CreatePullRequestActivity extends BaseActivity implements LabelsLis
|
|||||||
View view = labelsBinding.getRoot();
|
View view = labelsBinding.getRoot();
|
||||||
dialogLabels.setContentView(view);
|
dialogLabels.setContentView(view);
|
||||||
|
|
||||||
labelsBinding.cancel.setOnClickListener(editProperties -> dialogLabels.dismiss());
|
labelsBinding.save.setOnClickListener(editProperties -> dialogLabels.dismiss());
|
||||||
|
|
||||||
dialogLabels.show();
|
dialogLabels.show();
|
||||||
LabelsActions.getRepositoryLabels(ctx, repository.getOwner(), repository.getName(), labelsList, dialogLabels, labelsAdapter, labelsBinding);
|
LabelsActions.getRepositoryLabels(ctx, repository.getOwner(), repository.getName(), labelsList, dialogLabels, labelsAdapter, labelsBinding);
|
||||||
|
@ -268,7 +268,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
|
|||||||
|
|
||||||
assigneesAdapter.updateList(currentAssignees);
|
assigneesAdapter.updateList(currentAssignees);
|
||||||
dialogAssignees = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
|
dialogAssignees = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
|
||||||
dialogAssignees.setCancelable(false);
|
dialogAssignees.setCancelable(true);
|
||||||
|
|
||||||
if (dialogAssignees.getWindow() != null) {
|
if (dialogAssignees.getWindow() != null) {
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
|
|||||||
View view = assigneesBinding.getRoot();
|
View view = assigneesBinding.getRoot();
|
||||||
dialogAssignees.setContentView(view);
|
dialogAssignees.setContentView(view);
|
||||||
|
|
||||||
assigneesBinding.cancel.setOnClickListener(assigneesBinding_ -> {
|
assigneesBinding.save.setOnClickListener(assigneesBinding_ -> {
|
||||||
|
|
||||||
currentAssignees = new ArrayList<>(new LinkedHashSet<>(currentAssignees));
|
currentAssignees = new ArrayList<>(new LinkedHashSet<>(currentAssignees));
|
||||||
assigneesListData = new ArrayList<>(new LinkedHashSet<>(assigneesListData));
|
assigneesListData = new ArrayList<>(new LinkedHashSet<>(assigneesListData));
|
||||||
@ -305,7 +305,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
|
|||||||
|
|
||||||
labelsAdapter.updateList(currentLabelsIds);
|
labelsAdapter.updateList(currentLabelsIds);
|
||||||
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
|
dialogLabels = new Dialog(ctx, R.style.ThemeOverlay_MaterialComponents_Dialog_Alert);
|
||||||
dialogLabels.setCancelable(false);
|
dialogLabels.setCancelable(true);
|
||||||
|
|
||||||
if (dialogLabels.getWindow() != null) {
|
if (dialogLabels.getWindow() != null) {
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ public class IssueDetailActivity extends BaseActivity implements LabelsListAdapt
|
|||||||
View view = labelsBinding.getRoot();
|
View view = labelsBinding.getRoot();
|
||||||
dialogLabels.setContentView(view);
|
dialogLabels.setContentView(view);
|
||||||
|
|
||||||
labelsBinding.cancel.setOnClickListener(labelsBinding_ -> {
|
labelsBinding.save.setOnClickListener(labelsBinding_ -> {
|
||||||
|
|
||||||
currentLabelsIds = new ArrayList<>(new LinkedHashSet<>(currentLabelsIds));
|
currentLabelsIds = new ArrayList<>(new LinkedHashSet<>(currentLabelsIds));
|
||||||
labelsIds = new ArrayList<>(new LinkedHashSet<>(labelsIds));
|
labelsIds = new ArrayList<>(new LinkedHashSet<>(labelsIds));
|
||||||
|
@ -38,6 +38,7 @@ import org.mian.gitnex.fragments.AdministrationFragment;
|
|||||||
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
|
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
|
||||||
import org.mian.gitnex.fragments.DraftsFragment;
|
import org.mian.gitnex.fragments.DraftsFragment;
|
||||||
import org.mian.gitnex.fragments.ExploreFragment;
|
import org.mian.gitnex.fragments.ExploreFragment;
|
||||||
|
import org.mian.gitnex.fragments.MyIssuesFragment;
|
||||||
import org.mian.gitnex.fragments.MyProfileFragment;
|
import org.mian.gitnex.fragments.MyProfileFragment;
|
||||||
import org.mian.gitnex.fragments.MyRepositoriesFragment;
|
import org.mian.gitnex.fragments.MyRepositoriesFragment;
|
||||||
import org.mian.gitnex.fragments.NotificationsFragment;
|
import org.mian.gitnex.fragments.NotificationsFragment;
|
||||||
@ -161,6 +162,9 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
|||||||
else if(fragmentById instanceof AdministrationFragment) {
|
else if(fragmentById instanceof AdministrationFragment) {
|
||||||
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
|
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
|
||||||
}
|
}
|
||||||
|
else if(fragmentById instanceof MyIssuesFragment) {
|
||||||
|
toolbarTitle.setText(getResources().getString(R.string.navMyIssues));
|
||||||
|
}
|
||||||
|
|
||||||
getNotificationsCount(instanceToken);
|
getNotificationsCount(instanceToken);
|
||||||
|
|
||||||
@ -211,7 +215,6 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
|||||||
userEmail.setTypeface(myTypeface);
|
userEmail.setTypeface(myTypeface);
|
||||||
userFullName.setTypeface(myTypeface);
|
userFullName.setTypeface(myTypeface);
|
||||||
|
|
||||||
|
|
||||||
if (getAccount().getUserInfo() != null) {
|
if (getAccount().getUserInfo() != null) {
|
||||||
String userEmailNav = getAccount().getUserInfo().getEmail();
|
String userEmailNav = getAccount().getUserInfo().getEmail();
|
||||||
String userFullNameNav = getAccount().getFullName();
|
String userFullNameNav = getAccount().getFullName();
|
||||||
@ -272,6 +275,10 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
|||||||
// hide first
|
// hide first
|
||||||
navigationView.getMenu().findItem(R.id.nav_administration).setVisible(false);
|
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
|
@Override
|
||||||
@ -401,6 +408,12 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
|||||||
navigationView.setCheckedItem(R.id.nav_notifications);
|
navigationView.setCheckedItem(R.id.nav_notifications);
|
||||||
break;
|
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:
|
default:
|
||||||
toolbarTitle.setText(getResources().getString(R.string.navMyRepos));
|
toolbarTitle.setText(getResources().getString(R.string.navMyRepos));
|
||||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyRepositoriesFragment()).commit();
|
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));
|
toolbarTitle.setText(getResources().getString(R.string.pageTitleAdministration));
|
||||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AdministrationFragment()).commit();
|
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);
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
return true;
|
return true;
|
||||||
|
@ -26,6 +26,7 @@ import org.mian.gitnex.adapters.RepoForksAdapter;
|
|||||||
import org.mian.gitnex.clients.RetrofitClient;
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
import org.mian.gitnex.databinding.ActivityRepoForksBinding;
|
import org.mian.gitnex.databinding.ActivityRepoForksBinding;
|
||||||
import org.mian.gitnex.helpers.Constants;
|
import org.mian.gitnex.helpers.Constants;
|
||||||
|
import org.mian.gitnex.helpers.contexts.RepositoryContext;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
@ -49,6 +50,8 @@ public class RepoForksActivity extends BaseActivity {
|
|||||||
private RepoForksAdapter adapter;
|
private RepoForksAdapter adapter;
|
||||||
private ProgressBar progressLoadMore;
|
private ProgressBar progressLoadMore;
|
||||||
|
|
||||||
|
private RepositoryContext repository;
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -61,11 +64,9 @@ public class RepoForksActivity extends BaseActivity {
|
|||||||
Toolbar toolbar = activityRepoForksBinding.toolbar;
|
Toolbar toolbar = activityRepoForksBinding.toolbar;
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
String repoFullNameForForks = getIntent().getStringExtra("repoFullNameForForks");
|
repository = RepositoryContext.fromIntent(getIntent());
|
||||||
assert repoFullNameForForks != null;
|
final String repoOwner = repository.getOwner();
|
||||||
String[] parts = repoFullNameForForks.split("/");
|
final String repoName = repository.getName();
|
||||||
final String repoOwner = parts[0];
|
|
||||||
final String repoName = parts[1];
|
|
||||||
|
|
||||||
activityRepoForksBinding.toolbarTitle.setText(ctx.getResources().getString(R.string.infoTabRepoForksCount));
|
activityRepoForksBinding.toolbarTitle.setText(ctx.getResources().getString(R.string.infoTabRepoForksCount));
|
||||||
|
|
||||||
@ -75,10 +76,7 @@ public class RepoForksActivity extends BaseActivity {
|
|||||||
progressBar = activityRepoForksBinding.progressBar;
|
progressBar = activityRepoForksBinding.progressBar;
|
||||||
SwipeRefreshLayout swipeRefresh = activityRepoForksBinding.pullToRefresh;
|
SwipeRefreshLayout swipeRefresh = activityRepoForksBinding.pullToRefresh;
|
||||||
|
|
||||||
closeActivity.setOnClickListener(v -> {
|
closeActivity.setOnClickListener(v -> finish());
|
||||||
getIntent().removeExtra("repoFullNameForForks");
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
|
|
||||||
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
|
// if gitea is 1.12 or higher use the new limit (resultLimitNewGiteaInstances)
|
||||||
if(getAccount().requiresVersion("1.12")) {
|
if(getAccount().requiresVersion("1.12")) {
|
||||||
@ -241,4 +239,9 @@ public class RepoForksActivity extends BaseActivity {
|
|||||||
adapter.updateList(userRepositories);
|
adapter.updateList(userRepositories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
repository.checkAccountSwitch(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,10 @@ package org.mian.gitnex.activities;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import com.google.android.material.switchmaterial.SwitchMaterial;
|
|
||||||
import org.mian.gitnex.R;
|
import org.mian.gitnex.R;
|
||||||
import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding;
|
import org.mian.gitnex.databinding.ActivitySettingsGeneralBinding;
|
||||||
import org.mian.gitnex.helpers.Toasty;
|
import org.mian.gitnex.helpers.Toasty;
|
||||||
import org.mian.gitnex.helpers.Version;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -50,6 +47,11 @@ public class SettingsGeneralActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
homeScreenList = new ArrayList<>(Arrays.asList(appHomeDefaultScreen));
|
homeScreenList = new ArrayList<>(Arrays.asList(appHomeDefaultScreen));
|
||||||
|
|
||||||
|
if(!getAccount().requiresVersion("1.14.0")) {
|
||||||
|
homeScreenList.remove(8);
|
||||||
|
}
|
||||||
|
|
||||||
String[] homeScreenArray = new String[homeScreenList.size()];
|
String[] homeScreenArray = new String[homeScreenList.size()];
|
||||||
homeScreenList.toArray(homeScreenArray);
|
homeScreenList.toArray(homeScreenArray);
|
||||||
|
|
||||||
@ -87,6 +89,10 @@ public class SettingsGeneralActivity extends BaseActivity {
|
|||||||
|
|
||||||
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleNotifications));
|
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.pageTitleNotifications));
|
||||||
}
|
}
|
||||||
|
else if(homeScreenSelectedChoice == 8) {
|
||||||
|
|
||||||
|
viewBinding.homeScreenSelected.setText(getResources().getString(R.string.navMyIssues));
|
||||||
|
}
|
||||||
|
|
||||||
viewBinding.homeScreenFrame.setOnClickListener(setDefaultHomeScreen -> {
|
viewBinding.homeScreenFrame.setOnClickListener(setDefaultHomeScreen -> {
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.mian.gitnex.adapters;
|
package org.mian.gitnex.adapters;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -131,6 +132,7 @@ public class AssigneesListAdapter extends RecyclerView.Adapter<AssigneesListAdap
|
|||||||
return assigneesList.size();
|
return assigneesList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
public void updateList(List<String> list) {
|
public void updateList(List<String> list) {
|
||||||
|
|
||||||
currentAssignees = list;
|
currentAssignees = list;
|
||||||
|
@ -43,7 +43,7 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||||||
private final Context context;
|
private final Context context;
|
||||||
private final int TYPE_LOAD = 0;
|
private final int TYPE_LOAD = 0;
|
||||||
private List<Issues> searchedList;
|
private List<Issues> searchedList;
|
||||||
private Runnable loadMoreListener;
|
private OnLoadMoreListener loadMoreListener;
|
||||||
private boolean isLoading = false, isMoreDataAvailable = true;
|
private boolean isLoading = false, isMoreDataAvailable = true;
|
||||||
private final TinyDB tinyDb;
|
private final TinyDB tinyDb;
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||||
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
|
if(position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
loadMoreListener.run();
|
loadMoreListener.onLoadMore();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getItemViewType(position) == TYPE_LOAD) {
|
if(getItemViewType(position) == TYPE_LOAD) {
|
||||||
@ -204,15 +204,24 @@ public class ExploreIssuesAdapter extends RecyclerView.Adapter<RecyclerView.View
|
|||||||
|
|
||||||
public void setMoreDataAvailable(boolean moreDataAvailable) {
|
public void setMoreDataAvailable(boolean moreDataAvailable) {
|
||||||
isMoreDataAvailable = moreDataAvailable;
|
isMoreDataAvailable = moreDataAvailable;
|
||||||
|
if(!isMoreDataAvailable) {
|
||||||
|
loadMoreListener.onLoadFinished();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
public void notifyDataChanged() {
|
public void notifyDataChanged() {
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
loadMoreListener.onLoadFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoadMoreListener(Runnable loadMoreListener) {
|
public interface OnLoadMoreListener {
|
||||||
|
void onLoadMore();
|
||||||
|
void onLoadFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
|
||||||
this.loadMoreListener = loadMoreListener;
|
this.loadMoreListener = loadMoreListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import android.content.Context;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -12,22 +11,15 @@ import android.view.inputmethod.EditorInfo;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import org.gitnex.tea4j.models.Issues;
|
|
||||||
import org.mian.gitnex.R;
|
|
||||||
import org.mian.gitnex.activities.BaseActivity;
|
import org.mian.gitnex.activities.BaseActivity;
|
||||||
import org.mian.gitnex.adapters.ExploreIssuesAdapter;
|
import org.mian.gitnex.adapters.ExploreIssuesAdapter;
|
||||||
import org.mian.gitnex.clients.RetrofitClient;
|
|
||||||
import org.mian.gitnex.databinding.FragmentSearchIssuesBinding;
|
import org.mian.gitnex.databinding.FragmentSearchIssuesBinding;
|
||||||
import org.mian.gitnex.helpers.Constants;
|
import org.mian.gitnex.helpers.Constants;
|
||||||
import org.mian.gitnex.helpers.SnackBar;
|
import org.mian.gitnex.viewmodels.IssuesViewModel;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Author M M Arif
|
* Author M M Arif
|
||||||
@ -36,22 +28,14 @@ import retrofit2.Response;
|
|||||||
public class ExploreIssuesFragment extends Fragment {
|
public class ExploreIssuesFragment extends Fragment {
|
||||||
|
|
||||||
private FragmentSearchIssuesBinding viewBinding;
|
private FragmentSearchIssuesBinding viewBinding;
|
||||||
private Context context;
|
|
||||||
|
|
||||||
private List<Issues> dataList;
|
|
||||||
private ExploreIssuesAdapter adapter;
|
private ExploreIssuesAdapter adapter;
|
||||||
private int pageSize;
|
private int page = 1;
|
||||||
private final String TAG = Constants.exploreIssues;
|
private final String TAG = Constants.exploreIssues;
|
||||||
private final int resultLimit = Constants.resultLimitOldGiteaInstances; // search issues always return 10 records
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
||||||
viewBinding = FragmentSearchIssuesBinding.inflate(inflater, container, false);
|
viewBinding = FragmentSearchIssuesBinding.inflate(inflater, container, false);
|
||||||
context = getContext();
|
|
||||||
|
|
||||||
dataList = new ArrayList<>();
|
|
||||||
adapter = new ExploreIssuesAdapter(dataList, context);
|
|
||||||
|
|
||||||
viewBinding.searchKeyword.setOnEditorActionListener((v1, actionId, event) -> {
|
viewBinding.searchKeyword.setOnEditorActionListener((v1, actionId, event) -> {
|
||||||
if(actionId == EditorInfo.IME_ACTION_SEND) {
|
if(actionId == EditorInfo.IME_ACTION_SEND) {
|
||||||
@ -60,111 +44,70 @@ public class ExploreIssuesFragment extends Fragment {
|
|||||||
imm.hideSoftInputFromWindow(viewBinding.searchKeyword.getWindowToken(), 0);
|
imm.hideSoftInputFromWindow(viewBinding.searchKeyword.getWindowToken(), 0);
|
||||||
|
|
||||||
viewBinding.progressBar.setVisibility(View.VISIBLE);
|
viewBinding.progressBar.setVisibility(View.VISIBLE);
|
||||||
loadInitial(String.valueOf(viewBinding.searchKeyword.getText()), resultLimit);
|
fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization(), String.valueOf(viewBinding.searchKeyword.getText()));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
viewBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
viewBinding.pullToRefresh.setOnRefreshListener(() -> new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||||
|
|
||||||
viewBinding.pullToRefresh.setRefreshing(false);
|
viewBinding.pullToRefresh.setRefreshing(false);
|
||||||
loadInitial("", resultLimit);
|
if(!Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString().equals("")) {
|
||||||
adapter.notifyDataChanged();
|
fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization(), String.valueOf(viewBinding.searchKeyword.getText()));
|
||||||
}, 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);
|
|
||||||
}
|
}
|
||||||
}));
|
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.setHasFixedSize(true);
|
||||||
viewBinding.recyclerViewSearchIssues.addItemDecoration(dividerItemDecoration);
|
viewBinding.recyclerViewSearchIssues.addItemDecoration(dividerItemDecoration);
|
||||||
viewBinding.recyclerViewSearchIssues.setLayoutManager(new LinearLayoutManager(context));
|
viewBinding.recyclerViewSearchIssues.setLayoutManager(new LinearLayoutManager(requireActivity()));
|
||||||
viewBinding.recyclerViewSearchIssues.setAdapter(adapter);
|
|
||||||
|
|
||||||
loadInitial("", resultLimit);
|
fetchDataAsync(((BaseActivity) requireActivity()).getAccount().getAuthorization(), "");
|
||||||
|
|
||||||
return viewBinding.getRoot();
|
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() {
|
||||||
|
|
||||||
Call<List<Issues>> call = RetrofitClient
|
|
||||||
.getApiInterface(context).queryIssues(((BaseActivity) requireActivity()).getAccount().getAuthorization(), searchKeyword, "issues", "open", resultLimit, 1);
|
|
||||||
call.enqueue(new Callback<List<Issues>>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull Call<List<Issues>> call, @NonNull Response<List<Issues>> response) {
|
public void onLoadMore() {
|
||||||
if(response.isSuccessful()) {
|
|
||||||
if(response.body() != null && response.body().size() > 0) {
|
page += 1;
|
||||||
dataList.clear();
|
IssuesViewModel.loadMoreIssues(instanceToken, searchKeyword, "issues", null, "open", page, getContext(), adapter);
|
||||||
dataList.addAll(response.body());
|
viewBinding.progressBar.setVisibility(View.VISIBLE);
|
||||||
adapter.notifyDataChanged();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished() {
|
||||||
|
|
||||||
|
viewBinding.progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(adapter.getItemCount() > 0) {
|
||||||
|
viewBinding.recyclerViewSearchIssues.setAdapter(adapter);
|
||||||
viewBinding.noData.setVisibility(View.GONE);
|
viewBinding.noData.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dataList.clear();
|
|
||||||
adapter.notifyDataChanged();
|
adapter.notifyDataChanged();
|
||||||
|
viewBinding.recyclerViewSearchIssues.setAdapter(adapter);
|
||||||
viewBinding.noData.setVisibility(View.VISIBLE);
|
viewBinding.noData.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.progressBar.setVisibility(View.GONE);
|
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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull Call<List<Issues>> call, @NonNull Throwable t) {
|
|
||||||
Log.e(TAG, t.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadMore(String searchKeyword, int resultLimit, int page) {
|
|
||||||
|
|
||||||
viewBinding.progressBar.setVisibility(View.VISIBLE);
|
|
||||||
Call<List<Issues>> call = RetrofitClient.getApiInterface(context)
|
|
||||||
.queryIssues(((BaseActivity) requireActivity()).getAccount().getAuthorization(), searchKeyword, "issues", "open", resultLimit, page);
|
|
||||||
call.enqueue(new Callback<List<Issues>>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<List<Issues>> call, @NonNull Response<List<Issues>> response) {
|
|
||||||
if(response.isSuccessful()) {
|
|
||||||
assert response.body() != null;
|
|
||||||
List<Issues> 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<List<Issues>> call, @NonNull Throwable t) {
|
|
||||||
Log.e(TAG, t.toString());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package org.mian.gitnex.fragments;
|
package org.mian.gitnex.fragments;
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@ -9,15 +8,11 @@ import android.view.Menu;
|
|||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import org.gitnex.tea4j.models.Releases;
|
import org.gitnex.tea4j.models.Releases;
|
||||||
import org.mian.gitnex.R;
|
import org.mian.gitnex.R;
|
||||||
import org.mian.gitnex.activities.BaseActivity;
|
import org.mian.gitnex.activities.BaseActivity;
|
||||||
@ -35,13 +30,10 @@ import java.util.List;
|
|||||||
|
|
||||||
public class ReleasesFragment extends Fragment {
|
public class ReleasesFragment extends Fragment {
|
||||||
|
|
||||||
private ProgressBar mProgressBar;
|
|
||||||
private ReleasesAdapter adapter;
|
private ReleasesAdapter adapter;
|
||||||
private TagsAdapter tagsAdapter;
|
private TagsAdapter tagsAdapter;
|
||||||
private RecyclerView mRecyclerView;
|
|
||||||
private TextView noDataReleases;
|
|
||||||
|
|
||||||
private RepositoryContext repository;
|
private RepositoryContext repository;
|
||||||
|
private FragmentReleasesBinding fragmentReleasesBinding;
|
||||||
private String releaseTag;
|
private String releaseTag;
|
||||||
private int page = 1;
|
private int page = 1;
|
||||||
private int pageReleases = 1;
|
private int pageReleases = 1;
|
||||||
@ -66,31 +58,23 @@ public class ReleasesFragment extends Fragment {
|
|||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
FragmentReleasesBinding fragmentReleasesBinding = FragmentReleasesBinding.inflate(inflater, container, false);
|
fragmentReleasesBinding = FragmentReleasesBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
noDataReleases = fragmentReleasesBinding.noDataReleases;
|
fragmentReleasesBinding.recyclerView.setHasFixedSize(true);
|
||||||
|
fragmentReleasesBinding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
final SwipeRefreshLayout swipeRefresh = fragmentReleasesBinding.pullToRefresh;
|
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(fragmentReleasesBinding.recyclerView.getContext(),
|
||||||
|
|
||||||
mRecyclerView = fragmentReleasesBinding.recyclerView;
|
|
||||||
mRecyclerView.setHasFixedSize(true);
|
|
||||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
|
||||||
|
|
||||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView.getContext(),
|
|
||||||
DividerItemDecoration.VERTICAL);
|
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(() -> {
|
fragmentReleasesBinding.pullToRefresh.setRefreshing(false);
|
||||||
|
|
||||||
swipeRefresh.setRefreshing(false);
|
|
||||||
if(repository.isReleasesViewTypeIsTag()) {
|
if(repository.isReleasesViewTypeIsTag()) {
|
||||||
ReleasesViewModel.loadTagsList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext());
|
ReleasesViewModel.loadTagsList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext());
|
||||||
} else {
|
} else {
|
||||||
ReleasesViewModel.loadReleasesList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext());
|
ReleasesViewModel.loadReleasesList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext());
|
||||||
}
|
}
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
}, 50));
|
}, 50));
|
||||||
|
|
||||||
@ -106,11 +90,10 @@ public class ReleasesFragment extends Fragment {
|
|||||||
} else {
|
} else {
|
||||||
ReleasesViewModel.loadReleasesList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext());
|
ReleasesViewModel.loadReleasesList(((BaseActivity) requireActivity()).getAccount().getAuthorization(), repository.getOwner(), repository.getName(), getContext());
|
||||||
}
|
}
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE);
|
||||||
});
|
});
|
||||||
|
|
||||||
return fragmentReleasesBinding.getRoot();
|
return fragmentReleasesBinding.getRoot();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchDataAsync(String instanceToken, String owner, String repo) {
|
private void fetchDataAsync(String instanceToken, String owner, String repo) {
|
||||||
@ -126,31 +109,31 @@ public class ReleasesFragment extends Fragment {
|
|||||||
public void onLoadMore() {
|
public void onLoadMore() {
|
||||||
pageReleases += 1;
|
pageReleases += 1;
|
||||||
ReleasesViewModel.loadMoreReleases(instanceToken, owner, repo, pageReleases, getContext(), adapter);
|
ReleasesViewModel.loadMoreReleases(instanceToken, owner, repo, pageReleases, getContext(), adapter);
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished() {
|
public void onLoadFinished() {
|
||||||
mProgressBar.setVisibility(View.GONE);
|
fragmentReleasesBinding.progressBar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(adapter.getItemCount() > 0) {
|
if(adapter.getItemCount() > 0) {
|
||||||
mRecyclerView.setAdapter(adapter);
|
fragmentReleasesBinding.recyclerView.setAdapter(adapter);
|
||||||
if(releasesListMain != null && releaseTag != null) {
|
if(releasesListMain != null && releaseTag != null) {
|
||||||
int index = getReleaseIndex(releaseTag, releasesListMain);
|
int index = getReleaseIndex(releaseTag, releasesListMain);
|
||||||
releaseTag = null;
|
releaseTag = null;
|
||||||
if(index != -1) {
|
if(index != -1) {
|
||||||
mRecyclerView.scrollToPosition(index);
|
fragmentReleasesBinding.recyclerView.scrollToPosition(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
noDataReleases.setVisibility(View.GONE);
|
fragmentReleasesBinding.noDataReleases.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataChanged();
|
||||||
mRecyclerView.setAdapter(adapter);
|
fragmentReleasesBinding.recyclerView.setAdapter(adapter);
|
||||||
noDataReleases.setVisibility(View.VISIBLE);
|
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() {
|
public void onLoadMore() {
|
||||||
page += 1;
|
page += 1;
|
||||||
ReleasesViewModel.loadMoreTags(instanceToken, owner, repo , page, getContext(), tagsAdapter);
|
ReleasesViewModel.loadMoreTags(instanceToken, owner, repo , page, getContext(), tagsAdapter);
|
||||||
mProgressBar.setVisibility(View.VISIBLE);
|
fragmentReleasesBinding.progressBar.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadFinished() {
|
public void onLoadFinished() {
|
||||||
mProgressBar.setVisibility(View.GONE);
|
fragmentReleasesBinding.progressBar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(tagsAdapter.getItemCount() > 0) {
|
if(tagsAdapter.getItemCount() > 0) {
|
||||||
mRecyclerView.setAdapter(tagsAdapter);
|
fragmentReleasesBinding.recyclerView.setAdapter(tagsAdapter);
|
||||||
noDataReleases.setVisibility(View.GONE);
|
fragmentReleasesBinding.noDataReleases.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tagsAdapter.notifyDataSetChanged();
|
tagsAdapter.notifyDataChanged();
|
||||||
mRecyclerView.setAdapter(tagsAdapter);
|
fragmentReleasesBinding.recyclerView.setAdapter(tagsAdapter);
|
||||||
noDataReleases.setVisibility(View.VISIBLE);
|
fragmentReleasesBinding.noDataReleases.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
mProgressBar.setVisibility(View.GONE);
|
fragmentReleasesBinding.progressBar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.mian.gitnex.fragments;
|
package org.mian.gitnex.fragments;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -17,11 +16,18 @@ import org.gitnex.tea4j.models.UserRepositories;
|
|||||||
import org.mian.gitnex.R;
|
import org.mian.gitnex.R;
|
||||||
import org.mian.gitnex.activities.BaseActivity;
|
import org.mian.gitnex.activities.BaseActivity;
|
||||||
import org.mian.gitnex.activities.RepoDetailActivity;
|
import org.mian.gitnex.activities.RepoDetailActivity;
|
||||||
|
import org.mian.gitnex.activities.RepoForksActivity;
|
||||||
import org.mian.gitnex.activities.RepoStargazersActivity;
|
import org.mian.gitnex.activities.RepoStargazersActivity;
|
||||||
import org.mian.gitnex.activities.RepoWatchersActivity;
|
import org.mian.gitnex.activities.RepoWatchersActivity;
|
||||||
import org.mian.gitnex.clients.RetrofitClient;
|
import org.mian.gitnex.clients.RetrofitClient;
|
||||||
import org.mian.gitnex.databinding.FragmentRepoInfoBinding;
|
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 org.mian.gitnex.helpers.contexts.RepositoryContext;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
@ -85,6 +91,8 @@ public class RepoInfoFragment extends Fragment {
|
|||||||
|
|
||||||
binding.repoMetaWatchersFrame.setOnClickListener(metaWatchers -> ctx.startActivity(repository.getIntent(ctx, RepoWatchersActivity.class)));
|
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));
|
binding.repoMetaPullRequestsFrame.setOnClickListener(metaPR -> ((RepoDetailActivity) requireActivity()).mViewPager.setCurrentItem(3));
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
|
@ -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<List<Issues>> issuesList;
|
||||||
|
private static int resultLimit = Constants.resultLimitOldGiteaInstances;
|
||||||
|
|
||||||
|
public LiveData<List<Issues>> 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<List<Issues>> call = RetrofitClient
|
||||||
|
.getApiInterface(ctx)
|
||||||
|
.queryIssues(token, searchKeyword, type, created, state, resultLimit, 1);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<List<Issues>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<List<Issues>> call, @NonNull Response<List<Issues>> response) {
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
issuesList.postValue(response.body());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.e("onResponse", String.valueOf(response.code()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(@NonNull Call<List<Issues>> 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<List<Issues>> call = RetrofitClient
|
||||||
|
.getApiInterface(ctx)
|
||||||
|
.queryIssues(token, searchKeyword, type, created, state, resultLimit, page);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<List<Issues>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(@NonNull Call<List<Issues>> call, @NonNull Response<List<Issues>> response) {
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
List<Issues> 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<List<Issues>> call, @NonNull Throwable t) {
|
||||||
|
Log.e("onFailure", t.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -11,17 +11,10 @@
|
|||||||
android:strokeColor="?attr/iconsColor"
|
android:strokeColor="?attr/iconsColor"
|
||||||
android:strokeLineCap="round"/>
|
android:strokeLineCap="round"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M12,8L12,12"
|
android:pathData="M11.75,11.75m-2.25,0a2.25,2.25 0,1 1,4.5 0a2.25,2.25 0,1 1,-4.5 0"
|
||||||
android:strokeLineJoin="round"
|
android:strokeLineJoin="round"
|
||||||
android:strokeWidth="2"
|
android:strokeWidth="73.9523"
|
||||||
android:fillColor="#00000000"
|
android:fillColor="?attr/iconsColor"
|
||||||
android:strokeColor="?attr/iconsColor"
|
android:strokeColor="#00000000"
|
||||||
android:strokeLineCap="round"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M12,16L12.01,16"
|
|
||||||
android:strokeLineJoin="round"
|
|
||||||
android:strokeWidth="2"
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:strokeColor="?attr/iconsColor"
|
|
||||||
android:strokeLineCap="round"/>
|
android:strokeLineCap="round"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:pathData="M22,11.08V12a10,10 0,1 1,-5.93 -9.14"
|
android:pathData="M12,22c5.523,0 10,-4.477 10,-10S17.523,2 12,2 2,6.477 2,12s4.477,10 10,10z"
|
||||||
android:strokeLineJoin="round"
|
android:strokeLineJoin="round"
|
||||||
android:strokeWidth="2"
|
android:strokeWidth="2"
|
||||||
android:fillColor="#00000000"
|
android:fillColor="#00000000"
|
||||||
android:strokeColor="?attr/iconsColor"
|
android:strokeColor="?attr/iconsColor"
|
||||||
android:strokeLineCap="round"/>
|
android:strokeLineCap="round"/>
|
||||||
<path
|
<path
|
||||||
android:pathData="M22,4l-10,10.01l-3,-3"
|
android:pathData="M9,12l2,2 4,-4"
|
||||||
android:strokeLineJoin="round"
|
android:strokeLineJoin="round"
|
||||||
android:strokeWidth="2"
|
android:strokeWidth="2"
|
||||||
android:fillColor="#00000000"
|
android:fillColor="#00000000"
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
android:text="@string/isClosed"
|
android:text="@string/isClosed"
|
||||||
android:textColor="?attr/primaryTextColor"
|
android:textColor="?attr/primaryTextColor"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:drawableStartCompat="@drawable/ic_done" />
|
app:drawableStartCompat="@drawable/ic_issue_closed" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
android:text="@string/isClosed"
|
android:text="@string/isClosed"
|
||||||
android:textColor="?attr/primaryTextColor"
|
android:textColor="?attr/primaryTextColor"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:drawableStartCompat="@drawable/ic_done" />
|
app:drawableStartCompat="@drawable/ic_issue_closed" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -84,12 +84,12 @@
|
|||||||
android:orientation="vertical" >
|
android:orientation="vertical" >
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/cancel"
|
android:id="@+id/save"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
style="?android:attr/button"
|
style="?android:attr/button"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:text="@string/close"
|
android:text="@string/saveButton"
|
||||||
android:textColor="@color/colorWhite"
|
android:textColor="@color/colorWhite"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
@ -84,12 +84,12 @@
|
|||||||
android:orientation="vertical" >
|
android:orientation="vertical" >
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/cancel"
|
android:id="@+id/save"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
style="?android:attr/button"
|
style="?android:attr/button"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:text="@string/close"
|
android:text="@string/saveButton"
|
||||||
android:textColor="@color/colorWhite"
|
android:textColor="@color/colorWhite"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
android:icon="@drawable/ic_repo"
|
android:icon="@drawable/ic_repo"
|
||||||
android:title="@string/navRepos" />
|
android:title="@string/navRepos" />
|
||||||
|
|
||||||
|
<item android:id="@+id/nav_my_issues"
|
||||||
|
android:icon="@drawable/ic_issue"
|
||||||
|
android:title="@string/navMyIssues"
|
||||||
|
android:visible="false" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_notifications"
|
android:id="@+id/nav_notifications"
|
||||||
android:icon="@drawable/ic_notifications"
|
android:icon="@drawable/ic_notifications"
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
<item>@string/pageTitleExplore</item>
|
<item>@string/pageTitleExplore</item>
|
||||||
<item>@string/titleDrafts</item>
|
<item>@string/titleDrafts</item>
|
||||||
<item>@string/pageTitleNotifications</item>
|
<item>@string/pageTitleNotifications</item>
|
||||||
|
<item>@string/navMyIssues</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="linkHandlerDefaultScreen">
|
<string-array name="linkHandlerDefaultScreen">
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
<string name="navRate">Rate GitNex</string>
|
<string name="navRate">Rate GitNex</string>
|
||||||
<string name="navLogout">Logout</string>
|
<string name="navLogout">Logout</string>
|
||||||
<string name="navAdministration">Administration</string>
|
<string name="navAdministration">Administration</string>
|
||||||
|
<string name="navMyIssues">My Issues</string>
|
||||||
<!-- menu items -->
|
<!-- menu items -->
|
||||||
|
|
||||||
<!-- page titles -->
|
<!-- page titles -->
|
||||||
|
Loading…
Reference in New Issue
Block a user