package net.everythingandroid.smspopup.ui; import java.lang.ref.WeakReference; import net.everythingandroid.smspopup.BuildConfig; import net.everythingandroid.smspopup.R; import net.everythingandroid.smspopup.preferences.ButtonListPreference; import net.everythingandroid.smspopup.provider.SmsMmsMessage; import net.everythingandroid.smspopup.util.Log; import net.everythingandroid.smspopup.util.SmsPopupUtils; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.util.LruCache; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.FrameLayout.LayoutParams; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.QuickContactBadge; import android.widget.TextView; import android.widget.ViewFlipper; import android.widget.ViewSwitcher; public class SmsPopupFragment extends Fragment { private SmsMmsMessage message; private boolean messageViewed = false; private SmsPopupButtonsListener mButtonsListener; private TextView fromTv; private TextView timestampTv; private TextView messageTv; private ViewFlipper contentFlipper; private LinearLayout mainLayout; private int privacyMode = PRIVACY_MODE_OFF; private boolean showUnlockButton = false; private boolean showButtons = true; private QuickContactBadge contactBadge; private ViewSwitcher buttonViewSwitcher; public static final int PRIVACY_MODE_OFF = 0; public static final int PRIVACY_MODE_HIDE_MESSAGE = 1; public static final int PRIVACY_MODE_HIDE_ALL = 2; private static final String EXTRA_PRIVACY_MODE = "net.everythingandroid.smspopup.privacy_mode"; private static final String EXTRA_BUTTONS = "net.everythingandroid.smspopup.buttons"; private static final String EXTRA_UNLOCK_BUTTON = "net.everythingandroid.smspopup.unlock_button"; private static final String EXTRA_SHOW_BUTTONS = "net.everythingandroid.smspopup.show_buttons"; private static final int VIEW_SMS = 0; private static final int VIEW_MMS = 1; private static final int VIEW_PRIVACY_SMS = 2; private static final int VIEW_PRIVACY_MMS = VIEW_MMS; public static final int BUTTON_VIEW = 100; public static final int BUTTON_VIEW_MMS = 101; public static final int BUTTON_UNLOCK = 102; public static final int BUTTON_PRIVACY = 103; private static final int CONTACT_IMAGE_FADE_DURATION = 300; private static final int BUTTON_SWITCHER_MAIN_BUTTONS = 0; private static final int BUTTON_SWITCHER_UNLOCK_BUTTON = 1; private static final String EMPTY_MMS_SUBJECT = "no subject"; public static SmsPopupFragment newInstance(SmsMmsMessage newMessage, int[] buttons, int privacyMode, boolean showUnlockButton, boolean showButtons) { SmsPopupFragment newFragment = new SmsPopupFragment(); Bundle args = newMessage.toBundle(); args.putInt(EXTRA_PRIVACY_MODE, privacyMode); args.putIntArray(EXTRA_BUTTONS, buttons); args.putBoolean(EXTRA_UNLOCK_BUTTON, showUnlockButton); args.putBoolean(EXTRA_SHOW_BUTTONS, showButtons); newFragment.setArguments(args); return newFragment; } public static SmsPopupFragment newInstance(SmsMmsMessage newMessage, int[] buttons) { return newInstance(newMessage, buttons, PRIVACY_MODE_OFF, false, true); } public SmsPopupFragment() {}; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final Bundle args = getArguments(); privacyMode = args.getInt(EXTRA_PRIVACY_MODE); showUnlockButton = args.getBoolean(EXTRA_UNLOCK_BUTTON); showButtons = args.getBoolean(EXTRA_SHOW_BUTTONS); final int[] buttons = args.getIntArray(EXTRA_BUTTONS); message = new SmsMmsMessage(getActivity(), args); View v = inflater.inflate(R.layout.popup_message_fragment, container, false); // Find the main textviews and layouts fromTv = (TextView) v.findViewById(R.id.fromTextView); messageTv = (TextView) v.findViewById(R.id.messageTextView); timestampTv = (TextView) v.findViewById(R.id.timestampTextView); contentFlipper = (ViewFlipper) v.findViewById(R.id.contentFlipper); buttonViewSwitcher = (ViewSwitcher) v.findViewById(R.id.buttonViewSwitcher); mainLayout = (LinearLayout) v.findViewById(R.id.popupMessageMainlayout); // Find the QuickContactBadge view that will show the contact photo contactBadge = (QuickContactBadge) v.findViewById(R.id.contactBadge); final String[] buttonText = getResources().getStringArray(R.array.buttons_text); if (showButtons) { final Button button1 = (Button) v.findViewById(R.id.button1); final PopupButton button1Vals = new PopupButton(buttons[0], buttonText); button1.setOnClickListener(button1Vals); button1.setVisibility(button1Vals.buttonVisibility); button1.setText(button1Vals.buttonText); final Button button2 = (Button) v.findViewById(R.id.button2); final PopupButton button2Vals = new PopupButton(buttons[1], buttonText); button2.setOnClickListener(button2Vals); button2.setVisibility(button2Vals.buttonVisibility); button2.setText(button2Vals.buttonText); final Button button3 = (Button) v.findViewById(R.id.button3); final PopupButton button3Vals = new PopupButton(buttons[2], buttonText); button3.setOnClickListener(button3Vals); button3.setVisibility(button3Vals.buttonVisibility); button3.setText(button3Vals.buttonText); /* * This is really hacky. There are two types of reply buttons (quick reply and reply). * If the user has selected to show both the replies then the text on the buttons * should be different. If they only use one then the text can just be "Reply". */ int numReplyButtons = 0; if (button1Vals.isReplyButton) numReplyButtons++; if (button2Vals.isReplyButton) numReplyButtons++; if (button3Vals.isReplyButton) numReplyButtons++; if (numReplyButtons == 1) { if (button1Vals.isReplyButton) button1.setText(R.string.button_reply); if (button2Vals.isReplyButton) button2.setText(R.string.button_reply); if (button3Vals.isReplyButton) button3.setText(R.string.button_reply); } ((Button) v.findViewById(R.id.unlockButton)).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mButtonsListener.onButtonClicked(BUTTON_UNLOCK); } }); } if (message.isMms()) { // The ViewMMS button ((Button) v.findViewById(R.id.viewMmsButton)).setOnClickListener( new PopupButton(BUTTON_VIEW_MMS, buttonText)); final String mmsSubject = message.getMessageBody(); final TextView mmsSubjectTV = ((TextView) v.findViewById(R.id.mmsSubjectTextView)); if (mmsSubject != null && !"".equals(mmsSubject) && !EMPTY_MMS_SUBJECT.equals(mmsSubject)) { mmsSubjectTV.setText(message.getMessageBody()); } else { mmsSubjectTV.setVisibility(View.GONE); } } // The privacy view message button ((ImageButton) v.findViewById(R.id.viewButton)).setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { mButtonsListener.onButtonClicked(BUTTON_VIEW); } }); populateViews(); return v; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mButtonsListener = (SmsPopupButtonsListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement SmsPopupButtonsListener"); } } /* * Populate all the main SMS/MMS views with content from the actual SmsMmsMessage */ private void populateViews() { if (message.isSms()) { messageTv.setText(message.getMessageBody()); } // Set the from, message and header views fromTv.setText(message.getContactName()); timestampTv.setText(message.getFormattedTimestamp()); setPrivacy(privacyMode, true); refreshButtonViews(); } public void resizeLayout(int newWidth, int screenWidth) { LayoutParams params = (LayoutParams) mainLayout.getLayoutParams(); params.width = newWidth; mainLayout.setLayoutParams(params); } public void setShowUnlockButton(boolean show) { if (show != showUnlockButton) { showUnlockButton = show; refreshButtonViews(); } } private void refreshButtonViews() { if (!showButtons) { buttonViewSwitcher.setVisibility(View.GONE); } else { final int currentView = buttonViewSwitcher.getDisplayedChild(); if (showUnlockButton) { if (currentView != BUTTON_SWITCHER_UNLOCK_BUTTON) { // Show unlock button buttonViewSwitcher.setDisplayedChild(BUTTON_SWITCHER_UNLOCK_BUTTON); } } else { if (currentView != BUTTON_SWITCHER_MAIN_BUTTONS) { // Show main popup buttons buttonViewSwitcher.setDisplayedChild(BUTTON_SWITCHER_MAIN_BUTTONS); } } } } public void setPrivacy(int newMode) { setPrivacy(newMode, false); } private void setPrivacy(int newMode, boolean initial) { if ((newMode != privacyMode || initial) && message != null && contentFlipper != null) { final int viewPrivacy = message.isSms() ? VIEW_PRIVACY_SMS : VIEW_PRIVACY_MMS; final int viewPrivacyOff = message.isSms() ? VIEW_SMS : VIEW_MMS; final int currentView = contentFlipper.getDisplayedChild(); if (newMode == PRIVACY_MODE_OFF) { if (currentView != viewPrivacyOff) { contentFlipper.setDisplayedChild(viewPrivacyOff); } fromTv.setVisibility(View.VISIBLE); messageViewed = true; if (initial || privacyMode == PRIVACY_MODE_HIDE_ALL) { loadContactPhoto(); } } else if (newMode == PRIVACY_MODE_HIDE_MESSAGE) { if (currentView != viewPrivacy) { contentFlipper.setDisplayedChild(viewPrivacy); } fromTv.setVisibility(View.VISIBLE); loadContactPhoto(); } else if (newMode == PRIVACY_MODE_HIDE_ALL) { if (currentView != viewPrivacy) { contentFlipper.setDisplayedChild(viewPrivacy); } fromTv.setVisibility(View.GONE); } } privacyMode = newMode; } private void loadContactPhoto() { boolean cacheHit = false; if (mButtonsListener != null && message.getContactLookupUri() != null) { final LruCache<Uri, Bitmap> cache = mButtonsListener.getCache(); if (cache != null) { final Bitmap bitmap = cache.get(message.getContactLookupUri()); if (bitmap != null) { if (BuildConfig.DEBUG) Log.v("loadContactPhoto() - bitmap cache hit"); contactBadge.setImageBitmap(bitmap); cacheHit = true; } } } if (!cacheHit) { new FetchContactPhotoTask(contactBadge).execute(message.getContactLookupUri()); } contactBadge.setClickable(true); final Uri contactUri = message.getContactLookupUri(); if (contactUri != null) { contactBadge.assignContactUri(message.getContactLookupUri()); } else { contactBadge.assignContactFromPhone(message.getAddress(), false); } } /** * AsyncTask to fetch contact photo in background */ private class FetchContactPhotoTask extends AsyncTask<Uri, Integer, Bitmap> { private final WeakReference<QuickContactBadge> viewReference; public FetchContactPhotoTask(QuickContactBadge badge) { viewReference = new WeakReference<QuickContactBadge> (badge); } @Override protected Bitmap doInBackground(Uri... params) { if (isAdded()) { if (BuildConfig.DEBUG) Log.v("Loading contact photo in background..."); final Bitmap bitmap = SmsPopupUtils.getPersonPhoto(getActivity(), params[0]); if (mButtonsListener != null && bitmap != null) { final LruCache<Uri, Bitmap> cache = mButtonsListener.getCache(); if (cache != null) { cache.put(params[0], bitmap); } } return bitmap; } return null; } @Override protected void onPostExecute(Bitmap photo) { if (BuildConfig.DEBUG) Log.v("Done loading contact photo"); if (photo != null && viewReference != null) { final QuickContactBadge badge = viewReference.get(); if (badge != null && isAdded()) { TransitionDrawable mTd = new TransitionDrawable(new Drawable[] { getResources().getDrawable(R.drawable.ic_contact_picture), new BitmapDrawable(getResources(), photo) }); badge.setImageDrawable(mTd); mTd.setCrossFadeEnabled(false); mTd.startTransition(CONTACT_IMAGE_FADE_DURATION); } } } } private class PopupButton implements OnClickListener { final private int buttonId; public boolean isReplyButton; public String buttonText; public int buttonVisibility = View.VISIBLE; public PopupButton(int id, String[] buttonTextArray) { buttonId = id; isReplyButton = false; if (buttonId == ButtonListPreference.BUTTON_REPLY || buttonId == ButtonListPreference.BUTTON_QUICKREPLY || buttonId == ButtonListPreference.BUTTON_REPLY_BY_ADDRESS) { isReplyButton = true; } if (buttonId < buttonTextArray.length) { buttonText = buttonTextArray[buttonId]; } if (buttonId == ButtonListPreference.BUTTON_DISABLED) { // Disabled buttonVisibility = View.GONE; } } @Override public void onClick(View v) { mButtonsListener.onButtonClicked(buttonId); } } public static interface SmsPopupButtonsListener { abstract void onButtonClicked(int buttonType); abstract LruCache<Uri, Bitmap> getCache(); } }