package me.ccrama.redditslide.Fragments; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.TextView; import com.afollestad.materialdialogs.AlertDialogWrapper; import com.afollestad.materialdialogs.MaterialDialog; import com.mikepenz.itemanimators.AlphaInAnimator; import com.mikepenz.itemanimators.SlideUpAlphaAnimator; import net.dean.jraw.models.MultiReddit; import net.dean.jraw.models.MultiSubreddit; import net.dean.jraw.models.Submission; import java.util.ArrayList; import java.util.List; import me.ccrama.redditslide.Activities.Submit; import me.ccrama.redditslide.Adapters.MultiredditAdapter; import me.ccrama.redditslide.Adapters.MultiredditPosts; import me.ccrama.redditslide.Adapters.SubmissionDisplay; import me.ccrama.redditslide.Constants; import me.ccrama.redditslide.HasSeen; import me.ccrama.redditslide.Hidden; import me.ccrama.redditslide.LastComments; import me.ccrama.redditslide.OfflineSubreddit; import me.ccrama.redditslide.R; import me.ccrama.redditslide.Reddit; import me.ccrama.redditslide.SettingValues; import me.ccrama.redditslide.UserSubscriptions; import me.ccrama.redditslide.Views.CatchStaggeredGridLayoutManager; import me.ccrama.redditslide.Views.CreateCardView; import me.ccrama.redditslide.Visuals.Palette; import me.ccrama.redditslide.handler.ToolbarScrollHideHandler; public class MultiredditView extends Fragment implements SubmissionDisplay { private static final String EXTRA_PROFILE = "profile"; public MultiredditAdapter adapter; public MultiredditPosts posts; public RecyclerView rv; public FloatingActionButton fab; public int diff; private SwipeRefreshLayout refreshLayout; private int id; private int totalItemCount; private int visibleItemCount; private int pastVisiblesItems; private String profile; @NonNull private RecyclerView.LayoutManager createLayoutManager(final int numColumns) { return new CatchStaggeredGridLayoutManager(numColumns, CatchStaggeredGridLayoutManager.VERTICAL); } private int getNumColumns(final int orientation) { final int numColumns; if (orientation == Configuration.ORIENTATION_LANDSCAPE && SettingValues.tabletUI) { numColumns = Reddit.dpWidth; } else if (orientation == Configuration.ORIENTATION_PORTRAIT && SettingValues.dualPortrait) { numColumns = 2; } else { numColumns = 1; } return numColumns; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_verticalcontent, container, false); rv = ((RecyclerView) v.findViewById(R.id.vertical_content)); final RecyclerView.LayoutManager mLayoutManager = createLayoutManager(getNumColumns(getResources().getConfiguration().orientation)); rv.setLayoutManager(mLayoutManager); if (SettingValues.fab) { fab = (FloatingActionButton) v.findViewById(R.id.post_floating_action_button); if (SettingValues.fabType == Constants.FAB_POST) { fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final ArrayList<String> subs = new ArrayList<>(); for (MultiSubreddit s : posts.multiReddit.getSubreddits()) { subs.add(s.getDisplayName()); } new MaterialDialog.Builder(getActivity()) .title(R.string.multi_submit_which_sub) .items(subs) .itemsCallback(new MaterialDialog.ListCallback() { @Override public void onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) { Intent i = new Intent(getActivity(), Submit.class); i.putExtra(Submit.EXTRA_SUBREDDIT, subs.get(which)); startActivity(i); } }).show(); } }); } else { fab.setImageResource(R.drawable.hide); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!Reddit.fabClear) { new AlertDialogWrapper.Builder(getActivity()).setTitle(R.string.settings_fabclear) .setMessage(R.string.settings_fabclear_msg) .setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Reddit.colors.edit().putBoolean(SettingValues.PREF_FAB_CLEAR, true).apply(); Reddit.fabClear = true; clearSeenPosts(false); } }).show(); } else { clearSeenPosts(false); } } }); fab.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (!Reddit.fabClear) { new AlertDialogWrapper.Builder(getActivity()).setTitle(R.string.settings_fabclear) .setMessage(R.string.settings_fabclear_msg) .setPositiveButton(R.string.btn_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Reddit.colors.edit().putBoolean(SettingValues.PREF_FAB_CLEAR, true).apply(); Reddit.fabClear = true; clearSeenPosts(true); } }).show(); } else { clearSeenPosts(true); } /* ToDo Make a sncakbar with an undo option of the clear all View.OnClickListener undoAction = new View.OnClickListener() { @Override public void onClick(View v) { adapter.dataSet.posts = original; for(Submission post : adapter.dataSet.posts){ if(HasSeen.getSeen(post.getFullName())) Hidden.undoHidden(post); } } };*/ Snackbar s = Snackbar.make(rv, getResources().getString(R.string.posts_hidden_forever), Snackbar.LENGTH_LONG); View view = s.getView(); TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text); tv.setTextColor(Color.WHITE); s.show(); return false; } }); } } else { v.findViewById(R.id.post_floating_action_button).setVisibility(View.GONE); } refreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.activity_main_swipe_refresh_layout); /** * If using List view mode, we need to remove the start margin from the SwipeRefreshLayout. * The scrollbar style of "outsideInset" creates a 4dp padding around it. To counter this, * change the scrollbar style to "insideOverlay" when list view is enabled. * To recap: this removes the margins from the start/end so list view is full-width. */ if (SettingValues.defaultCardView == CreateCardView.CardEnum.LIST) { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { params.setMarginStart(0); } rv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); refreshLayout.setLayoutParams(params); } List<MultiReddit> multireddits; if (profile.isEmpty()) { multireddits = UserSubscriptions.multireddits; } else { multireddits = UserSubscriptions.public_multireddits.get(profile); } if ((multireddits != null) && !multireddits.isEmpty()) { refreshLayout.setColorSchemeColors(Palette.getColors(multireddits.get(id).getDisplayName(), getActivity())); } //If we use 'findViewById(R.id.header).getMeasuredHeight()', 0 is always returned. //So, we estimate the height of the header in dp refreshLayout.setProgressViewOffset(false, Constants.TAB_HEADER_VIEW_OFFSET - Constants.PTR_OFFSET_TOP, Constants.TAB_HEADER_VIEW_OFFSET + Constants.PTR_OFFSET_BOTTOM); refreshLayout.post(new Runnable() { @Override public void run() { refreshLayout.setRefreshing(true); } }); if ((multireddits != null) && !multireddits.isEmpty()) { posts = new MultiredditPosts(multireddits.get(id).getDisplayName(), profile); adapter = new MultiredditAdapter(getActivity(), posts, rv, refreshLayout, this); rv.setAdapter(adapter); rv.setItemAnimator(new SlideUpAlphaAnimator()); posts.loadMore(getActivity(), this, true, adapter); refreshLayout.setOnRefreshListener( new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { posts.loadMore(getActivity(), MultiredditView.this, true, adapter); //TODO catch errors } } ); if (fab != null) { fab.show(); } rv.addOnScrollListener(new ToolbarScrollHideHandler((Toolbar) (getActivity()).findViewById(R.id.toolbar), getActivity().findViewById(R.id.header)) { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); visibleItemCount = rv.getLayoutManager().getChildCount(); totalItemCount = rv.getLayoutManager().getItemCount(); int[] firstVisibleItems; firstVisibleItems = ((CatchStaggeredGridLayoutManager) rv.getLayoutManager()).findFirstVisibleItemPositions(null); if (firstVisibleItems != null && firstVisibleItems.length > 0) { for (int firstVisibleItem : firstVisibleItems) { pastVisiblesItems = firstVisibleItem; if (SettingValues.scrollSeen && pastVisiblesItems > 0 && SettingValues.storeHistory) { HasSeen.addSeenScrolling(posts.posts.get(pastVisiblesItems - 1).getFullName()); } } } if (!posts.loading) { if ((visibleItemCount + pastVisiblesItems) + 5 >= totalItemCount && !posts.nomore) { posts.loading = true; posts.loadMore(getActivity(), MultiredditView.this, false, adapter); } } if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { diff += dy; } else { diff = 0; } if (fab != null) { if (dy <= 0 && fab.getId() != 0 && SettingValues.fab) { if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_DRAGGING || diff < -fab.getHeight() * 2) fab.show(); } else { fab.hide(); } } } }); } return v; } private List<Submission> clearSeenPosts(boolean forever) { if (posts.posts != null) { List<Submission> originalDataSetPosts = posts.posts; OfflineSubreddit o = OfflineSubreddit.getSubreddit("multi" + posts.multiReddit.getDisplayName().toLowerCase(), false, getActivity()); for (int i = posts.posts.size(); i > -1; i--) { try { if (HasSeen.getSeen(posts.posts.get(i))) { if (forever) { Hidden.setHidden(posts.posts.get(i)); } o.clearPost(posts.posts.get(i)); posts.posts.remove(i); if (posts.posts.isEmpty()) { adapter.notifyDataSetChanged(); } else { rv.setItemAnimator(new AlphaInAnimator()); adapter.notifyItemRemoved(i + 1); } } } catch (IndexOutOfBoundsException e) { //Let the loop reset itself } } o.writeToMemoryNoStorage(); rv.setItemAnimator(new SlideUpAlphaAnimator()); return originalDataSetPosts; } return null; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle bundle = this.getArguments(); id = bundle.getInt("id", 0); profile = bundle.getString(EXTRA_PROFILE, ""); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); final int currentOrientation = newConfig.orientation; final CatchStaggeredGridLayoutManager mLayoutManager = (CatchStaggeredGridLayoutManager) rv.getLayoutManager(); mLayoutManager.setSpanCount(getNumColumns(currentOrientation)); } @Override public void updateSuccess(List<Submission> submissions, final int startIndex) { adapter.context.runOnUiThread(new Runnable() { @Override public void run() { refreshLayout.setRefreshing(false); if (startIndex != -1) { adapter.notifyItemRangeInserted(startIndex + 1, posts.posts.size()); } else { adapter.notifyDataSetChanged(); } } }); } @Override public void updateOffline(List<Submission> submissions, long cacheTime) { adapter.setError(true); refreshLayout.setRefreshing(false); } @Override public void updateOfflineError() { } @Override public void updateError() { } @Override public void updateViews() { try { adapter.notifyItemRangeChanged(0, adapter.dataSet.getPosts().size()); } catch(Exception e){ } } }