package com.gh4a.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import com.gh4a.BaseActivity;
import com.gh4a.Gh4Application;
import com.gh4a.R;
import com.gh4a.loader.LoaderCallbacks;
import com.gh4a.utils.ApiHelpers;
import com.gh4a.widget.SwipeRefreshLayout;
import org.eclipse.egit.github.core.Repository;
public class RepositoryListContainerFragment extends Fragment implements
LoaderCallbacks.ParentCallback, SearchView.OnCloseListener, SearchView.OnQueryTextListener,
MenuItemCompat.OnActionExpandListener, SwipeRefreshLayout.ChildScrollDelegate {
public static RepositoryListContainerFragment newInstance(String userLogin, boolean isOrg) {
RepositoryListContainerFragment f = new RepositoryListContainerFragment();
Bundle args = new Bundle();
args.putString("user", userLogin);
args.putBoolean("is_org", isOrg);
f.setArguments(args);
return f;
}
private String mUserLogin;
private boolean mIsOrg;
private String mFilterType = "all";
private String mSortOrder = "full_name";
private String mSortDirection = "asc";
private boolean mSearchVisible;
private PagedDataBaseFragment<Repository> mMainFragment;
private RepositorySearchFragment mSearchFragment;
private MenuItem mFilterItem;
private String mSearchQuery;
public interface Callback {
void initiateFilter();
}
private static final String STATE_KEY_FILTER_TYPE = "filter_type";
private static final String STATE_KEY_SORT_ORDER = "sort_order";
private static final String STATE_KEY_SORT_DIRECTION = "sort_direction";
private static final String STATE_KEY_SEARCH_VISIBLE = "search_visible";
private static final String STATE_KEY_QUERY = "search_query";
@Override
public void onCreate(Bundle savedInstanceState) {
Bundle data = getArguments();
mUserLogin = data.getString("user");
mIsOrg = data.getBoolean("is_org");
if (savedInstanceState != null && savedInstanceState.containsKey(STATE_KEY_FILTER_TYPE)) {
mFilterType = savedInstanceState.getString(STATE_KEY_FILTER_TYPE);
mSortOrder = savedInstanceState.getString(STATE_KEY_SORT_ORDER);
mSortDirection = savedInstanceState.getString(STATE_KEY_SORT_DIRECTION);
mSearchVisible = savedInstanceState.getBoolean(STATE_KEY_SEARCH_VISIBLE);
mSearchQuery = savedInstanceState.getString(STATE_KEY_QUERY);
}
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
@Override
public BaseActivity getBaseActivity() {
return (BaseActivity) getActivity();
}
@Override
public void onRefresh() {
mMainFragment.onRefresh();
mSearchFragment.onRefresh();
}
public void destroyChildren() {
getChildFragmentManager().beginTransaction()
.remove(mMainFragment)
.remove(mSearchFragment)
.commitNowAllowingStateLoss();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.frame_layout, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
FragmentManager fm = getChildFragmentManager();
mMainFragment = (PagedDataBaseFragment<Repository>) fm.findFragmentByTag("main");
mSearchFragment = (RepositorySearchFragment) fm.findFragmentByTag("search");
if (mMainFragment == null) {
applyFilterTypeAndSortOrder();
addSearchFragment();
} else {
setSearchVisibility(mSearchVisible);
}
}
@Override
public boolean canChildScrollUp() {
if (mFilterItem != null && !mFilterItem.isVisible()) {
// search mode
return mSearchFragment.canChildScrollUp();
}
return mMainFragment.canChildScrollUp();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(STATE_KEY_FILTER_TYPE, mFilterType);
outState.putString(STATE_KEY_SORT_ORDER, mSortOrder);
outState.putString(STATE_KEY_SORT_DIRECTION, mSortDirection);
outState.putBoolean(STATE_KEY_SEARCH_VISIBLE, mSearchVisible);
outState.putString(STATE_KEY_QUERY, mSearchQuery);
}
public void setFilterType(String type) {
if (!TextUtils.equals(type, mFilterType)) {
mFilterType = type;
applyFilterTypeAndSortOrder();
}
}
public void setSortOrder(String sortOrder, String direction) {
if (!TextUtils.equals(sortOrder, mSortOrder) || !TextUtils.equals(mSortDirection, direction)) {
mSortOrder = sortOrder;
mSortDirection = direction;
validateSortOrder();
applyFilterTypeAndSortOrder();
}
}
private void validateSortOrder() {
if (TextUtils.equals(mFilterType, "starred")) {
if (!TextUtils.equals(mSortOrder, "updated")
&& !TextUtils.equals(mSortOrder, "created")) {
mSortOrder = "created";
mSortDirection = "desc";
}
} else {
if (!TextUtils.equals(mSortOrder, "full_name")
&& !TextUtils.equals(mSortOrder, "created")
&& !TextUtils.equals(mSortOrder, "pushed")) {
mSortOrder = "full_name";
mSortDirection = "asc";
}
}
}
private void applyFilterTypeAndSortOrder() {
if (!isAdded()) {
// we'll do this in onActivityCreated()
return;
}
switch (mFilterType) {
case "starred":
mMainFragment = StarredRepositoryListFragment.newInstance(mUserLogin,
mSortOrder, mSortDirection);
break;
case "watched":
mMainFragment = WatchedRepositoryListFragment.newInstance(mUserLogin);
break;
default:
mMainFragment = RepositoryListFragment.newInstance(mUserLogin, mIsOrg,
mFilterType, mSortOrder, mSortDirection);
break;
}
FragmentManager fm = getChildFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment old = fm.findFragmentByTag("main");
if (old != null) {
ft.remove(old);
}
ft.add(R.id.details, mMainFragment, "main");
ft.commitAllowingStateLoss();
}
public String getFilterType() {
return mFilterType;
}
public String getSortOrder() {
validateSortOrder();
return mSortOrder;
}
public String getSortDirection() {
return mSortDirection;
}
private void addSearchFragment() {
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
mSearchFragment = RepositorySearchFragment.newInstance(mUserLogin);
mSearchFragment.setUserVisibleHint(false);
ft.add(R.id.details, mSearchFragment, "search");
ft.hide(mSearchFragment);
ft.commit();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
getActivity().getMenuInflater().inflate(R.menu.repo_list_menu, menu);
// We can only properly search the 'all repos' list
if ("all".equals(mFilterType)) {
MenuItem searchItem = menu.findItem(R.id.search);
MenuItemCompat.setOnActionExpandListener(searchItem, this);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
if (mSearchQuery != null) {
MenuItemCompat.expandActionView(searchItem);
searchView.setQuery(mSearchQuery, false);
}
searchView.setOnCloseListener(this);
searchView.setOnQueryTextListener(this);
} else {
menu.removeItem(R.id.search);
}
mFilterItem = menu.findItem(R.id.filter);
mFilterItem.setVisible(!mSearchVisible);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search:
setSearchVisibility(true);
return true;
case R.id.filter:
if (getActivity() instanceof Callback) {
((Callback) getActivity()).initiateFilter();
}
return true;
}
return super.onOptionsItemSelected(item);
}
private void setSearchVisibility(boolean visible) {
String hiddenTag = visible ? "main" : "search";
String visibleTag = visible ? "search" : "main";
FragmentManager fm = getChildFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
mSearchVisible = visible;
if (mFilterItem != null) {
mFilterItem.setVisible(!visible);
}
mSearchFragment.setQuery(null);
mSearchFragment.setUserVisibleHint(visible);
ft.hide(fm.findFragmentByTag(hiddenTag));
ft.show(fm.findFragmentByTag(visibleTag));
ft.commit();
}
@Override
public boolean onQueryTextSubmit(String query) {
if (mSearchFragment != null) {
mSearchFragment.setQuery(query);
}
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
mSearchQuery = newText;
return false;
}
@Override
public boolean onClose() {
mSearchQuery = null;
setSearchVisibility(false);
return false;
}
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
mSearchQuery = null;
setSearchVisibility(false);
return true;
}
private static void setMenuItemChecked(MenuItem item, int selected, SparseArray<?> relevant) {
if (relevant.indexOfKey(item.getItemId()) >= 0) {
item.setChecked(item.getItemId() == selected);
}
}
private static void setMenuItemChecked(Menu menu, int selected, SparseArray<?> relevant) {
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
if (item.hasSubMenu()) {
SubMenu sm = item.getSubMenu();
for (int j = 0; j < sm.size(); j++) {
setMenuItemChecked(sm.getItem(j), selected, relevant);
}
} else {
setMenuItemChecked(item, selected, relevant);
}
}
}
public static class FilterDrawerHelper {
private final int mMenuResId;
private static final SparseArray<String> FILTER_LOOKUP = new SparseArray<>();
static {
FILTER_LOOKUP.put(R.id.filter_type_all, "all");
FILTER_LOOKUP.put(R.id.filter_type_owner, "owner");
FILTER_LOOKUP.put(R.id.filter_type_member, "member");
FILTER_LOOKUP.put(R.id.filter_type_public, "public");
FILTER_LOOKUP.put(R.id.filter_type_private, "private");
FILTER_LOOKUP.put(R.id.filter_type_sources, "sources");
FILTER_LOOKUP.put(R.id.filter_type_forks, "forks");
FILTER_LOOKUP.put(R.id.filter_type_watched, "watched");
FILTER_LOOKUP.put(R.id.filter_type_starred, "starred");
}
public static FilterDrawerHelper create(String userLogin, boolean isOrg) {
int menuResId;
if (ApiHelpers.loginEquals(userLogin, Gh4Application.get().getAuthLogin())) {
menuResId = R.menu.repo_filter_logged_in;
} else if (isOrg) {
menuResId = R.menu.repo_filter_org;
} else {
menuResId = R.menu.repo_filter_user;
}
return new FilterDrawerHelper(menuResId);
}
private FilterDrawerHelper(int menuResId) {
mMenuResId = menuResId;
}
public int getMenuResId() {
return mMenuResId;
}
public void selectFilterType(Menu menu, String filterType) {
int selectedId = 0;
for (int i = 0; i < FILTER_LOOKUP.size(); i++) {
if (FILTER_LOOKUP.valueAt(i).equals(filterType)) {
selectedId = FILTER_LOOKUP.keyAt(i);
break;
}
}
setMenuItemChecked(menu, selectedId, FILTER_LOOKUP);
}
public String handleSelectionAndGetFilterType(MenuItem item) {
return FILTER_LOOKUP.get(item.getItemId());
}
}
public static class SortDrawerHelper {
private String mFilterType = "all";
private static final SparseArray<String[]> SORT_LOOKUP = new SparseArray<>();
static {
SORT_LOOKUP.put(R.id.sort_name_asc, new String[] { "full_name", "asc" });
SORT_LOOKUP.put(R.id.sort_name_desc, new String[] { "full_name", "desc" });
SORT_LOOKUP.put(R.id.sort_created_asc, new String[] { "created", "asc" });
SORT_LOOKUP.put(R.id.sort_created_desc, new String[] { "created", "desc" });
SORT_LOOKUP.put(R.id.sort_pushed_asc, new String[] { "pushed", "asc" });
SORT_LOOKUP.put(R.id.sort_pushed_desc, new String[] { "pushed", "desc" });
SORT_LOOKUP.put(R.id.sort_updated_asc, new String[] { "updated", "asc" });
SORT_LOOKUP.put(R.id.sort_updated_desc, new String[] { "updated", "desc" });
}
public SortDrawerHelper() {
}
public void setFilterType(String type) {
mFilterType = type;
}
public int getMenuResId() {
return TextUtils.equals(mFilterType, "starred") ? R.menu.repo_starred_sort
: TextUtils.equals(mFilterType, "watched") ? 0
: R.menu.repo_sort;
}
public void selectSortType(Menu menu, String order, String direction) {
int selectedId = 0;
for (int i = 0; i < SORT_LOOKUP.size(); i++) {
String[] value = SORT_LOOKUP.valueAt(i);
if (value[0].equals(order) && value[1].equals(direction)) {
selectedId = SORT_LOOKUP.keyAt(i);
break;
}
}
setMenuItemChecked(menu, selectedId, SORT_LOOKUP);
}
public String[] handleSelectionAndGetSortOrder(MenuItem item) {
return SORT_LOOKUP.get(item.getItemId());
}
}
}