package com.kenny.openimgur.fragments; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.AlertDialog; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.SearchView; import android.text.TextUtils; 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.widget.Button; import android.widget.FilterQueryProvider; import com.kenny.openimgur.R; import com.kenny.openimgur.api.ApiClient; import com.kenny.openimgur.api.ImgurService; import com.kenny.openimgur.api.responses.GalleryResponse; import com.kenny.openimgur.classes.FragmentListener; import com.kenny.openimgur.classes.ImgurFilters; import com.kenny.openimgur.classes.ImgurFilters.RedditSort; import com.kenny.openimgur.ui.adapters.SearchAdapter; import com.kenny.openimgur.util.DBContracts; import com.kenny.openimgur.util.LogUtil; import com.kenny.openimgur.util.RequestCodes; import com.kenny.openimgur.util.SqlHelper; import com.kenny.openimgur.util.ViewUtils; import com.kennyc.view.MultiStateView; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import butterknife.BindView; import butterknife.OnClick; /** * Created by kcampagna on 8/14/14. */ public class RedditFragment extends BaseGridFragment { public static final String KEY_PINNED_SUBREDDITS = "pinnedSubreddits"; private static final String KEY_QUERY = "query"; private static final String KEY_SORT = "redditSort"; private static final String KEY_TOP_SORT = "redditTopSort"; @BindView(R.id.mySubreddits) Button mMySubredditsBtn; String mQuery; private RedditSort mSort; private ImgurFilters.TimeSort mTopSort; SearchAdapter mCursorAdapter; private MenuItem mSearchMenuItem; private SearchView mSearchView; private final Set<String> mPinnedSubs = new HashSet<>(); public static RedditFragment newInstance() { return new RedditFragment(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_reddit, container, false); } @Override public void onResume() { super.onResume(); if (getAdapter() == null || getAdapter().isEmpty()) { mIsLoading = false; mMultiStateView.setViewState(MultiStateView.VIEW_STATE_EMPTY); if (mListener != null) mListener.onFragmentStateChange(FragmentListener.STATE_LOADING_COMPLETE); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.reddit, menu); mSearchMenuItem = menu.findItem(R.id.search); mSearchView = (SearchView) MenuItemCompat.getActionView(mSearchMenuItem); mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String text) { return search(text); } @Override public boolean onQueryTextChange(String s) { return false; } }); mSearchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() { @Override public boolean onSuggestionSelect(int position) { String title = mCursorAdapter.getTitle(position); return search(title); } @Override public boolean onSuggestionClick(int position) { String title = mCursorAdapter.getTitle(position); return search(title); } }); if (getActivity() != null) { mSearchView.setQueryHint(getString(R.string.enter_sub_reddit)); mCursorAdapter = new SearchAdapter(getActivity(), SqlHelper.getInstance(getActivity()).getSubReddits(), DBContracts.SubRedditContract.COLUMN_NAME); mCursorAdapter.setFilterQueryProvider(new FilterQueryProvider() { @Override public Cursor runQuery(CharSequence constraint) { return SqlHelper.getInstance(getActivity()).getSubReddits(constraint.toString()); } }); mSearchView.setSuggestionsAdapter(mCursorAdapter); } super.onCreateOptionsMenu(menu, inflater); } @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); boolean hasPinned = !mPinnedSubs.isEmpty(); menu.findItem(R.id.mySubreddits).setVisible(hasPinned); if (mMySubredditsBtn != null) { mMySubredditsBtn.setVisibility(hasPinned ? View.VISIBLE : View.GONE); } MenuItem action = menu.findItem(R.id.mySubredditAction); if (TextUtils.isEmpty(mQuery)) { action.setVisible(false); } else { action.setVisible(true); boolean isPinned = mPinnedSubs.contains(mQuery); action.setTitle(isPinned ? R.string.my_subreddits_remove : R.string.my_subreddits_add); action.setIcon(isPinned ? R.drawable.ic_remove_circle_outline_24dp : R.drawable.ic_add_circle_outline_24dp); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.filter: Activity activity = getActivity(); View anchor; anchor = activity.findViewById(R.id.filter); if (anchor == null) anchor = activity.findViewById(R.id.refresh); if (anchor == null) anchor = activity.findViewById(R.id.search); PopupMenu m = new PopupMenu(getActivity(), anchor); m.inflate(R.menu.filter_reddit); m.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.newest: onFilterChanged(RedditSort.TIME, ImgurFilters.TimeSort.DAY); return true; case R.id.topDay: onFilterChanged(RedditSort.TOP, ImgurFilters.TimeSort.DAY); return true; case R.id.topWeek: onFilterChanged(RedditSort.TOP, ImgurFilters.TimeSort.WEEK); return true; case R.id.topMonth: onFilterChanged(RedditSort.TOP, ImgurFilters.TimeSort.MONTH); return true; case R.id.topYear: onFilterChanged(RedditSort.TOP, ImgurFilters.TimeSort.YEAR); return true; case R.id.topAll: onFilterChanged(RedditSort.TOP, ImgurFilters.TimeSort.ALL); return true; } return false; } }); m.show(); return true; case R.id.refresh: if (!TextUtils.isEmpty(mQuery)) refresh(); return true; case R.id.mySubreddits: viewMySubreddits(); return true; case R.id.mySubredditAction: int messageId; if (mPinnedSubs.contains(mQuery)) { mPinnedSubs.remove(mQuery); messageId = R.string.subreddit_removed; } else { mPinnedSubs.add(mQuery); messageId = R.string.subreddit_added; } getActivity().invalidateOptionsMenu(); Snackbar.make(getSnackbarView(), messageId, Snackbar.LENGTH_LONG).show(); saveSubreddits(); return true; } return super.onOptionsItemSelected(item); } boolean search(String query) { if (!mIsLoading && !TextUtils.isEmpty(query)) { if (getAdapter() != null) { getAdapter().clear(); } mQuery = query; mCurrentPage = 0; mHasMore = true; mSearchView.setQuery(mQuery, false); mMultiStateView.setViewState(MultiStateView.VIEW_STATE_LOADING); if (mListener != null) { mListener.onFragmentStateChange(FragmentListener.STATE_LOADING_STARTED); mListener.onUpdateActionBarTitle(mQuery); } fetchGallery(); mSearchMenuItem.collapseActionView(); return true; } return false; } @OnClick(R.id.mySubreddits) public void viewMySubreddits() { // Alphabetize the list List<String> subreddits = new ArrayList<>(mPinnedSubs); Collections.sort(subreddits); final String[] items = new String[subreddits.size()]; subreddits.toArray(items); new AlertDialog.Builder(getActivity(), theme.getAlertDialogTheme()) .setTitle(R.string.my_subreddits) .setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { String query = items[i]; if (!query.equals(mQuery)) { search(items[i]); } } }) .setPositiveButton(R.string.close, null) .show(); } void onFilterChanged(RedditSort sort, ImgurFilters.TimeSort topSort) { if (sort == mSort && topSort == mTopSort) { // Don't fetch data if they haven't changed anything LogUtil.v(TAG, "Filters have not been updated"); return; } mSort = sort; mTopSort = topSort; // Don't bother making an Api call if the there is no present query if (getAdapter() != null && !getAdapter().isEmpty() && !TextUtils.isEmpty(mQuery)) { getAdapter().clear(); mMultiStateView.setViewState(MultiStateView.VIEW_STATE_LOADING); mCurrentPage = 0; mIsLoading = true; mHasMore = true; fetchGallery(); } saveFilterSettings(); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString(KEY_SORT, mSort.getSort()); outState.putString(KEY_QUERY, mQuery); outState.putString(KEY_TOP_SORT, mTopSort.getSort()); } @Override protected void onRestoreSavedInstance(Bundle savedInstanceState) { super.onRestoreSavedInstance(savedInstanceState); SharedPreferences pref = app.getPreferences(); if (savedInstanceState == null) { mSort = RedditSort.getSortFromString(pref.getString(KEY_SORT, RedditSort.TIME.getSort())); mTopSort = ImgurFilters.TimeSort.getSortFromString(pref.getString(KEY_TOP_SORT, ImgurFilters.TimeSort.DAY.getSort())); } else { mQuery = savedInstanceState.getString(KEY_QUERY, null); mSort = RedditSort.getSortFromString(savedInstanceState.getString(KEY_SORT, RedditSort.TIME.getSort())); mTopSort = ImgurFilters.TimeSort.getSortFromString(savedInstanceState.getString(KEY_TOP_SORT, ImgurFilters.TimeSort.DAY.getSort())); } if (TextUtils.isEmpty(mQuery) && mListener != null) { mListener.onUpdateActionBarTitle(getString(R.string.subreddit)); } else if (mListener != null) { mListener.onUpdateActionBarTitle(mQuery); } Set<String> pinned = pref.getStringSet(KEY_PINNED_SUBREDDITS, null); if (pinned != null) mPinnedSubs.addAll(pinned); } private void saveFilterSettings() { app.getPreferences().edit() .putString(KEY_SORT, mSort.getSort()).putString(KEY_TOP_SORT, mTopSort.getSort()) .apply(); } private void saveSubreddits() { if (mPinnedSubs.isEmpty()) { // Remove from shared preferences if saved if (app.getPreferences().contains(KEY_PINNED_SUBREDDITS)) app.getPreferences().edit().remove(KEY_PINNED_SUBREDDITS).apply(); } else { app.getPreferences().edit().putStringSet(KEY_PINNED_SUBREDDITS, mPinnedSubs).apply(); } } @Override public void onDestroyView() { mSearchMenuItem = null; mSearchView = null; if (mCursorAdapter != null && mCursorAdapter.getCursor() != null && !mCursorAdapter.getCursor().isClosed()) { mCursorAdapter.getCursor().close(); } super.onDestroyView(); } @Override protected void fetchGallery() { if (TextUtils.isEmpty(mQuery)) return; super.fetchGallery(); ImgurService apiService = ApiClient.getService(); String query = mQuery.replaceAll("\\s", ""); if (query.startsWith("r/")) query = query.replace("r/", ""); if (mSort == RedditSort.TOP) { apiService.getSubRedditForTopSorted(query, mTopSort.getSort(), mCurrentPage).enqueue(this); } else { apiService.getSubReddit(query, mSort.getSort(), mCurrentPage).enqueue(this); } } @Override protected void onApiResult(@NonNull GalleryResponse galleryResponse) { super.onApiResult(galleryResponse); if (mCurrentPage == 0 && !galleryResponse.data.isEmpty()) { SqlHelper sql = SqlHelper.getInstance(getActivity()); sql.addSubReddit(mQuery); if (mCursorAdapter == null) { mCursorAdapter = new SearchAdapter(getActivity(), sql.getSubReddits(mQuery), DBContracts.SubRedditContract.COLUMN_NAME); mSearchView.setSuggestionsAdapter(mCursorAdapter); } else { mCursorAdapter.changeCursor(sql.getSubReddits(mQuery)); } mCursorAdapter.notifyDataSetChanged(); getActivity().invalidateOptionsMenu(); } } @Override protected void onEmptyResults() { super.onEmptyResults(); ViewUtils.setEmptyText(mMultiStateView, R.id.empty, getString(R.string.reddit_empty, mQuery)); mQuery = null; getActivity().invalidateOptionsMenu(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == RequestCodes.SETTINGS) { // Reload pinned subreddits mPinnedSubs.clear(); Set<String> pinned = app.getPreferences().getStringSet(KEY_PINNED_SUBREDDITS, null); if (pinned != null) mPinnedSubs.addAll(pinned); getActivity().invalidateOptionsMenu(); } } }