mirror of
https://github.com/gitnex-org/gitnex.git
synced 2026-06-10 19:20:34 -05:00
refactor explore and starred repos to activites
This commit is contained in:
@@ -178,6 +178,14 @@
|
||||
android:name=".activities.MostVisitedReposActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
|
||||
android:windowSoftInputMode="adjustResize"/>
|
||||
<activity
|
||||
android:name=".activities.ExploreActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
|
||||
android:windowSoftInputMode="adjustResize"/>
|
||||
<activity
|
||||
android:name=".activities.StarredReposActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
|
||||
android:windowSoftInputMode="adjustResize"/>
|
||||
|
||||
<meta-data
|
||||
android:name="com.samsung.android.keepalive.density"
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package org.mian.gitnex.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.databinding.ActivityExploreBinding;
|
||||
import org.mian.gitnex.fragments.ExploreIssuesFragment;
|
||||
import org.mian.gitnex.fragments.ExplorePublicOrganizationsFragment;
|
||||
import org.mian.gitnex.fragments.ExploreRepositoriesFragment;
|
||||
import org.mian.gitnex.fragments.ExploreUsersFragment;
|
||||
import org.mian.gitnex.helpers.AppDatabaseSettings;
|
||||
import org.mian.gitnex.helpers.ViewPager2Transformers;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class ExploreActivity extends BaseActivity {
|
||||
|
||||
private ActivityExploreBinding binding;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivityExploreBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
setSupportActionBar(binding.toolbar);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
setupViewPager();
|
||||
}
|
||||
|
||||
private void setupViewPager() {
|
||||
binding.containerExplore.setOffscreenPageLimit(1);
|
||||
|
||||
ExplorePagerAdapter adapter = new ExplorePagerAdapter(this);
|
||||
binding.containerExplore.setAdapter(adapter);
|
||||
ViewPager2Transformers.returnSelectedTransformer(
|
||||
binding.containerExplore,
|
||||
Integer.parseInt(
|
||||
AppDatabaseSettings.getSettingsValue(
|
||||
this, AppDatabaseSettings.APP_TABS_ANIMATION_KEY)));
|
||||
|
||||
String[] tabTitles = {
|
||||
getString(R.string.navRepos),
|
||||
getString(R.string.pageTitleIssues),
|
||||
getString(R.string.navOrg),
|
||||
getString(R.string.pageTitleUsers)
|
||||
};
|
||||
|
||||
new TabLayoutMediator(
|
||||
binding.tabsExplore,
|
||||
binding.containerExplore,
|
||||
(tab, position) -> tab.setText(tabTitles[position]))
|
||||
.attach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private static class ExplorePagerAdapter extends FragmentStateAdapter {
|
||||
|
||||
public ExplorePagerAdapter(@NonNull FragmentActivity fa) {
|
||||
super(fa);
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Fragment createFragment(int position) {
|
||||
return switch (position) {
|
||||
case 0 -> new ExploreRepositoriesFragment();
|
||||
case 1 -> new ExploreIssuesFragment();
|
||||
case 2 -> new ExplorePublicOrganizationsFragment();
|
||||
case 3 -> new ExploreUsersFragment();
|
||||
default -> throw new IllegalStateException("Unexpected position: " + position);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,10 @@ public class MainActivity extends BaseActivity
|
||||
R.id.notificationsFragment, null, navOptions);
|
||||
return true;
|
||||
} else if (itemId == R.id.exploreFragment) {
|
||||
navController.navigate(R.id.exploreFragment, null, navOptions);
|
||||
Intent intent = new Intent(ctx, ExploreActivity.class);
|
||||
startActivity(intent);
|
||||
this.overridePendingTransition(
|
||||
android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
return true;
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
@@ -506,7 +509,9 @@ public class MainActivity extends BaseActivity
|
||||
navController.navigate(R.id.notificationsFragment, null, navOptions);
|
||||
break;
|
||||
case "explore":
|
||||
navController.navigate(R.id.exploreFragment, null, navOptions);
|
||||
Intent intent = new Intent(ctx, ExploreActivity.class);
|
||||
startActivity(intent);
|
||||
this.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
break;
|
||||
case "profile":
|
||||
Intent intentProfile = new Intent(this, ProfileActivity.class);
|
||||
@@ -573,8 +578,9 @@ public class MainActivity extends BaseActivity
|
||||
navController.navigate(R.id.repositoriesFragment, null, navOptions);
|
||||
break;
|
||||
case 5:
|
||||
binding.toolbarTitle.setText(getResources().getString(R.string.pageTitleExplore));
|
||||
navController.navigate(R.id.exploreFragment, null, navOptions);
|
||||
Intent intent = new Intent(ctx, ExploreActivity.class);
|
||||
startActivity(intent);
|
||||
this.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
break;
|
||||
case 6:
|
||||
navController.navigate(R.id.notificationsFragment, null, navOptions);
|
||||
|
||||
@@ -95,10 +95,9 @@ public class MostVisitedReposActivity extends BaseActivity {
|
||||
|
||||
private void setupRefreshLayout() {
|
||||
binding.pullToRefresh.setOnRefreshListener(
|
||||
() -> {
|
||||
new Handler(Looper.getMainLooper())
|
||||
.postDelayed(() -> fetchDataAsync(currentActiveAccountId), 250);
|
||||
});
|
||||
() ->
|
||||
new Handler(Looper.getMainLooper())
|
||||
.postDelayed(() -> fetchDataAsync(currentActiveAccountId), 250));
|
||||
}
|
||||
|
||||
private void fetchDataAsync(int accountId) {
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package org.mian.gitnex.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.gitnex.tea4j.v2.models.Repository;
|
||||
import org.mian.gitnex.adapters.ReposListAdapter;
|
||||
import org.mian.gitnex.databinding.ActivityRepositoriesBinding;
|
||||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.helpers.EndlessRecyclerViewScrollListener;
|
||||
import org.mian.gitnex.viewmodels.RepositoriesViewModel;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class StarredReposActivity extends BaseActivity {
|
||||
|
||||
private ActivityRepositoriesBinding binding;
|
||||
private RepositoriesViewModel viewModel;
|
||||
private ReposListAdapter adapter;
|
||||
private EndlessRecyclerViewScrollListener scrollListener;
|
||||
private int resultLimit;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivityRepositoriesBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
resultLimit = Constants.getCurrentResultLimit(this);
|
||||
viewModel = new ViewModelProvider(this).get(RepositoriesViewModel.class);
|
||||
|
||||
setupUI();
|
||||
setupSearch();
|
||||
observeViewModel();
|
||||
|
||||
refreshData();
|
||||
}
|
||||
|
||||
private void setupUI() {
|
||||
binding.btnBack.setOnClickListener(v -> finish());
|
||||
binding.btnSearch.setOnClickListener(v -> binding.searchView.show());
|
||||
binding.btnNewRepository.setOnClickListener(
|
||||
v -> startActivity(new Intent(ctx, CreateRepoActivity.class)));
|
||||
|
||||
adapter = new ReposListAdapter(new ArrayList<>(), this);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
binding.recyclerView.setLayoutManager(layoutManager);
|
||||
binding.recyclerView.setAdapter(adapter);
|
||||
|
||||
scrollListener =
|
||||
new EndlessRecyclerViewScrollListener(layoutManager) {
|
||||
@Override
|
||||
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
|
||||
if (binding.searchView.isShowing()) return;
|
||||
|
||||
viewModel.fetchRepos(
|
||||
ctx, "starredRepos", "", null, page, resultLimit, null, false);
|
||||
}
|
||||
};
|
||||
binding.recyclerView.addOnScrollListener(scrollListener);
|
||||
|
||||
binding.pullToRefresh.setOnRefreshListener(
|
||||
() -> {
|
||||
binding.pullToRefresh.setRefreshing(false);
|
||||
refreshData();
|
||||
});
|
||||
}
|
||||
|
||||
private void setupSearch() {
|
||||
binding.searchResultsRecycler.setAdapter(adapter);
|
||||
|
||||
binding.searchView
|
||||
.getEditText()
|
||||
.addTextChangedListener(
|
||||
new TextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(
|
||||
CharSequence s, int start, int before, int count) {
|
||||
adapter.getFilter().filter(s.toString().trim());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(
|
||||
CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
});
|
||||
|
||||
binding.searchView.addTransitionListener(
|
||||
(searchView, previousState, newState) -> {
|
||||
if (newState
|
||||
== com.google.android.material.search.SearchView.TransitionState
|
||||
.HIDDEN) {
|
||||
List<Repository> originalList = viewModel.getRepos().getValue();
|
||||
if (originalList != null) {
|
||||
adapter.updateList(originalList);
|
||||
}
|
||||
binding.recyclerView.scrollToPosition(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void observeViewModel() {
|
||||
viewModel
|
||||
.getRepos()
|
||||
.observe(
|
||||
this,
|
||||
list -> {
|
||||
adapter.updateList(list);
|
||||
updateUiState();
|
||||
});
|
||||
|
||||
viewModel
|
||||
.getIsLoading()
|
||||
.observe(
|
||||
this,
|
||||
loading -> {
|
||||
boolean hasData = adapter.getItemCount() > 0;
|
||||
binding.expressiveLoader.setVisibility(
|
||||
loading && !hasData ? View.VISIBLE : View.GONE);
|
||||
});
|
||||
|
||||
viewModel.getHasLoadedOnce().observe(this, hasLoaded -> updateUiState());
|
||||
}
|
||||
|
||||
private void updateUiState() {
|
||||
boolean isEmpty = adapter.getItemCount() == 0;
|
||||
boolean loaded = Boolean.TRUE.equals(viewModel.getHasLoadedOnce().getValue());
|
||||
binding.layoutEmpty.getRoot().setVisibility(loaded && isEmpty ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void refreshData() {
|
||||
if (scrollListener != null) scrollListener.resetState();
|
||||
viewModel.resetPagination();
|
||||
viewModel.fetchRepos(this, "starredRepos", "", null, 1, resultLimit, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (MainActivity.reloadRepos) {
|
||||
refreshData();
|
||||
MainActivity.reloadRepos = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package org.mian.gitnex.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.helpers.AppDatabaseSettings;
|
||||
import org.mian.gitnex.helpers.ViewPager2Transformers;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class ExploreFragment extends Fragment {
|
||||
|
||||
@Nullable @Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
View view = inflater.inflate(R.layout.fragment_explore, container, false);
|
||||
|
||||
Context ctx = getContext();
|
||||
|
||||
ViewPager2 viewPager = view.findViewById(R.id.containerExplore);
|
||||
viewPager.setOffscreenPageLimit(1);
|
||||
TabLayout tabLayout = view.findViewById(R.id.tabsExplore);
|
||||
|
||||
ViewGroup vg = (ViewGroup) tabLayout.getChildAt(0);
|
||||
|
||||
viewPager.setAdapter(new ViewPagerAdapter(this));
|
||||
|
||||
ViewPager2Transformers.returnSelectedTransformer(
|
||||
viewPager,
|
||||
Integer.parseInt(
|
||||
AppDatabaseSettings.getSettingsValue(
|
||||
ctx, AppDatabaseSettings.APP_TABS_ANIMATION_KEY)));
|
||||
|
||||
String[] tabTitles = {
|
||||
getResources().getString(R.string.navRepos),
|
||||
getResources().getString(R.string.pageTitleIssues),
|
||||
getResources().getString(R.string.navOrg),
|
||||
getResources().getString(R.string.pageTitleUsers)
|
||||
};
|
||||
new TabLayoutMediator(
|
||||
tabLayout, viewPager, (tab, position) -> tab.setText(tabTitles[position]))
|
||||
.attach();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
public static class ViewPagerAdapter extends FragmentStateAdapter {
|
||||
|
||||
public ViewPagerAdapter(@NonNull ExploreFragment fa) {
|
||||
super(fa);
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public Fragment createFragment(int position) {
|
||||
Fragment fragment =
|
||||
switch (position) {
|
||||
case 0 -> // Repositories
|
||||
new ExploreRepositoriesFragment();
|
||||
case 1 -> // Issues
|
||||
new ExploreIssuesFragment();
|
||||
case 2 -> // Organizations
|
||||
new ExplorePublicOrganizationsFragment();
|
||||
case 3 -> // Users
|
||||
new ExploreUsersFragment();
|
||||
default -> null;
|
||||
};
|
||||
assert fragment != null;
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import org.mian.gitnex.activities.MainActivity;
|
||||
import org.mian.gitnex.activities.MostVisitedReposActivity;
|
||||
import org.mian.gitnex.activities.NotesActivity;
|
||||
import org.mian.gitnex.activities.ProfileActivity;
|
||||
import org.mian.gitnex.activities.StarredReposActivity;
|
||||
import org.mian.gitnex.adapters.UserAccountsAdapter;
|
||||
import org.mian.gitnex.database.api.BaseApi;
|
||||
import org.mian.gitnex.database.api.UserAccountsApi;
|
||||
@@ -155,7 +156,15 @@ public class HomeDashboardFragment extends Fragment {
|
||||
});
|
||||
binding.repoStarredCard
|
||||
.getRoot()
|
||||
.setOnClickListener(v -> navigateTo(R.id.action_to_starredRepositories));
|
||||
.setOnClickListener(
|
||||
v -> {
|
||||
Intent intent =
|
||||
new Intent(requireContext(), StarredReposActivity.class);
|
||||
startActivity(intent);
|
||||
requireActivity()
|
||||
.overridePendingTransition(
|
||||
android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
});
|
||||
binding.repoWatchedCard
|
||||
.getRoot()
|
||||
.setOnClickListener(v -> navigateTo(R.id.action_to_watchedRepositories));
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
package org.mian.gitnex.fragments;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.core.view.MenuProvider;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.ArrayList;
|
||||
import org.mian.gitnex.R;
|
||||
import org.mian.gitnex.activities.CreateRepoActivity;
|
||||
import org.mian.gitnex.activities.MainActivity;
|
||||
import org.mian.gitnex.adapters.ReposListAdapter;
|
||||
import org.mian.gitnex.databinding.FragmentRepositoriesBinding;
|
||||
import org.mian.gitnex.helpers.Constants;
|
||||
import org.mian.gitnex.helpers.EndlessRecyclerViewScrollListener;
|
||||
import org.mian.gitnex.viewmodels.RepositoriesViewModel;
|
||||
|
||||
/**
|
||||
* @author mmarif
|
||||
*/
|
||||
public class StarredRepositoriesFragment extends Fragment {
|
||||
|
||||
private FragmentRepositoriesBinding binding;
|
||||
private RepositoriesViewModel viewModel;
|
||||
private ReposListAdapter adapter;
|
||||
private EndlessRecyclerViewScrollListener scrollListener;
|
||||
private int resultLimit;
|
||||
private boolean isSearching = false;
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
binding = FragmentRepositoriesBinding.inflate(inflater, container, false);
|
||||
resultLimit = Constants.getCurrentResultLimit(requireContext());
|
||||
viewModel = new ViewModelProvider(this).get(RepositoriesViewModel.class);
|
||||
|
||||
setupRecyclerView();
|
||||
setupSwipeRefresh();
|
||||
setupMenu();
|
||||
observeViewModel();
|
||||
|
||||
refreshData();
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
adapter = new ReposListAdapter(new ArrayList<>(), requireContext());
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
|
||||
binding.recyclerView.setLayoutManager(layoutManager);
|
||||
binding.recyclerView.setAdapter(adapter);
|
||||
|
||||
scrollListener =
|
||||
new EndlessRecyclerViewScrollListener(layoutManager) {
|
||||
@Override
|
||||
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
|
||||
if (!isSearching) {
|
||||
viewModel.fetchRepos(
|
||||
requireContext(),
|
||||
"starredRepos",
|
||||
"",
|
||||
null,
|
||||
page,
|
||||
resultLimit,
|
||||
null,
|
||||
false);
|
||||
}
|
||||
}
|
||||
};
|
||||
binding.recyclerView.addOnScrollListener(scrollListener);
|
||||
|
||||
binding.addNewRepo.setOnClickListener(
|
||||
v -> startActivity(new Intent(getContext(), CreateRepoActivity.class)));
|
||||
}
|
||||
|
||||
private void setupMenu() {
|
||||
requireActivity()
|
||||
.addMenuProvider(
|
||||
new MenuProvider() {
|
||||
@Override
|
||||
public void onCreateMenu(
|
||||
@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
|
||||
menuInflater.inflate(R.menu.search_menu, menu);
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
SearchView searchView = (SearchView) searchItem.getActionView();
|
||||
if (searchView != null) {
|
||||
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
searchView.setOnQueryTextListener(
|
||||
new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
isSearching = !newText.isEmpty();
|
||||
adapter.getFilter().filter(newText);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
getViewLifecycleOwner(),
|
||||
Lifecycle.State.RESUMED);
|
||||
}
|
||||
|
||||
private void observeViewModel() {
|
||||
viewModel
|
||||
.getRepos()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
list -> {
|
||||
adapter.updateList(list);
|
||||
updateUiState();
|
||||
});
|
||||
|
||||
viewModel
|
||||
.getIsLoading()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
loading -> {
|
||||
boolean hasData = adapter.getItemCount() > 0;
|
||||
binding.expressiveLoader.setVisibility(
|
||||
loading && !hasData ? View.VISIBLE : View.GONE);
|
||||
});
|
||||
|
||||
viewModel.getHasLoadedOnce().observe(getViewLifecycleOwner(), hasLoaded -> updateUiState());
|
||||
}
|
||||
|
||||
private void updateUiState() {
|
||||
boolean isEmpty = adapter.getItemCount() == 0;
|
||||
boolean loaded = Boolean.TRUE.equals(viewModel.getHasLoadedOnce().getValue());
|
||||
binding.layoutEmpty.getRoot().setVisibility(loaded && isEmpty ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void refreshData() {
|
||||
if (scrollListener != null) scrollListener.resetState();
|
||||
viewModel.resetPagination();
|
||||
viewModel.fetchRepos(
|
||||
requireContext(), "starredRepos", "", null, 1, resultLimit, null, true);
|
||||
}
|
||||
|
||||
private void setupSwipeRefresh() {
|
||||
binding.pullToRefresh.setOnRefreshListener(
|
||||
() -> {
|
||||
binding.pullToRefresh.setRefreshing(false);
|
||||
refreshData();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (MainActivity.reloadRepos) {
|
||||
refreshData();
|
||||
MainActivity.reloadRepos = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,29 +2,32 @@
|
||||
<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:paddingBottom="@dimen/dimen16dp"
|
||||
android:paddingTop="@dimen/dimen56dp"
|
||||
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"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:title="@string/pageTitleExplore" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabsExplore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/primaryBackgroundColor"
|
||||
app:tabIndicatorColor="?attr/pagerTabIndicatorColor"
|
||||
app:tabIndicatorFullWidth="true"
|
||||
app:tabMode="auto"
|
||||
app:tabIndicatorHeight="@dimen/dimen4dp"
|
||||
app:tabTextAppearance="@style/customTabLayout"
|
||||
app:tabTextColor="?attr/primaryTextColor"/>
|
||||
app:tabMode="fixed"
|
||||
app:tabGravity="fill"
|
||||
app:tabIndicatorAnimationMode="elastic"
|
||||
app:tabSelectedTextColor="?attr/colorPrimary" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
@@ -32,6 +35,6 @@
|
||||
android:id="@+id/containerExplore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
132
app/src/main/res/layout/activity_repositories.xml
Normal file
132
app/src/main/res/layout/activity_repositories.xml
Normal file
@@ -0,0 +1,132 @@
|
||||
<?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:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/primaryBackgroundColor">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/pullToRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingTop="@dimen/dimen54dp"
|
||||
android:paddingBottom="@dimen/dimen80dp"
|
||||
android:paddingHorizontal="@dimen/dimen12dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||
|
||||
<com.google.android.material.loadingindicator.LoadingIndicator
|
||||
android:id="@+id/expressive_loader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
app:indicatorSize="@dimen/dimen48dp"
|
||||
app:trackThickness="@dimen/dimen4dp" />
|
||||
|
||||
<include
|
||||
android:id="@+id/layout_empty"
|
||||
layout="@layout/layout_empty_state" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<com.google.android.material.dockedtoolbar.DockedToolbarLayout
|
||||
android:id="@+id/docked_toolbar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:paddingBottomSystemWindowInsets="false"
|
||||
app:paddingLeftSystemWindowInsets="false"
|
||||
app:paddingRightSystemWindowInsets="false"
|
||||
app:paddingTopSystemWindowInsets="false"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginBottom="@dimen/dimen32dp"
|
||||
app:shapeAppearanceOverlay="@style/ShapeAppearance.RoundedDock"
|
||||
android:backgroundTint="?attr/colorSurfaceContainerHigh"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideViewOnScrollBehavior">
|
||||
|
||||
<com.google.android.material.overflow.OverflowLinearLayout
|
||||
android:id="@+id/docked_toolbar_child"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_back"
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_arrow_back"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="@dimen/dimen0dp"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_marginEnd="@dimen/dimen4dp"
|
||||
android:insetLeft="@dimen/dimen0dp"
|
||||
android:insetRight="@dimen/dimen0dp"
|
||||
android:contentDescription="@string/close" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_new_repository"
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_add"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="@dimen/dimen0dp"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_marginEnd="@dimen/dimen4dp"
|
||||
android:insetLeft="@dimen/dimen0dp"
|
||||
android:insetRight="@dimen/dimen0dp"
|
||||
android:contentDescription="@string/addButton" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_search"
|
||||
style="?attr/materialIconButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_search"
|
||||
app:iconGravity="textStart"
|
||||
app:iconPadding="@dimen/dimen0dp"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_marginEnd="@dimen/dimen4dp"
|
||||
android:insetLeft="@dimen/dimen0dp"
|
||||
android:insetRight="@dimen/dimen0dp"
|
||||
android:contentDescription="@string/search" />
|
||||
|
||||
</com.google.android.material.overflow.OverflowLinearLayout>
|
||||
|
||||
</com.google.android.material.dockedtoolbar.DockedToolbarLayout>
|
||||
|
||||
<com.google.android.material.search.SearchView
|
||||
android:id="@+id/search_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:hint="@string/search"
|
||||
app:navigationIcon="@drawable/ic_arrow_back"
|
||||
app:backgroundTint="?attr/primaryBackgroundColor">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/search_results_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/dimen12dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||
|
||||
</com.google.android.material.search.SearchView>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -18,11 +18,6 @@
|
||||
app:destination="@id/myRepositoriesFragment"
|
||||
app:popUpTo="@id/homeDashboardFragment"
|
||||
app:popUpToInclusive="false" />
|
||||
<action
|
||||
android:id="@+id/action_to_starredRepositories"
|
||||
app:destination="@id/starredRepositoriesFragment"
|
||||
app:popUpTo="@id/homeDashboardFragment"
|
||||
app:popUpToInclusive="false" />
|
||||
<action
|
||||
android:id="@+id/action_to_watchedRepositories"
|
||||
app:destination="@id/watchedRepositoriesFragment"
|
||||
@@ -60,11 +55,6 @@
|
||||
android:name="org.mian.gitnex.fragments.NotificationsFragment"
|
||||
android:label="Notifications" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/exploreFragment"
|
||||
android:name="org.mian.gitnex.fragments.ExploreFragment"
|
||||
android:label="Explore" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/myIssuesFragment"
|
||||
android:name="org.mian.gitnex.fragments.MyIssuesFragment"
|
||||
@@ -80,11 +70,6 @@
|
||||
android:name="org.mian.gitnex.fragments.MyRepositoriesFragment"
|
||||
android:label="My Repositories" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/starredRepositoriesFragment"
|
||||
android:name="org.mian.gitnex.fragments.StarredRepositoriesFragment"
|
||||
android:label="Starred Repositories" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/watchedRepositoriesFragment"
|
||||
android:name="org.mian.gitnex.fragments.WatchedRepositoriesFragment"
|
||||
|
||||
Reference in New Issue
Block a user