package what.whatandroid.forums.thread; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.view.ViewPager; 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.Toast; import api.forum.thread.ForumThread; import api.forum.thread.Poll; import api.son.MySon; import api.soup.MySoup; import what.whatandroid.R; import what.whatandroid.callbacks.AddQuoteCallback; import what.whatandroid.callbacks.LoadingListener; import what.whatandroid.callbacks.OnLoggedInCallback; import what.whatandroid.callbacks.SetTitleCallback; import what.whatandroid.forums.ForumActivity; import what.whatandroid.forums.NumberPickerDialog; import what.whatandroid.forums.poll.PollDialog; /** * Displays a paged view of posts in a thread */ public class ThreadFragment extends Fragment implements OnLoggedInCallback, LoadingListener<ForumThread>, AddQuoteCallback, NumberPickerDialog.NumberPickerListener, ReplyDialogFragment.ReplyDialogListener { private static final String THREAD_NAME = "what.whatandroid.forums.THREAD_NAME", PAGES = "what.whatandroid.forums.PAGES", LOCKED = "what.whatandroid.forums.LOCKED"; private SetTitleCallback setTitle; private ThreadPagerAdapter pagerAdapter; private ViewPager viewPager; private int thread, pages = 0, postId = -1; private String threadName; private boolean subscribed = false, locked = false; private MenuItem viewPoll, toggleSubscription, reply; /** * We track the poll separately from the rest of the thread so we can update * it without having to reload the page */ private Poll poll; /** * The current draft of the reply we might be writing for this thread */ private String replyDraft = ""; /** * Create a new thread fragment showing the first page of the thread * * @param thread thread id to view */ public static ThreadFragment newInstance(int thread){ ThreadFragment f = new ThreadFragment(); Bundle args = new Bundle(); args.putInt(ForumActivity.THREAD_ID, thread); f.setArguments(args); return f; } /** * Create a new thread fragment showing the thread at some post * * @param thread thread id to view * @param post post to jump to */ public static ThreadFragment newInstance(int thread, int post){ ThreadFragment f = new ThreadFragment(); Bundle args = new Bundle(); args.putInt(ForumActivity.THREAD_ID, thread); args.putInt(ForumActivity.POST_ID, post); f.setArguments(args); return f; } public ThreadFragment(){ //Required empty ctor } @Override public void onAttach(Activity activity){ super.onAttach(activity); try { setTitle = (SetTitleCallback) activity; } catch (ClassCastException e){ throw new ClassCastException(activity.toString() + " must implement SetTitleCallback"); } } @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setHasOptionsMenu(true); thread = getArguments().getInt(ForumActivity.THREAD_ID); if (savedInstanceState != null){ pages = savedInstanceState.getInt(PAGES); threadName = savedInstanceState.getString(THREAD_NAME); replyDraft = savedInstanceState.getString(ReplyDialogFragment.DRAFT, ""); locked = savedInstanceState.getBoolean(LOCKED); if (savedInstanceState.containsKey(PollDialog.POLL)){ poll = (Poll) MySon.toObjectFromString(savedInstanceState.getString(PollDialog.POLL), Poll.class); } } else { postId = getArguments().getInt(ForumActivity.POST_ID, -1); } } @Override public void onResume(){ super.onResume(); if (threadName != null){ setTitle.setTitle(threadName); } updateMenus(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ View view = inflater.inflate(R.layout.fragment_view_pager_strip, container, false); viewPager = (ViewPager) view.findViewById(R.id.pager); pagerAdapter = new ThreadPagerAdapter(getChildFragmentManager(), pages, thread, postId); viewPager.setAdapter(pagerAdapter); pagerAdapter.setLoadingListener(this); if (MySoup.isLoggedIn()){ onLoggedIn(); } return view; } @Override public void onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); outState.putInt(PAGES, pages); outState.putString(ReplyDialogFragment.DRAFT, replyDraft); outState.putBoolean(LOCKED, locked); if (threadName != null){ outState.putString(THREAD_NAME, threadName); if (poll != null){ outState.putString(PollDialog.POLL, MySon.toJson(poll, Poll.class)); } } else { outState.putString(THREAD_NAME, "Thread"); } } @Override public void onLoggedIn(){ pagerAdapter.onLoggedIn(); } @Override public void onLoadingComplete(ForumThread data){ if (poll == null){ poll = data.getResponse().getPoll(); } threadName = data.getResponse().getThreadTitle(); pages = data.getPages(); setTitle.setTitle(threadName); subscribed = data.getResponse().isSubscribed(); locked = data.getResponse().isLocked(); updateMenus(); } private void updateMenus(){ if (viewPoll != null && toggleSubscription != null){ if (poll != null){ viewPoll.setVisible(true); } if (subscribed){ toggleSubscription.setIcon(R.drawable.ic_visibility_24dp); } else { toggleSubscription.setIcon(R.drawable.ic_visibility_off_24dp); } } if(reply != null) { if(locked){ reply.setVisible(false); // visible by default } } } /** * Update the cached poll for the thread */ public void updatePoll(int vote){ if (poll != null){ poll.applyVote(vote); } } @Override public void quote(String quote){ replyDraft += quote; showReplyDialog(); } @Override public void pickNumber(int number){ viewPager.setCurrentItem(number - 1); } @Override public void post(String message, String subject){ replyDraft = ""; new PostReplyTask().execute(message); } @Override public void saveDraft(String message, String subject){ replyDraft = message; } @Override public void discard(){ replyDraft = ""; } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ inflater.inflate(R.menu.forum_thread, menu); viewPoll = menu.findItem(R.id.action_view_poll); reply = menu.findItem(R.id.action_reply); toggleSubscription = menu.findItem(R.id.action_subscription); updateMenus(); } @Override public boolean onOptionsItemSelected(MenuItem item){ switch (item.getItemId()){ //Show the reply dialog so the user can write their post case R.id.action_reply: showReplyDialog(); return true; //Show the poll dialog to either vote or view results case R.id.action_view_poll: PollDialog pollDialog = PollDialog.newInstance(poll, thread); pollDialog.show(getFragmentManager(), "dialog"); return true; case R.id.action_subscription: new ToggleSubscriptionsTask().execute(); return true; case R.id.action_pick_page: NumberPickerDialog dialog = NumberPickerDialog.newInstance("Select Page", 1, pages, viewPager.getCurrentItem()+1); dialog.setTargetFragment(this, 0); dialog.show(getFragmentManager(), "dialog"); return true; case R.id.action_pick_last_page: viewPager.setCurrentItem(pages - 1); return true; case R.id.action_refresh: pagerAdapter.refresh(); return true; default: break; } return false; } /** * Display the compose reply dialog so the user can write their response */ private void showReplyDialog(){ FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager().findFragmentByTag("dialog"); if (prev != null){ ft.remove(prev); } ft.addToBackStack(null); ReplyDialogFragment reply = ReplyDialogFragment.newInstance(replyDraft); reply.setTargetFragment(this, 0); reply.show(ft, "dialog"); } /** * Async task to toggle the artist's notification status */ private class ToggleSubscriptionsTask extends AsyncTask<Void, Void, Boolean> { @Override protected Boolean doInBackground(Void... params){ if (subscribed){ return ForumThread.unsubscribe(thread); } return ForumThread.subscribe(thread); } @Override protected void onPreExecute(){ //Display action as successful while we load if (subscribed){ toggleSubscription.setIcon(R.drawable.ic_visibility_off_24dp); } else { toggleSubscription.setIcon(R.drawable.ic_visibility_24dp); } if (isAdded()){ getActivity().setProgressBarIndeterminate(true); getActivity().setProgressBarIndeterminateVisibility(true); } } @Override protected void onPostExecute(Boolean status){ if (isAdded()){ getActivity().setProgressBarIndeterminate(false); getActivity().setProgressBarIndeterminateVisibility(false); } if (!status){ if (subscribed){ Toast.makeText(getActivity(), "Could not remove notifications", Toast.LENGTH_LONG).show(); } else { Toast.makeText(getActivity(), "Could not enable notifications", Toast.LENGTH_LONG).show(); } } else { subscribed = !subscribed; } updateMenus(); } } private class PostReplyTask extends AsyncTask<String, Void, Boolean> { @Override protected Boolean doInBackground(String... params){ return ForumThread.postReply(thread, params[0], false); } @Override protected void onPostExecute(Boolean status){ if (!status){ Toast.makeText(getActivity(), "Could not post reply", Toast.LENGTH_LONG).show(); } else { pagerAdapter.getNewPosts(viewPager); } } } }