package cl.monsoon.s1next.view.fragment; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.text.TextUtils; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import com.google.common.base.Preconditions; import javax.inject.Inject; import cl.monsoon.s1next.App; import cl.monsoon.s1next.R; import cl.monsoon.s1next.data.User; import cl.monsoon.s1next.data.api.Api; import cl.monsoon.s1next.data.api.model.Thread; import cl.monsoon.s1next.data.api.model.ThreadLink; import cl.monsoon.s1next.data.api.model.collection.Posts; import cl.monsoon.s1next.data.event.QuoteEvent; import cl.monsoon.s1next.util.ClipboardUtil; import cl.monsoon.s1next.util.IntentUtil; import cl.monsoon.s1next.util.MathUtil; import cl.monsoon.s1next.util.RxJavaUtil; import cl.monsoon.s1next.util.StringUtil; import cl.monsoon.s1next.view.activity.ReplyActivity; import cl.monsoon.s1next.view.dialog.LoginPromptDialogFragment; import cl.monsoon.s1next.view.dialog.ThreadAttachmentDialogFragment; import cl.monsoon.s1next.view.dialog.ThreadFavouritesAddDialogFragment; import cl.monsoon.s1next.view.internal.CoordinatorLayoutAnchorDelegate; import cl.monsoon.s1next.widget.EventBus; import rx.Subscription; /** * A Fragment includes {@link android.support.v4.view.ViewPager} * to represent each page of post lists. */ public final class PostListFragment extends BaseViewPagerFragment implements PostListPagerFragment.PagerCallback, View.OnClickListener { public static final String TAG = PostListFragment.class.getName(); private static final String ARG_THREAD = "thread"; private static final String ARG_SHOULD_GO_TO_LAST_PAGE = "should_go_to_last_page"; /** * ARG_JUMP_PAGE takes precedence over {@link #ARG_SHOULD_GO_TO_LAST_PAGE}. */ private static final String ARG_JUMP_PAGE = "jump_page"; private static final String ARG_QUOTE_POST_ID = "quote_post_id"; @Inject EventBus mEventBus; @Inject User mUser; private String mThreadId; @Nullable private String mThreadTitle; private Posts.ThreadAttachment mThreadAttachment; private MenuItem mMenuThreadAttachment; private Subscription mSubscription; public static PostListFragment newInstance(Thread thread, boolean shouldGoToLastPage) { PostListFragment fragment = new PostListFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(ARG_THREAD, thread); bundle.putBoolean(ARG_SHOULD_GO_TO_LAST_PAGE, shouldGoToLastPage); fragment.setArguments(bundle); return fragment; } public static PostListFragment newInstance(ThreadLink threadLink) { Thread thread = new Thread(); thread.setId(threadLink.getThreadId()); PostListFragment fragment = new PostListFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(ARG_THREAD, thread); bundle.putInt(ARG_JUMP_PAGE, threadLink.getJumpPage()); if (threadLink.getQuotePostId().isPresent()) { bundle.putString(ARG_QUOTE_POST_ID, threadLink.getQuotePostId().get()); } fragment.setArguments(bundle); return fragment; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); App.getAppComponent(getContext()).inject(this); Bundle bundle = getArguments(); Thread thread = Preconditions.checkNotNull(bundle.getParcelable(ARG_THREAD)); // thread title is null if this thread comes from ThreadLink mThreadTitle = thread.getTitle(); mThreadId = thread.getId(); if (savedInstanceState == null) { final int jumpPage = bundle.getInt(ARG_JUMP_PAGE, 0); if (jumpPage != 0) { // we do not know the total page if we open this thread by URL // so we set the jump page to total page setTotalPages(jumpPage); setCurrentPage(jumpPage - 1); } else { // +1 for original post setTotalPageByPosts(thread.getReplies() + 1); if (bundle.getBoolean(ARG_SHOULD_GO_TO_LAST_PAGE, false)) { setCurrentPage(getTotalPages() - 1); } } } ((CoordinatorLayoutAnchorDelegate) getActivity()).setupFloatingActionButton( R.drawable.ic_insert_comment_white_24dp, this); } @Override public void onResume() { super.onResume(); mSubscription = mEventBus.get().subscribe(o -> { if (o instanceof QuoteEvent) { QuoteEvent quoteEvent = (QuoteEvent) o; startReplyActivity(quoteEvent.getQuotePostId(), quoteEvent.getQuotePostCount()); } }); } @Override public void onPause() { super.onPause(); RxJavaUtil.unsubscribeIfNotNull(mSubscription); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.fragment_post, menu); mMenuThreadAttachment = menu.findItem(R.id.menu_thread_attachment); if (mThreadAttachment == null) { mMenuThreadAttachment.setVisible(false); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_thread_attachment: ThreadAttachmentDialogFragment.newInstance(mThreadAttachment).show( getActivity().getSupportFragmentManager(), ThreadAttachmentDialogFragment.TAG); return true; case R.id.menu_favourites_add: if (!LoginPromptDialogFragment.showLoginPromptDialogIfNeeded(getActivity(), mUser)) { ThreadFavouritesAddDialogFragment.newInstance(mThreadId).show( getActivity().getSupportFragmentManager(), ThreadFavouritesAddDialogFragment.TAG); } return true; case R.id.menu_link: ClipboardUtil.copyText(getContext(), Api.getPostListUrlForBrowser(mThreadId, getCurrentPage())); ((CoordinatorLayoutAnchorDelegate) getActivity()).showShortSnackbar( R.string.message_thread_link_copy); return true; case R.id.menu_share: String value; String url = Api.getPostListUrlForBrowser(mThreadId, getCurrentPage()); if (TextUtils.isEmpty(mThreadTitle)) { value = url; } else { value = StringUtil.concatWithTwoSpaces(mThreadTitle, url); } Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_TEXT, value); intent.setType("text/plain"); startActivity(Intent.createChooser(intent, getString(R.string.menu_title_share))); return true; case R.id.menu_browser: IntentUtil.startViewIntentExcludeOurApp(getContext(), Uri.parse( Api.getPostListUrlForBrowser(mThreadId, getCurrentPage() + 1))); return true; default: return super.onOptionsItemSelected(item); } } @Override BaseFragmentStatePagerAdapter getPagerAdapter(FragmentManager fragmentManager) { return new PostListPagerAdapter(fragmentManager); } @Nullable @Override CharSequence getTitleWithoutPosition() { return mThreadTitle; } @Override public void setTotalPageByPosts(int threads) { setTotalPages(MathUtil.divide(threads, Api.POSTS_PER_PAGE)); } @Override public void setThreadTitle(CharSequence title) { Thread thread = Preconditions.checkNotNull(getArguments().getParcelable(ARG_THREAD)); thread.setTitle(title.toString()); mThreadTitle = thread.getTitle(); setTitleWithPosition(getCurrentPage()); } @Override public void setupThreadAttachment(Posts.ThreadAttachment threadAttachment) { this.mThreadAttachment = threadAttachment; // mMenuThreadAttachment = null when configuration changes (like orientation changes) // but we don't need to care about the visibility of mMenuThreadAttachment // because mThreadAttachment != null and we won't invoke // mMenuThreadAttachment.setVisible(false) during onCreateOptionsMenu(Menu) if (mMenuThreadAttachment != null) { mMenuThreadAttachment.setVisible(true); } } @Override public void onClick(View v) { startReplyActivity(null, null); } private void startReplyActivity(@Nullable String quotePostId, @Nullable String quotePostCount) { if (LoginPromptDialogFragment.showLoginPromptDialogIfNeeded(getActivity(), mUser)) { return; } ReplyActivity.startReplyActivityForResultMessage(getActivity(), mThreadId, mThreadTitle, quotePostId, quotePostCount); } /** * Returns a Fragment corresponding to one of the pages of posts. */ private class PostListPagerAdapter extends BaseFragmentStatePagerAdapter { private PostListPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { Bundle bundle = getArguments(); int jumpPage = bundle.getInt(ARG_JUMP_PAGE, -1); String quotePostId = bundle.getString(ARG_QUOTE_POST_ID); if (jumpPage == i + 1 && !TextUtils.isEmpty(quotePostId)) { // clear this arg string because we only need to tell PostListPagerFragment once bundle.putString(ARG_QUOTE_POST_ID, null); return PostListPagerFragment.newInstance(mThreadId, jumpPage, quotePostId); } else { return PostListPagerFragment.newInstance(mThreadId, i + 1); } } } }