package com.xda.one.ui; import com.squareup.otto.Subscribe; import com.xda.one.R; import com.xda.one.api.inteface.ThreadClient; import com.xda.one.api.model.response.ResponseUnifiedThread; import com.xda.one.api.model.response.container.ResponsePostContainer; import com.xda.one.api.retrofit.RetrofitThreadClient; import com.xda.one.event.thread.ThreadSubscriptionChangedEvent; import com.xda.one.event.thread.ThreadSubscriptionChangingFailedEvent; import com.xda.one.model.augmented.AugmentedPost; import com.xda.one.model.augmented.AugmentedUnifiedThread; import com.xda.one.ui.helper.QuickReturnHelper; import com.xda.one.ui.widget.FloatingActionButton; import com.xda.one.util.AccountUtils; import com.xda.one.util.CompatUtils; import com.xda.one.util.UIUtils; import android.annotation.TargetApi; import android.app.Activity; import android.content.Intent; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.support.v7.widget.XDALinerLayoutManager; import android.text.Html; 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.animation.Animation; import android.view.animation.Transformation; import android.widget.BaseAdapter; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class PostPagerFragment extends Fragment implements PostFragment.Callback { public static final String THREAD_PAGE_COUNT_ARGUMENT = "thread_page_count"; public static final String POST_PAGE_ARGUMENT = "post_page"; public static final int CREATE_POST_REQUEST_CODE = 101; private static final String THREAD_ARGUMENT = "thread"; private static final String PAGE_CONTAINER_ARGUMENT = "page_container"; private static final String FORUM_HIERARCHY_ARGUMENT = "hierarchy"; private final ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager .OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { final int page = position + 1; mTopBar.setText("Page " + page); updatePagingButtonVisibility(position); mQuickReturnHelper.setPosition(position); mQuickReturnHelper.showTopBar(); getCurrentFragment().finishActionMode(); } @Override public void onPageScrollStateChanged(int state) { } }; private final EventHandler mEventHandler = new EventHandler(); private ViewPager mViewPager; private QuickReturnHelper mQuickReturnHelper; private RecyclerView mPageRecyclerView; private PostFragmentAdapter mAdapter; private int mTotalPages; private AugmentedUnifiedThread mUnifiedThread; private ThreadClient mThreadClient; private List<String> mHierarchy; private HierarchySpinnerAdapter mSpinnerAdapter; private ResponsePostContainer mContainerArgument; private Callback mCallback; private int mTargetHeight; private PostPageAdapter mPageAdapter; private TextView mTopBar; private View mFirst; private View mLast; public static PostPagerFragment getInstance(final AugmentedUnifiedThread unifiedThread, final ResponsePostContainer container, final int pageCount, final ArrayList<String> hierarchy) { final Bundle bundle = new Bundle(); bundle.putParcelable(THREAD_ARGUMENT, unifiedThread); bundle.putParcelable(PAGE_CONTAINER_ARGUMENT, container); bundle.putInt(THREAD_PAGE_COUNT_ARGUMENT, pageCount); bundle.putStringArrayList(FORUM_HIERARCHY_ARGUMENT, hierarchy); final PostPagerFragment postPagerFragment = new PostPagerFragment(); postPagerFragment.setArguments(bundle); return postPagerFragment; } public void collapse(final View view) { final Animation animation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { if (interpolatedTime == 1) { view.getLayoutParams().height = 0; view.setLayoutParams(view.getLayoutParams()); view.setVisibility(View.GONE); } else { view.getLayoutParams().height = mTargetHeight - (int) (mTargetHeight * interpolatedTime); view.setLayoutParams(view.getLayoutParams()); } } @Override public boolean willChangeBounds() { return true; } }; animation.setDuration(100); view.startAnimation(animation); } public void expand(final View view) { view.getLayoutParams().height = 0; view.setVisibility(View.VISIBLE); final Animation animation = new Animation() { @Override protected void applyTransformation(final float interpolatedTime, final Transformation transformation) { view.getLayoutParams().height = interpolatedTime == 1 ? ViewGroup.LayoutParams.WRAP_CONTENT : (int) (mTargetHeight * interpolatedTime); view.setLayoutParams(view.getLayoutParams()); } @Override public boolean willChangeBounds() { return true; } }; animation.setDuration(200); view.startAnimation(animation); } @Override public void onAttach(final Activity activity) { super.onAttach(activity); mCallback = (Callback) activity; } @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); mThreadClient = RetrofitThreadClient.getClient(getActivity()); mUnifiedThread = getArguments().getParcelable(THREAD_ARGUMENT); mTotalPages = getArguments().getInt(THREAD_PAGE_COUNT_ARGUMENT, 0); mHierarchy = getArguments().getStringArrayList(FORUM_HIERARCHY_ARGUMENT); if (savedInstanceState == null) { mContainerArgument = getArguments().getParcelable(PAGE_CONTAINER_ARGUMENT); } mAdapter = new PostFragmentAdapter(getChildFragmentManager(), mUnifiedThread, mTotalPages, mContainerArgument); mSpinnerAdapter = new HierarchySpinnerAdapter(); mPageAdapter = new PostPageAdapter(getActivity(), mTotalPages, new PostPageClickListener()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.post_pager_fragment, container, false); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); setHasOptionsMenu(true); final View header = view.findViewById(R.id.pagination_bar); mPageRecyclerView = (RecyclerView) view.findViewById(R.id.page_list); mPageRecyclerView.setLayoutManager(new XDALinerLayoutManager(getActivity())); if (mTotalPages > 1) { mPageRecyclerView.setAdapter(mPageAdapter); ViewCompat.setOverScrollMode(mPageRecyclerView, ViewCompat.OVER_SCROLL_NEVER); mPageRecyclerView.post(new Runnable() { @Override public void run() { mTargetHeight = mPageRecyclerView.getMeasuredHeight(); mPageRecyclerView.getLayoutParams().height = 0; mPageRecyclerView.setLayoutParams(mPageRecyclerView.getLayoutParams()); mPageRecyclerView.setVisibility(View.GONE); } }); mTopBar = (TextView) header.findViewById(R.id.page_top_textview); mTopBar.setText("Page 1"); mTopBar.setOnClickListener(new TopBarClickListener()); setupPagingButtons(header); mQuickReturnHelper = new QuickReturnHelper(getActivity(), header, mCallback.getToolbar()); } else { header.setVisibility(View.GONE); mPageRecyclerView.setVisibility(View.GONE); } final ActionBar actionBar = UIUtils.getSupportActionBar(getActivity()); actionBar.setTitle(null); actionBar.setSubtitle(null); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); actionBar.setListNavigationCallbacks(mSpinnerAdapter, mSpinnerAdapter); actionBar.setSelectedNavigationItem(mSpinnerAdapter.getCount() - 1); final Drawable background = new ColorDrawable( getResources().getColor(R.color.colorPrimary)); actionBar.setBackgroundDrawable(background); mViewPager = (ViewPager) view.findViewById(R.id.post_pager_fragment_view_pager); mViewPager.setAdapter(mAdapter); mViewPager.setOnPageChangeListener(mOnPageChangeListener); if (mContainerArgument != null) { mViewPager.setCurrentItem(mContainerArgument.getCurrentPage() - 1); } final FloatingActionButton button = (FloatingActionButton) view .findViewById(R.id.post_pager_fragment_floating_reply_button); button.setOnClickListener(new CreatePostListener()); if (CompatUtils.hasLollipop()) { final Drawable drawable = getResources().getDrawable(R.drawable.fab_background); button.setBackground(drawable); } else { final int color = getResources().getColor(R.color.fab_color); button.setBackgroundColor(color); } mThreadClient.getBus().register(mEventHandler); } private void setupPagingButtons(final View header) { mFirst = header.findViewById(R.id.page_first); mFirst.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { mViewPager.setCurrentItem(0); } }); mLast = header.findViewById(R.id.page_last); mLast.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { mViewPager.setCurrentItem(mTotalPages - 1); } }); } private void updatePagingButtonVisibility(final int position) { mFirst.setVisibility(position == 0 ? View.INVISIBLE : View.VISIBLE); mLast.setVisibility(position == mTotalPages - 1 ? View.INVISIBLE : View.VISIBLE); } @Override public void onDestroyView() { super.onDestroyView(); final ActionBar actionBar = UIUtils.getSupportActionBar(getActivity()); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); if (mQuickReturnHelper != null) { mQuickReturnHelper.showToolbar(); } mThreadClient.getBus().unregister(mEventHandler); } // Keeping this around because we'll almost certainly need this in the future @SuppressWarnings("unused") public PostFragment getCurrentFragment() { return (PostFragment) mViewPager.getAdapter().instantiateItem(mViewPager, mViewPager.getCurrentItem()); } @Override public void quotePost(final AugmentedPost... posts) { final DialogFragment fragment = posts == null ? CreatePostFragment.createInstance(mUnifiedThread) : CreatePostFragment.createInstance(mUnifiedThread, posts); fragment.setTargetFragment(this, CREATE_POST_REQUEST_CODE); fragment.show(getFragmentManager(), "createPost"); } @Override public void switchToFragment(final ResponsePostContainer container) { mAdapter.setContainerArgument(container); mViewPager.setCurrentItem(container.getCurrentPage() - 1); if (getCurrentFragment().getView() != null) { getCurrentFragment().scrollToPosition(container); } } @Override public void setQuickReturnListener(final RecyclerView recyclerView, final int position) { if (mTotalPages != 1) { mQuickReturnHelper.setOnScrollListener(recyclerView, position); } } @Override public void postPaddingToQuickReturn(final View content) { final View header = getView().findViewById(R.id.pagination_bar); QuickReturnHelper.postPaddingToQuickReturn(header, content); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK && requestCode == CREATE_POST_REQUEST_CODE) { onNewPostCreated(); } } // Options menu @Override public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { inflater.inflate(R.menu.post_pager_fragment_ab, menu); } @Override public void onPrepareOptionsMenu(final Menu menu) { final boolean visible = AccountUtils.isAccountAvailable(getActivity()); final MenuItem item = menu.findItem(R.id.post_pager_fragment_subscribe_unsubscribe); item.setVisible(visible); if (visible) { item.setIcon(mUnifiedThread.isSubscribed() ? R.drawable.ic_star_light : R.drawable.ic_action_star_outline); } } @Override public boolean onOptionsItemSelected(final MenuItem item) { switch (item.getItemId()) { case R.id.post_pager_fragment_subscribe_unsubscribe: toggleThreadSubscription(); return true; } return false; } private void toggleThreadSubscription() { mThreadClient.toggleSubscribeAsync(mUnifiedThread); } private void onNewPostCreated() { if (mUnifiedThread.getTotalPosts() % 10 == 0) { // TODO - need to work out what we need to do in this scenario } else { mViewPager.setCurrentItem(mTotalPages - 1); getCurrentFragment().refreshPageAndScrollToBottom(); } } @Override public void onPageLoaded(final ResponseUnifiedThread thread) { if (getTargetFragment() != null) { final Intent intent = new Intent(); intent.putExtra("thread", thread); getTargetFragment() .onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent); } } public interface Callback { public Toolbar getToolbar(); public void login(final Runnable runnable); } private class CreatePostListener implements View.OnClickListener { @Override public void onClick(final View v) { if (AccountUtils.isAccountAvailable(getActivity())) { quoteOrReply(); } else { mCallback.login(new Runnable() { @Override public void run() { quoteOrReply(); } }); } } private void quoteOrReply() { final PostFragment postFragment = getCurrentFragment(); if (postFragment.isActionModeStarted()) { quotePost(postFragment.getCheckedItems()); postFragment.finishActionMode(); } else { quotePost(); } } } private class HierarchySpinnerAdapter extends BaseAdapter implements ActionBar.OnNavigationListener { private final LayoutInflater mLayouInflater; public HierarchySpinnerAdapter() { mLayouInflater = LayoutInflater.from(getActivity()); } @Override public int getCount() { return mHierarchy.size(); } @Override public String getItem(int position) { return mHierarchy.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { convertView = convertView == null ? mLayouInflater.inflate(R.layout .hierarchy_spinner_item, parent, false) : convertView; final TextView title = (TextView) convertView .findViewById(R.id.hierarchy_spinner_item_name); final String text = getItem(position); final CharSequence formatted = Html.fromHtml(text); title.setText(formatted); return convertView; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { return getView(position, convertView, parent); } @Override public boolean onNavigationItemSelected(int itemPosition, long itemId) { getFragmentManager().popBackStack(getItem(itemPosition), 0); return true; } } private class EventHandler { @Subscribe public void onThreadSubscriptionToggled(final ThreadSubscriptionChangedEvent event) { mUnifiedThread.setSubscribedFlag(event.isNowSubscribed); getActivity().supportInvalidateOptionsMenu(); if (event.isNowSubscribed) { Toast.makeText(getActivity(), R.string.thread_subscription_subscribed, Toast.LENGTH_LONG).show(); } else { Toast.makeText(getActivity(), R.string.thread_subscription_unsubscribed, Toast.LENGTH_LONG).show(); } } @Subscribe public void onThreadSubscriptionToggleFailed(final ThreadSubscriptionChangingFailedEvent event) { Toast.makeText(getActivity(), R.string.thread_subscription_toggle_failed, Toast.LENGTH_LONG).show(); } } private class PostPageClickListener implements View.OnClickListener { @Override public void onClick(final View view) { collapse(mPageRecyclerView); final int position = mPageRecyclerView.getChildPosition(view); mViewPager.setCurrentItem(position); } } private class TopBarClickListener implements View.OnClickListener { @Override public void onClick(final View v) { final int visibility = mPageRecyclerView.getVisibility(); if (visibility == View.VISIBLE) { collapse(mPageRecyclerView); } else { expand(mPageRecyclerView); } } } }