mirror of
https://codeberg.org/gitnex/GitNex
synced 2024-12-23 00:48:57 +01:00
Search issues (#713)
Implement pagination Use tabs for explore add fragment, layout, adapter and implementation of api calls Merge branch 'master' into 14-search-issues-pulls Merge branch 'master' into 14-search-issues-pulls Merge branch 'master' into 14-search-issues-pulls Add menu item Co-authored-by: M M Arif <mmarif@swatian.com> Reviewed-on: https://codeberg.org/gitnex/GitNex/pulls/713
This commit is contained in:
parent
d20a773d1d
commit
d52d7a188e
@ -34,7 +34,7 @@ import org.mian.gitnex.database.models.UserAccount;
|
||||
import org.mian.gitnex.fragments.AdministrationFragment;
|
||||
import org.mian.gitnex.fragments.BottomSheetDraftsFragment;
|
||||
import org.mian.gitnex.fragments.DraftsFragment;
|
||||
import org.mian.gitnex.fragments.ExploreRepositoriesFragment;
|
||||
import org.mian.gitnex.fragments.ExploreFragment;
|
||||
import org.mian.gitnex.fragments.MyRepositoriesFragment;
|
||||
import org.mian.gitnex.fragments.NotificationsFragment;
|
||||
import org.mian.gitnex.fragments.OrganizationsFragment;
|
||||
@ -176,7 +176,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
||||
else if(fragmentById instanceof OrganizationsFragment) {
|
||||
toolbarTitle.setText(getResources().getString(R.string.pageTitleOrganizations));
|
||||
}
|
||||
else if(fragmentById instanceof ExploreRepositoriesFragment) {
|
||||
else if(fragmentById instanceof ExploreFragment) {
|
||||
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
|
||||
}
|
||||
else if(fragmentById instanceof NotificationsFragment) {
|
||||
@ -305,6 +305,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
||||
|
||||
toolbarTitle.setText(getResources().getString(R.string.pageTitleProfile));
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ProfileFragment()).commit();
|
||||
navigationView.setCheckedItem(R.id.nav_profile);
|
||||
drawer.closeDrawers();
|
||||
});
|
||||
|
||||
@ -384,7 +385,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
||||
|
||||
case 5:
|
||||
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit();
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
|
||||
navigationView.setCheckedItem(R.id.nav_explore);
|
||||
break;
|
||||
|
||||
@ -550,7 +551,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
||||
|
||||
case R.id.nav_explore:
|
||||
toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreRepositoriesFragment()).commit();
|
||||
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ExploreFragment()).commit();
|
||||
break;
|
||||
|
||||
case R.id.nav_notifications:
|
||||
|
@ -0,0 +1,172 @@
|
||||
package org.mian.gitnex.adapters;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.activities.IssueDetailActivity;
|
||||
import org.mian.gitnex.clients.PicassoService;
|
||||
import org.mian.gitnex.database.api.RepositoriesApi;
|
||||
import org.mian.gitnex.database.models.Repository;
|
||||
import org.mian.gitnex.helpers.ClickListener;
|
||||
import org.mian.gitnex.helpers.RoundedTransformation;
|
||||
import org.mian.gitnex.helpers.TimeHelper;
|
||||
import org.mian.gitnex.helpers.TinyDB;
|
||||
import org.mian.gitnex.models.Issues;
|
||||
import org.ocpsoft.prettytime.PrettyTime;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class SearchIssuesAdapter extends RecyclerView.Adapter<SearchIssuesAdapter.SearchViewHolder> {
|
||||
|
||||
private List<Issues> searchedList;
|
||||
private Context mCtx;
|
||||
private TinyDB tinyDb;
|
||||
|
||||
public SearchIssuesAdapter(List<Issues> dataList, Context mCtx) {
|
||||
|
||||
this.mCtx = mCtx;
|
||||
this.searchedList = dataList;
|
||||
this.tinyDb = new TinyDB(mCtx);
|
||||
}
|
||||
|
||||
class SearchViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private TextView issueNumber;
|
||||
private ImageView issueAssigneeAvatar;
|
||||
private TextView issueTitle;
|
||||
private TextView issueCreatedTime;
|
||||
private TextView issueCommentsCount;
|
||||
private TextView repoFullName;
|
||||
|
||||
private SearchViewHolder(View itemView) {
|
||||
|
||||
super(itemView);
|
||||
|
||||
issueNumber = itemView.findViewById(R.id.issueNumber);
|
||||
issueAssigneeAvatar = itemView.findViewById(R.id.assigneeAvatar);
|
||||
issueTitle = itemView.findViewById(R.id.issueTitle);
|
||||
issueCommentsCount = itemView.findViewById(R.id.issueCommentsCount);
|
||||
issueCreatedTime = itemView.findViewById(R.id.issueCreatedTime);
|
||||
repoFullName = itemView.findViewById(R.id.repoFullName);
|
||||
|
||||
issueTitle.setOnClickListener(v -> {
|
||||
|
||||
Context context = v.getContext();
|
||||
|
||||
Intent intent = new Intent(context, IssueDetailActivity.class);
|
||||
intent.putExtra("issueNumber", issueNumber.getText());
|
||||
|
||||
tinyDb.putString("issueNumber", issueNumber.getText().toString());
|
||||
tinyDb.putString("issueType", "Issue");
|
||||
|
||||
tinyDb.putString("repoFullName", repoFullName.getText().toString());
|
||||
|
||||
String[] parts = repoFullName.getText().toString().split("/");
|
||||
final String repoOwner = parts[0];
|
||||
final String repoName = parts[1];
|
||||
|
||||
int currentActiveAccountId = tinyDb.getInt("currentActiveAccountId");
|
||||
RepositoriesApi repositoryData = new RepositoriesApi(context);
|
||||
|
||||
Integer count = repositoryData.checkRepository(currentActiveAccountId, repoOwner, repoName);
|
||||
|
||||
if(count == 0) {
|
||||
|
||||
long id = repositoryData.insertRepository(currentActiveAccountId, repoOwner, repoName);
|
||||
tinyDb.putLong("repositoryId", id);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
Repository data = repositoryData.getRepository(currentActiveAccountId, repoOwner, repoName);
|
||||
tinyDb.putLong("repositoryId", data.getRepositoryId());
|
||||
|
||||
}
|
||||
|
||||
context.startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SearchIssuesAdapter.SearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_issues, parent, false);
|
||||
return new SearchIssuesAdapter.SearchViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final SearchIssuesAdapter.SearchViewHolder holder, int position) {
|
||||
|
||||
Issues currentItem = searchedList.get(position);
|
||||
|
||||
String locale = tinyDb.getString("locale");
|
||||
String timeFormat = tinyDb.getString("dateFormat");
|
||||
|
||||
if(!currentItem.getUser().getFull_name().equals("")) {
|
||||
holder.issueAssigneeAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCreator) + currentItem.getUser().getFull_name(), mCtx));
|
||||
}
|
||||
else {
|
||||
holder.issueAssigneeAvatar.setOnClickListener(new ClickListener(mCtx.getResources().getString(R.string.issueCreator) + currentItem.getUser().getLogin(), mCtx));
|
||||
}
|
||||
|
||||
PicassoService
|
||||
.getInstance(mCtx).get().load(currentItem.getUser().getAvatar_url()).placeholder(R.drawable.loader_animated).transform(new RoundedTransformation(8, 0)).resize(120, 120).centerCrop().into(holder.issueAssigneeAvatar);
|
||||
|
||||
String issueNumber_ = "<font color='" + mCtx.getResources().getColor(R.color.lightGray) + "'>" + currentItem.getRepository().getFull_name() + mCtx.getResources().getString(R.string.hash) + currentItem.getNumber() + "</font>";
|
||||
holder.issueTitle.setText(Html.fromHtml(issueNumber_ + " " + currentItem.getTitle()));
|
||||
|
||||
holder.issueNumber.setText(String.valueOf(currentItem.getNumber()));
|
||||
holder.issueCommentsCount.setText(String.valueOf(currentItem.getComments()));
|
||||
holder.repoFullName.setText(currentItem.getRepository().getFull_name());
|
||||
|
||||
switch(timeFormat) {
|
||||
case "pretty": {
|
||||
PrettyTime prettyTime = new PrettyTime(new Locale(locale));
|
||||
String createdTime = prettyTime.format(currentItem.getCreated_at());
|
||||
holder.issueCreatedTime.setText(createdTime);
|
||||
holder.issueCreatedTime.setOnClickListener(new ClickListener(TimeHelper.customDateFormatForToastDateFormat(currentItem.getCreated_at()), mCtx));
|
||||
break;
|
||||
}
|
||||
case "normal": {
|
||||
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
|
||||
String createdTime = formatter.format(currentItem.getCreated_at());
|
||||
holder.issueCreatedTime.setText(createdTime);
|
||||
break;
|
||||
}
|
||||
case "normal1": {
|
||||
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy '" + mCtx.getResources().getString(R.string.timeAtText) + "' HH:mm", new Locale(locale));
|
||||
String createdTime = formatter.format(currentItem.getCreated_at());
|
||||
holder.issueCreatedTime.setText(createdTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
|
||||
return searchedList.size();
|
||||
}
|
||||
|
||||
public void notifyDataChanged() {
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
129
app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java
Normal file
129
app/src/main/java/org/mian/gitnex/fragments/ExploreFragment.java
Normal file
@ -0,0 +1,129 @@
|
||||
package org.mian.gitnex.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.activities.MainActivity;
|
||||
import org.mian.gitnex.helpers.TinyDB;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class ExploreFragment extends Fragment {
|
||||
|
||||
private Context ctx;
|
||||
private TinyDB tinyDB;
|
||||
|
||||
private int tabsCount;
|
||||
public ViewPager mViewPager;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
|
||||
View v = inflater.inflate(R.layout.fragment_explore, container,false);
|
||||
ctx = getContext();
|
||||
tinyDB = new TinyDB(ctx);
|
||||
|
||||
((MainActivity) requireActivity()).setActionBarTitle(getResources().getString(R.string.navExplore));
|
||||
|
||||
TabLayout tabLayout = v.findViewById(R.id.tabsExplore);
|
||||
|
||||
ViewGroup viewGroup = (ViewGroup) tabLayout.getChildAt(0);
|
||||
tabsCount = viewGroup.getChildCount();
|
||||
|
||||
Typeface myTypeface;
|
||||
|
||||
switch(tinyDB.getInt("customFontId", -1)) {
|
||||
|
||||
case 0:
|
||||
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/roboto.ttf");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/sourcecodeproregular.ttf");
|
||||
break;
|
||||
|
||||
default:
|
||||
myTypeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/manroperegular.ttf");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
for(int j = 0; j < tabsCount; j++) {
|
||||
|
||||
ViewGroup vgTab = (ViewGroup) viewGroup.getChildAt(j);
|
||||
int tabChildCount = vgTab.getChildCount();
|
||||
|
||||
for(int i = 0; i < tabChildCount; i++) {
|
||||
|
||||
View tabViewChild = vgTab.getChildAt(i);
|
||||
|
||||
if(tabViewChild instanceof TextView) {
|
||||
((TextView) tabViewChild).setTypeface(myTypeface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mViewPager = v.findViewById(R.id.containerExplore);
|
||||
|
||||
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
|
||||
tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
|
||||
|
||||
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
|
||||
mViewPager.setAdapter(mSectionsPagerAdapter);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public class SectionsPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
SectionsPagerAdapter(FragmentManager fm) {
|
||||
|
||||
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
|
||||
Fragment fragment = null;
|
||||
|
||||
switch(position) {
|
||||
|
||||
case 0: // Repositories
|
||||
fragment = new ExploreRepositoriesFragment();
|
||||
break;
|
||||
|
||||
case 1: // Issues
|
||||
fragment = new SearchIssuesFragment();
|
||||
break;
|
||||
}
|
||||
|
||||
assert fragment != null;
|
||||
return fragment;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
|
||||
return tabsCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -27,7 +27,6 @@ import org.mian.gitnex.interfaces.ApiInterface;
|
||||
import org.mian.gitnex.models.Milestones;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
@ -104,7 +103,7 @@ public class MilestonesFragment extends Fragment {
|
||||
|
||||
}, 50));
|
||||
|
||||
((RepoDetailActivity) Objects.requireNonNull(getActivity())).setFragmentRefreshListenerMilestone(milestoneState -> {
|
||||
((RepoDetailActivity) requireActivity()).setFragmentRefreshListenerMilestone(milestoneState -> {
|
||||
|
||||
if(milestoneState.equals("closed")) {
|
||||
menu.getItem(1).setIcon(R.drawable.ic_filter_closed);
|
||||
|
@ -0,0 +1,192 @@
|
||||
package org.mian.gitnex.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import org.mian.gitnex.adapters.SearchIssuesAdapter;
|
||||
import org.mian.gitnex.clients.RetrofitClient;
|
||||
import org.mian.gitnex.databinding.FragmentSearchIssuesBinding;
|
||||
import org.mian.gitnex.helpers.AppUtil;
|
||||
import org.mian.gitnex.helpers.Authorization;
|
||||
import org.mian.gitnex.helpers.InfiniteScrollListener;
|
||||
import org.mian.gitnex.helpers.TinyDB;
|
||||
import org.mian.gitnex.models.Issues;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* Author M M Arif
|
||||
*/
|
||||
|
||||
public class SearchIssuesFragment extends Fragment {
|
||||
|
||||
private Context ctx;
|
||||
private TinyDB tinyDb;
|
||||
private FragmentSearchIssuesBinding viewBinding;
|
||||
private SearchIssuesAdapter adapter;
|
||||
private List<Issues> dataList;
|
||||
|
||||
private String instanceUrl;
|
||||
private String loginUid;
|
||||
private String instanceToken;
|
||||
|
||||
private int apiCallCurrentValue = 10;
|
||||
private int pageCurrentIndex = 1;
|
||||
private String type = "issues";
|
||||
private String state = "open";
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
viewBinding = FragmentSearchIssuesBinding.inflate(inflater, container, false);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
ctx = getContext();
|
||||
tinyDb = new TinyDB(getContext());
|
||||
|
||||
instanceUrl = tinyDb.getString("instanceUrl");
|
||||
loginUid = tinyDb.getString("loginUid");
|
||||
instanceToken = "token " + tinyDb.getString(loginUid + "-token");
|
||||
|
||||
dataList = new ArrayList<>();
|
||||
adapter = new SearchIssuesAdapter(dataList, ctx);
|
||||
|
||||
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ctx);
|
||||
|
||||
viewBinding.recyclerViewSearchIssues.setHasFixedSize(true);
|
||||
viewBinding.recyclerViewSearchIssues.setLayoutManager(linearLayoutManager);
|
||||
viewBinding.recyclerViewSearchIssues.setAdapter(adapter);
|
||||
|
||||
viewBinding.searchKeyword.setOnEditorActionListener((v1, actionId, event) -> {
|
||||
|
||||
if(actionId == EditorInfo.IME_ACTION_SEND) {
|
||||
|
||||
if(!Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString().equals("")) {
|
||||
|
||||
InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(viewBinding.searchKeyword.getWindowToken(), 0);
|
||||
|
||||
pageCurrentIndex = 1;
|
||||
apiCallCurrentValue = 10;
|
||||
viewBinding.progressBar.setVisibility(View.VISIBLE);
|
||||
loadData(false, viewBinding.searchKeyword.getText().toString());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
viewBinding.recyclerViewSearchIssues.addOnScrollListener(new InfiniteScrollListener(pageCurrentIndex, linearLayoutManager) {
|
||||
|
||||
@Override
|
||||
public void onScrolledToEnd(int firstVisibleItemPosition) {
|
||||
|
||||
pageCurrentIndex++;
|
||||
loadData(true, Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
viewBinding.pullToRefresh.setOnRefreshListener(() -> {
|
||||
|
||||
pageCurrentIndex = 1;
|
||||
apiCallCurrentValue = 10;
|
||||
loadData(false, Objects.requireNonNull(viewBinding.searchKeyword.getText()).toString());
|
||||
|
||||
});
|
||||
|
||||
loadData(false, "");
|
||||
|
||||
return viewBinding.getRoot();
|
||||
}
|
||||
|
||||
private void loadData(boolean append, String searchKeyword) {
|
||||
|
||||
viewBinding.noData.setVisibility(View.GONE);
|
||||
|
||||
int apiCallDefaultLimit = 10;
|
||||
if(apiCallDefaultLimit > apiCallCurrentValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(pageCurrentIndex == 1 || !append) {
|
||||
|
||||
dataList.clear();
|
||||
adapter.notifyDataSetChanged();
|
||||
viewBinding.pullToRefresh.setRefreshing(false);
|
||||
viewBinding.progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else {
|
||||
|
||||
viewBinding.loadingMoreView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
Call<List<Issues>> call = RetrofitClient.getInstance(instanceUrl, getContext()).getApiInterface().queryIssues(
|
||||
Authorization.returnAuthentication(getContext(), loginUid, instanceToken), searchKeyword, type, state, pageCurrentIndex);
|
||||
|
||||
call.enqueue(new Callback<List<Issues>>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<List<Issues>> call, @NonNull Response<List<Issues>> response) {
|
||||
|
||||
if(response.code() == 200) {
|
||||
|
||||
assert response.body() != null;
|
||||
apiCallCurrentValue = response.body().size();
|
||||
|
||||
Log.e("searchIssues", String.valueOf(apiCallCurrentValue));
|
||||
|
||||
if(!append) {
|
||||
|
||||
dataList.clear();
|
||||
}
|
||||
|
||||
dataList.addAll(response.body());
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
dataList.clear();
|
||||
adapter.notifyDataChanged();
|
||||
viewBinding.noData.setVisibility(View.VISIBLE);
|
||||
|
||||
}
|
||||
|
||||
onCleanup();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<List<Issues>> call, @NonNull Throwable t) {
|
||||
|
||||
Log.e("onFailure", Objects.requireNonNull(t.getMessage()));
|
||||
onCleanup();
|
||||
|
||||
}
|
||||
|
||||
private void onCleanup() {
|
||||
|
||||
AppUtil.setMultiVisibility(View.GONE, viewBinding.loadingMoreView, viewBinding.progressBar);
|
||||
|
||||
if(dataList.isEmpty()) {
|
||||
|
||||
viewBinding.noData.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,6 @@ package org.mian.gitnex.helpers;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import org.mian.gitnex.R;
|
||||
@ -18,17 +17,16 @@ public class ClickListener implements View.OnClickListener {
|
||||
private Context mCtx;
|
||||
|
||||
public ClickListener(String infoText, Context mCtx) {
|
||||
|
||||
this.infoText = infoText;
|
||||
this.mCtx = mCtx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
public void onClick(View v) {
|
||||
|
||||
LayoutInflater inflater1 = LayoutInflater.from(mCtx);
|
||||
View layout = inflater1.inflate(R.layout.custom_toast_success,
|
||||
(ViewGroup) v.findViewById(R.id.custom_toast_container));
|
||||
View layout = inflater1.inflate(R.layout.custom_toast_info, v.findViewById(R.id.custom_toast_container));
|
||||
|
||||
TextView text = layout.findViewById(R.id.toastText);
|
||||
text.setText(infoText);
|
||||
|
@ -268,6 +268,9 @@ public interface ApiInterface {
|
||||
@GET("repos/search") // get all the repos which match the query string
|
||||
Call<ExploreRepositories> queryRepos(@Header("Authorization") String token, @Query("q") String searchKeyword, @Query("private") Boolean repoTypeInclude, @Query("sort") String sort, @Query("order") String order, @Query("topic") boolean topic, @Query("includeDesc") boolean includeDesc, @Query("template") boolean template, @Query("archived") boolean archived, @Query("is_private") boolean is_private, @Query("limit") int limit);
|
||||
|
||||
@GET("repos/issues/search") // get all the issues which match the query string
|
||||
Call<List<Issues>> queryIssues(@Header("Authorization") String token, @Query("q") String searchKeyword, @Query("type") String type, @Query("state") String state, @Query("page") int page);
|
||||
|
||||
@POST("repos/{owner}/{repo}/contents/{file}") // create new file
|
||||
Call<JsonElement> createNewFile(@Header("Authorization") String token, @Path("owner") String ownerName, @Path("repo") String repoName, @Path("file") String fileName, @Body NewFile jsonStr);
|
||||
|
||||
|
@ -27,6 +27,7 @@ public class Issues {
|
||||
private pullRequestObject pull_request;
|
||||
private milestoneObject milestone;
|
||||
private List<assigneesObject> assignees;
|
||||
private repositoryObject repository;
|
||||
|
||||
public Issues(String body) {
|
||||
this.body = body;
|
||||
@ -193,6 +194,35 @@ public class Issues {
|
||||
}
|
||||
}
|
||||
|
||||
public static class repositoryObject {
|
||||
|
||||
private int id;
|
||||
private String full_name;
|
||||
private String name;
|
||||
private String owner;
|
||||
|
||||
public int getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getFull_name() {
|
||||
|
||||
return full_name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
|
||||
return owner;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
@ -267,4 +297,9 @@ public class Issues {
|
||||
this.html_url = html_url;
|
||||
}
|
||||
|
||||
public repositoryObject getRepository() {
|
||||
|
||||
return repository;
|
||||
}
|
||||
|
||||
}
|
||||
|
48
app/src/main/res/layout/fragment_explore.xml
Normal file
48
app/src/main/res/layout/fragment_explore.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/exploreFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/primaryBackgroundColor">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/Widget.AppCompat.SearchView">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabsExplore"
|
||||
app:tabMode="fixed"
|
||||
app:tabTextAppearance="@style/customTabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
app:tabTextColor="?attr/primaryTextColor"
|
||||
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:id="@+id/tabExploreRepositories"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pageTitleRepositories" />
|
||||
|
||||
<com.google.android.material.tabs.TabItem
|
||||
android:id="@+id/tabExploreIssues"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pageTitleIssues" />
|
||||
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/containerExplore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
88
app/src/main/res/layout/fragment_search_issues.xml
Normal file
88
app/src/main/res/layout/fragment_search_issues.xml
Normal file
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.progressindicator.ProgressIndicator
|
||||
android:id="@+id/loadingMoreView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
|
||||
app:indicatorColor="?attr/progressIndicatorColor" />
|
||||
|
||||
<com.google.android.material.progressindicator.ProgressIndicator
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.MaterialComponents.ProgressIndicator.Linear.Indeterminate"
|
||||
app:indicatorColor="?attr/progressIndicatorColor" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/searchKeywordLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:boxBackgroundColor="?attr/inputBackgroundColor"
|
||||
android:textColorHint="?attr/hintColor"
|
||||
app:hintTextColor="?attr/hintColor"
|
||||
app:boxStrokeErrorColor="@color/darkRed"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:startIconDrawable="@drawable/ic_search"
|
||||
app:startIconTint="?attr/iconsColor"
|
||||
app:endIconMode="clear_text"
|
||||
app:endIconTint="?attr/iconsColor"
|
||||
android:hint="@string/navSearchIssuesPulls">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/searchKeyword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/inputTextColor"
|
||||
android:textColorHighlight="?attr/hintColor"
|
||||
android:textColorHint="?attr/hintColor"
|
||||
android:imeOptions="actionSend"
|
||||
android:inputType="text"
|
||||
android:textSize="16sp" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/noData"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="15dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/noDataFound"
|
||||
android:textColor="?attr/primaryTextColor"
|
||||
android:textSize="20sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/pullToRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerViewSearchIssues"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
</LinearLayout>
|
@ -12,6 +12,12 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/repoFullName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/mainFrame"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -32,6 +32,7 @@
|
||||
<string name="navLogout">Logout</string>
|
||||
<string name="navExplore">Explore</string>
|
||||
<string name="navAdministration">Administration</string>
|
||||
<string name="navSearchIssuesPulls">Search Issues</string>
|
||||
<!-- menu items -->
|
||||
|
||||
<!-- page titles -->
|
||||
|
Loading…
Reference in New Issue
Block a user