package what.whatandroid.forums.thread; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; import what.whatandroid.R; import what.whatandroid.comments.WhatBBParser; /** * A dialog fragment where the user can enter their reply to * a post or message. Communicates with the activity to request * that drafts be saved or discarded or that the current * text should be posted to the site. */ public class ReplyDialogFragment extends DialogFragment implements View.OnClickListener { /** * Listener to receive the users composed message and decisions * about whether to save the draft, post it or discard it */ public interface ReplyDialogListener { /** * Called if we want to post the composed message * * @param message message text to send * @param subject optional subject */ public void post(String message, String subject); /** * Called if the user wants to save the draft of the message * * @param message message draft to save * @param subject optional subject draft to save */ public void saveDraft(String message, String subject); /** * Called if the user wants to discard any saved message * and subject drafts */ public void discard(); } public static final String DRAFT = "what.whatandroid.replydialogfragment.DRAFT", SUBJECT = "what.whatandroid.replydialogfragment.SUBJECT", PREVIEWING = "what.whatandroid.replydialogfragment.PREVIEWING"; /** * The input box for the user to enter their post */ private EditText postText, postSubject; /** * Preview rendering textview and parser to apply styling */ private TextView preview; private Button renderPreview; private WhatBBParser whatBBParser = new WhatBBParser(); /** * Track if we should save the draft since it's done automatically * in onPause but sometimes we wouldn't want to do it, eg. when * discarding or posting the draft */ private boolean saveDraft = true; /** * Listener to alert about changes made to the draft */ private ReplyDialogListener listener; /** * Create a new reply dialog fragment displaying the * user's previous draft to continue editing * * @param draft saved draft of a reply we're resuming editing */ public static ReplyDialogFragment newInstance(String draft){ ReplyDialogFragment f = new ReplyDialogFragment(); Bundle args = new Bundle(); args.putString(DRAFT, draft); f.setArguments(args); return f; } /** * Create a new reply dialog fragment displaying the * user's previous draft to continue editing * * @param draft saved draft of a message we're resuming editing * @param subject saved subject of a message we're resuming editing */ public static ReplyDialogFragment newInstance(String draft, String subject){ ReplyDialogFragment f = new ReplyDialogFragment(); Bundle args = new Bundle(); args.putString(DRAFT, draft); args.putString(SUBJECT, subject); f.setArguments(args); return f; } public ReplyDialogFragment(){ //Required empty ctor } @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setStyle(DialogFragment.STYLE_NORMAL, R.style.AppTheme); try { listener = (ReplyDialogListener)getTargetFragment(); } catch (ClassCastException e){ throw new ClassCastException(getTargetFragment().toString() + " must implement ReplyDialogListener"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ View view = inflater.inflate(R.layout.dialog_reply, container, false); postText = (EditText)view.findViewById(R.id.post_text); postSubject = (EditText)view.findViewById(R.id.subject); preview = (TextView)view.findViewById(R.id.post_preview); Button discard = (Button)view.findViewById(R.id.discard); discard.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_clear_24dp, 0); Button send = (Button)view.findViewById(R.id.send); send.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_send_24dp, 0); renderPreview = (Button)view.findViewById(R.id.render_preview); preview.setOnClickListener(this); discard.setOnClickListener(this); send.setOnClickListener(this); renderPreview.setOnClickListener(this); getDialog().setTitle("Compose Reply"); //If we're restoring from a saved state the edit text takes care of restoring the contents //Otherwise we can restore a previous draft to show if (savedInstanceState == null){ if (getArguments().getString(DRAFT) != null){ postText.append(getArguments().getString(DRAFT)); } if (getArguments().getString(SUBJECT) != null){ postSubject.append(getArguments().getString(SUBJECT)); postSubject.setVisibility(View.VISIBLE); } } if (savedInstanceState != null){ postText.setText(savedInstanceState.getString(DRAFT)); setPreviewState(savedInstanceState.getBoolean(PREVIEWING)); if (savedInstanceState.getString(SUBJECT) != null){ postSubject.append(getArguments().getString(SUBJECT)); postSubject.setVisibility(View.VISIBLE); } } return view; } @Override public void onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); outState.putBoolean(PREVIEWING, preview.isShown()); outState.putString(DRAFT, postText.getText().toString()); if (postSubject.isShown()){ outState.putString(SUBJECT, postSubject.getText().toString()); } } @Override public void onPause(){ super.onPause(); String draft = postText.getText().toString(); if (saveDraft && !draft.isEmpty()){ listener.saveDraft(draft, postSubject.getText().toString()); } } @Override public void onClick(View v){ switch (v.getId()){ //If we click the rendered preview we want to go back to editing //to mirror the site behavior case R.id.post_preview: setPreviewState(false); break; case R.id.discard: saveDraft = false; listener.discard(); getDialog().dismiss(); break; case R.id.send: postReply(); break; //We want to toggle the preview state here, eg. show preview if we aren't //and show the edit box if we are case R.id.render_preview: setPreviewState(preview.getVisibility() != View.VISIBLE); break; default: break; } } /** * Validate that a subject (if being shown) and body text have been entered * before sending a reply */ private void postReply(){ if (postSubject.isShown() && postSubject.getText().length() == 0){ Toast.makeText(getActivity(), "Please enter a subject", Toast.LENGTH_SHORT).show(); postSubject.requestFocus(); } else if (postText.getText().length() == 0){ Toast.makeText(getActivity(), "Please enter your message", Toast.LENGTH_SHORT).show(); //Make sure the edit box is showing and focus on it setPreviewState(false); postText.requestFocus(); } else { saveDraft = false; listener.post(postText.getText().toString(), postSubject.getText().toString()); getDialog().dismiss(); } } /** * Set the text box/preview state * * @param showPreview true if we want to show the preview, false to show * the edit box */ private void setPreviewState(boolean showPreview){ if (showPreview){ postText.setVisibility(View.GONE); preview.setVisibility(View.VISIBLE); preview.setText(whatBBParser.parsebb(postText.getText().toString())); renderPreview.setText("Edit"); } else { preview.setVisibility(View.GONE); postText.setVisibility(View.VISIBLE); renderPreview.setText("Preview"); } } }