From 6f0d297e2d3a663446af0caa6e6afee47e036131 Mon Sep 17 00:00:00 2001 From: Maxime Biais Date: Thu, 12 Feb 2015 18:32:05 +0100 Subject: [PATCH] LegacyEditorFragment now lives in the editor subproject --- .../android/editor/LegacyEditorFragment.java | 1015 ++++++++++++++++- .../editor/legacy/EditLinkActivity.java | 76 ++ .../res/drawable-hdpi/media_movieclip.png | Bin 0 -> 4208 bytes .../res/drawable-xhdpi/media_movieclip.png | Bin 0 -> 4292 bytes .../res/drawable-xxhdpi/media_movieclip.png | Bin 0 -> 2240 bytes .../src/main/res/layout/alert_create_link.xml | 42 + .../main/res/layout/alert_image_options.xml | 81 ++ .../src/main/res/values/colors.xml | 1 + .../src/main/res/values/strings.xml | 25 + 9 files changed, 1238 insertions(+), 2 deletions(-) create mode 100644 WordPressEditor/src/main/java/org/wordpress/android/editor/legacy/EditLinkActivity.java create mode 100644 WordPressEditor/src/main/res/drawable-hdpi/media_movieclip.png create mode 100644 WordPressEditor/src/main/res/drawable-xhdpi/media_movieclip.png create mode 100644 WordPressEditor/src/main/res/drawable-xxhdpi/media_movieclip.png create mode 100644 WordPressEditor/src/main/res/layout/alert_create_link.xml create mode 100644 WordPressEditor/src/main/res/layout/alert_image_options.xml diff --git a/WordPressEditor/src/main/java/org/wordpress/android/editor/LegacyEditorFragment.java b/WordPressEditor/src/main/java/org/wordpress/android/editor/LegacyEditorFragment.java index 958c27d7441e..e75f405c87e7 100644 --- a/WordPressEditor/src/main/java/org/wordpress/android/editor/LegacyEditorFragment.java +++ b/WordPressEditor/src/main/java/org/wordpress/android/editor/LegacyEditorFragment.java @@ -1,7 +1,1018 @@ package org.wordpress.android.editor; -import android.app.Fragment; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Typeface; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.text.Editable; +import android.text.Layout; +import android.text.Selection; +import android.text.Spannable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.ArrowKeyMovementMethod; +import android.text.style.AlignmentSpan; +import android.text.style.QuoteSpan; +import android.text.style.StrikethroughSpan; +import android.text.style.StyleSpan; +import android.text.style.URLSpan; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.WindowManager; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.SeekBar; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.ToggleButton; -public class LegacyEditorFragment extends Fragment { +import com.android.volley.VolleyError; +import com.android.volley.toolbox.ImageLoader; +import org.wordpress.android.analytics.AnalyticsTracker; +import org.wordpress.android.analytics.AnalyticsTracker.Stat; +import org.wordpress.android.editor.legacy.EditLinkActivity; +import org.wordpress.android.editor.legacy.WPEditImageSpan; +import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.AppLog.T; +import org.wordpress.android.util.DisplayUtils; +import org.wordpress.android.util.ImageUtils; +import org.wordpress.android.util.MediaUtils; +import org.wordpress.android.util.helpers.MediaFile; +import org.wordpress.android.util.helpers.MediaGalleryImageSpan; +import org.wordpress.android.util.helpers.WPImageSpan; +import org.wordpress.android.util.helpers.WPUnderlineSpan; +import org.wordpress.android.util.widgets.WPEditText; + +public class LegacyEditorFragment extends EditorFragmentAbstract implements TextWatcher, + WPEditText.OnSelectionChangedListener, View.OnTouchListener { + public static final int ACTIVITY_REQUEST_CODE_CREATE_LINK = 4; + + private static final int MIN_THUMBNAIL_WIDTH = 200; + private static final int CONTENT_ANIMATION_DURATION = 250; + private static final String TAG_FORMAT_BAR_BUTTON_STRONG = "strong"; + private static final String TAG_FORMAT_BAR_BUTTON_EM = "em"; + private static final String TAG_FORMAT_BAR_BUTTON_UNDERLINE = "u"; + private static final String TAG_FORMAT_BAR_BUTTON_STRIKE = "strike"; + private static final String TAG_FORMAT_BAR_BUTTON_QUOTE = "blockquote"; + + private ActionBarActivity mActivity; + private View mRootView; + private WPEditText mContentEditText; + private Button mAddPictureButton; + private EditText mTitleEditText; + private ToggleButton mBoldToggleButton, mEmToggleButton, mBquoteToggleButton; + private ToggleButton mUnderlineToggleButton, mStrikeToggleButton; + private LinearLayout mFormatBar, mPostContentLinearLayout, mPostSettingsLinearLayout; + private boolean mIsBackspace; + private boolean mScrollDetected; + private boolean mIsLocalDraft; + + private int mStyleStart, mSelectionStart, mSelectionEnd, mFullViewBottom; + private int mLastPosition = -1; + private CharSequence mTitle; + private CharSequence mContent; + + private float mLastYPos = 0; + + @Override + public boolean onBackPressed() { + // leave full screen mode back button is pressed + if (getActivity().getActionBar() != null && !getActivity().getActionBar().isShowing()) { + setContentEditingModeVisible(false); + return true; + } + return false; + } + + @Override + public CharSequence getTitle() { + if (mTitleEditText != null) { + return mTitleEditText.getText().toString(); + } + return mTitle; + } + + @Override + public CharSequence getContent() { + if (mContentEditText != null) { + return mContentEditText.getText().toString(); + } + return mContent; + } + + @Override + public void setTitle(CharSequence text) { + mTitle = text; + if (mTitleEditText != null) { + mTitleEditText.setText(text); + } else { + // TODO + } + } + + @Override + public void setContent(CharSequence text) { + mContent = text; + if (mContentEditText != null) { + mContentEditText.setText(text); + } else { + // TODO + } + } + + public void setLocalDraft(boolean isLocalDraft) { + mIsLocalDraft = isLocalDraft; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + mActivity = (ActionBarActivity) getActivity(); + + final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_edit_post_content, container, false); + + mFormatBar = (LinearLayout) rootView.findViewById(R.id.format_bar); + mTitleEditText = (EditText) rootView.findViewById(R.id.post_title); + mTitleEditText.setText(mTitle); + mTitleEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + // Go to full screen editor when 'next' button is tapped on soft keyboard + if (actionId == EditorInfo.IME_ACTION_NEXT && isAdded() && mActivity.getSupportActionBar() != null && + mActivity.getSupportActionBar().isShowing()) { + setContentEditingModeVisible(true); + } + return false; + } + }); + mContentEditText = (WPEditText) rootView.findViewById(R.id.post_content); + mContentEditText.setText(mContent); + mPostContentLinearLayout = (LinearLayout) rootView.findViewById(R.id.post_content_wrapper); + mPostSettingsLinearLayout = (LinearLayout) rootView.findViewById(R.id.post_settings_wrapper); + Button postSettingsButton = (Button) rootView.findViewById(R.id.post_settings_button); + postSettingsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mEditorFragmentListener.onSettingsClicked(); + } + }); + mBoldToggleButton = (ToggleButton) rootView.findViewById(R.id.bold); + mEmToggleButton = (ToggleButton) rootView.findViewById(R.id.em); + mBquoteToggleButton = (ToggleButton) rootView.findViewById(R.id.bquote); + mUnderlineToggleButton = (ToggleButton) rootView.findViewById(R.id.underline); + mStrikeToggleButton = (ToggleButton) rootView.findViewById(R.id.strike); + mAddPictureButton = (Button) rootView.findViewById(R.id.addPictureButton); + Button linkButton = (Button) rootView.findViewById(R.id.link); + Button moreButton = (Button) rootView.findViewById(R.id.more); + + registerForContextMenu(mAddPictureButton); + mContentEditText.setOnSelectionChangedListener(this); + mContentEditText.setOnTouchListener(this); + mContentEditText.addTextChangedListener(this); + mContentEditText.setOnEditTextImeBackListener(new WPEditText.EditTextImeBackListener() { + @Override + public void onImeBack(WPEditText ctrl, String text) { + // Go back to regular editor if IME keyboard is dismissed + // Bottom comparison is there to ensure that the keyboard is actually showing + if (mRootView.getBottom() < mFullViewBottom && isAdded() && mActivity.getSupportActionBar() != null + && !mActivity.getSupportActionBar().isShowing()) { + setContentEditingModeVisible(false); + } + } + }); + mAddPictureButton.setOnClickListener(mFormatBarButtonClickListener); + mBoldToggleButton.setOnClickListener(mFormatBarButtonClickListener); + linkButton.setOnClickListener(mFormatBarButtonClickListener); + mEmToggleButton.setOnClickListener(mFormatBarButtonClickListener); + mUnderlineToggleButton.setOnClickListener(mFormatBarButtonClickListener); + mStrikeToggleButton.setOnClickListener(mFormatBarButtonClickListener); + mBquoteToggleButton.setOnClickListener(mFormatBarButtonClickListener); + moreButton.setOnClickListener(mFormatBarButtonClickListener); + mEditorFragmentListener.onEditorFragmentInitialized(); + return rootView; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mRootView = view; + mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener); + } + + private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { + public void onGlobalLayout() { + mRootView.getViewTreeObserver().removeGlobalOnLayoutListener(this); + mFullViewBottom = mRootView.getBottom(); + } + }; + + public void setContentEditingModeVisible(boolean isVisible) { + if (!isAdded()) { + return; + } + ActionBar actionBar = mActivity.getSupportActionBar(); + if (isVisible) { + Animation fadeAnimation = new AlphaAnimation(1, 0); + fadeAnimation.setDuration(CONTENT_ANIMATION_DURATION); + fadeAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + mTitleEditText.setVisibility(View.GONE); + } + + @Override + public void onAnimationEnd(Animation animation) { + mPostSettingsLinearLayout.setVisibility(View.GONE); + mFormatBar.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + + mPostContentLinearLayout.startAnimation(fadeAnimation); + if (actionBar != null) { + actionBar.hide(); + } + } else { + mTitleEditText.setVisibility(View.VISIBLE); + mFormatBar.setVisibility(View.GONE); + Animation fadeAnimation = new AlphaAnimation(0, 1); + fadeAnimation.setDuration(CONTENT_ANIMATION_DURATION); + fadeAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + mPostSettingsLinearLayout.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + mPostContentLinearLayout.startAnimation(fadeAnimation); + mActivity.invalidateOptionsMenu(); + if (actionBar != null) { + actionBar.show(); + } + } + } + + // TODO: call MediaPicker-Android instead (see EditPostActivity.onAddMediaButtonClicked) + /* + @Override + public boolean onContextItemSelected(MenuItem item) { + switch (item.getItemId()) { + case 0: + launchPictureLibrary(); + return true; + case 1: + launchCamera(); + return true; + case 2: + launchVideoLibrary(); + return true; + case 3: + launchVideoCamera(); + return true; + case 4: + startMediaGalleryActivity(null); + return true; + case 5: + startMediaGalleryAddActivity(); + return true; + } + return false; + } + */ + + public boolean hasEmptyContentFields() { + return TextUtils.isEmpty(mTitleEditText.getText()) && TextUtils.isEmpty(mContentEditText.getText()); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mFullViewBottom = mRootView.getBottom(); + } + + public void createLinkFromSelection(String linkURL, String linkText) { + try { + if (linkURL != null && !linkURL.equals("http://") && !linkURL.equals("")) { + if (mSelectionStart > mSelectionEnd) { + int temp = mSelectionEnd; + mSelectionEnd = mSelectionStart; + mSelectionStart = temp; + } + Editable str = mContentEditText.getText(); + if (str == null) + return; + if (mIsLocalDraft) { + if (linkText == null) { + if (mSelectionStart < mSelectionEnd) { + str.delete(mSelectionStart, mSelectionEnd); + } + str.insert(mSelectionStart, linkURL); + str.setSpan(new URLSpan(linkURL), mSelectionStart, mSelectionStart + linkURL.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + mContentEditText.setSelection(mSelectionStart + linkURL.length()); + } else { + if (mSelectionStart < mSelectionEnd) { + str.delete(mSelectionStart, mSelectionEnd); + } + str.insert(mSelectionStart, linkText); + str.setSpan(new URLSpan(linkURL), mSelectionStart, mSelectionStart + linkText.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + mContentEditText.setSelection(mSelectionStart + linkText.length()); + } + } else { + if (linkText == null) { + if (mSelectionStart < mSelectionEnd) + str.delete(mSelectionStart, mSelectionEnd); + String urlHTML = "" + linkURL + ""; + str.insert(mSelectionStart, urlHTML); + mContentEditText.setSelection(mSelectionStart + urlHTML.length()); + } else { + if (mSelectionStart < mSelectionEnd) { + str.delete(mSelectionStart, mSelectionEnd); + } + String urlHTML = "" + linkText + ""; + str.insert(mSelectionStart, urlHTML); + mContentEditText.setSelection(mSelectionStart + urlHTML.length()); + } + } + } + } catch (RuntimeException e) { + AppLog.e(T.POSTS, e); + } + } + + /** + * Formatting bar + */ + private View.OnClickListener mFormatBarButtonClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.bold) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_BOLD); + onFormatButtonClick(mBoldToggleButton, TAG_FORMAT_BAR_BUTTON_STRONG); + } else if (id == R.id.em) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_ITALIC); + onFormatButtonClick(mEmToggleButton, TAG_FORMAT_BAR_BUTTON_EM); + } else if (id == R.id.underline) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_UNDERLINE); + onFormatButtonClick(mUnderlineToggleButton, TAG_FORMAT_BAR_BUTTON_UNDERLINE); + } else if (id == R.id.strike) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_STRIKETHROUGH); + onFormatButtonClick(mStrikeToggleButton, TAG_FORMAT_BAR_BUTTON_STRIKE); + } else if (id == R.id.bquote) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_BLOCKQUOTE); + onFormatButtonClick(mBquoteToggleButton, TAG_FORMAT_BAR_BUTTON_QUOTE); + } else if (id == R.id.more) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_MORE); + mSelectionEnd = mContentEditText.getSelectionEnd(); + Editable str = mContentEditText.getText(); + if (str != null) { + if (mSelectionEnd > str.length()) + mSelectionEnd = str.length(); + str.insert(mSelectionEnd, "\n\n"); + } + } else if (id == R.id.link) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_LINK); + mSelectionStart = mContentEditText.getSelectionStart(); + mStyleStart = mSelectionStart; + mSelectionEnd = mContentEditText.getSelectionEnd(); + if (mSelectionStart > mSelectionEnd) { + int temp = mSelectionEnd; + mSelectionEnd = mSelectionStart; + mSelectionStart = temp; + } + Intent i = new Intent(getActivity(), EditLinkActivity.class); + if (mSelectionEnd > mSelectionStart) { + if (mContentEditText.getText() != null) { + String selectedText = mContentEditText.getText().subSequence(mSelectionStart, mSelectionEnd).toString(); + i.putExtra("selectedText", selectedText); + } + } + startActivityForResult(i, ACTIVITY_REQUEST_CODE_CREATE_LINK); + } else if (id == R.id.addPictureButton) { + AnalyticsTracker.track(Stat.EDITOR_TAPPED_IMAGE); + mAddPictureButton.performLongClick(); + } + } + }; + + private WPEditImageSpan createWPEditImageSpanLocal(Context context, MediaFile mediaFile) { + Uri imageUri = Uri.parse(mediaFile.getFilePath()); + Bitmap thumbnailBitmap; + if (imageUri.toString().contains("video") && !MediaUtils.isInMediaStore(imageUri)) { + thumbnailBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.media_movieclip); + } else { + thumbnailBitmap = ImageUtils.getWPImageSpanThumbnailFromFilePath(context, imageUri.getEncodedPath(), + ImageUtils.getMaximumThumbnailWidthForEditor(context)); + if (thumbnailBitmap == null) { + return null; + } + } + WPEditImageSpan imageSpan = new WPEditImageSpan(context, thumbnailBitmap, imageUri); + mediaFile.setWidth(MediaUtils.getMinimumImageWidth(context, imageUri, mBlogSettingMaxImageWidth)); + return imageSpan; + } + + private WPEditImageSpan createWPEditImageSpanRemote(Context context, MediaFile mediaFile) { + int drawable = mediaFile.isVideo() ? R.drawable.media_movieclip : R.drawable.dashicon_format_image_big_grey; + Uri uri = Uri.parse(mediaFile.getFileURL()); + WPEditImageSpan imageSpan = new WPEditImageSpan(context, drawable, uri); + imageSpan.setMediaFile(mediaFile); + return imageSpan; + } + + private WPEditImageSpan createWPEditImageSpan(Context context, MediaFile mediaFile) { + if (mediaFile.getFileURL() == null) { + return createWPEditImageSpanLocal(context, mediaFile); + } else { + return createWPEditImageSpanRemote(context, mediaFile); + } + } + + /** + * Applies formatting to selected text, or marks the entry for a new text style + * at the current cursor position + * @param toggleButton button from formatting bar + * @param tag HTML tag name for text style + */ + private void onFormatButtonClick(ToggleButton toggleButton, String tag) { + Spannable s = mContentEditText.getText(); + if (s == null) + return; + int selectionStart = mContentEditText.getSelectionStart(); + mStyleStart = selectionStart; + int selectionEnd = mContentEditText.getSelectionEnd(); + + if (selectionStart > selectionEnd) { + int temp = selectionEnd; + selectionEnd = selectionStart; + selectionStart = temp; + } + + Class styleClass = null; + if (tag.equals(TAG_FORMAT_BAR_BUTTON_STRONG) || tag.equals(TAG_FORMAT_BAR_BUTTON_EM)) + styleClass = StyleSpan.class; + else if (tag.equals(TAG_FORMAT_BAR_BUTTON_UNDERLINE)) + styleClass = WPUnderlineSpan.class; + else if (tag.equals(TAG_FORMAT_BAR_BUTTON_STRIKE)) + styleClass = StrikethroughSpan.class; + else if (tag.equals(TAG_FORMAT_BAR_BUTTON_QUOTE)) + styleClass = QuoteSpan.class; + + if (styleClass == null) + return; + + Object[] allSpans = s.getSpans(selectionStart, selectionEnd, styleClass); + boolean textIsSelected = selectionEnd > selectionStart; + if (mIsLocalDraft) { + // Local drafts can use the rich text editor. Yay! + boolean shouldAddSpan = true; + for (Object span : allSpans) { + if (span instanceof StyleSpan) { + StyleSpan styleSpan = (StyleSpan)span; + if ((styleSpan.getStyle() == Typeface.BOLD && !tag.equals(TAG_FORMAT_BAR_BUTTON_STRONG)) + || (styleSpan.getStyle() == Typeface.ITALIC && !tag.equals(TAG_FORMAT_BAR_BUTTON_EM))) { + continue; + } + } + if (!toggleButton.isChecked() && textIsSelected) { + // If span exists and text is selected, remove the span + s.removeSpan(span); + shouldAddSpan = false; + break; + } else if (!toggleButton.isChecked()) { + // Remove span at cursor point if button isn't checked + Object[] spans = s.getSpans(mStyleStart - 1, mStyleStart, styleClass); + for (Object removeSpan : spans) { + selectionStart = s.getSpanStart(removeSpan); + selectionEnd = s.getSpanEnd(removeSpan); + s.removeSpan(removeSpan); + } + } + } + + if (shouldAddSpan) { + if (tag.equals(TAG_FORMAT_BAR_BUTTON_STRONG)) { + s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (tag.equals(TAG_FORMAT_BAR_BUTTON_EM)) { + s.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + try { + s.setSpan(styleClass.newInstance(), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } catch (java.lang.InstantiationException e) { + AppLog.e(T.POSTS, e); + } catch (IllegalAccessException e) { + AppLog.e(T.POSTS, e); + } + } + } + } else { + // Add HTML tags when editing an existing post + String startTag = "<" + tag + ">"; + String endTag = ""; + Editable content = mContentEditText.getText(); + if (textIsSelected) { + content.insert(selectionStart, startTag); + content.insert(selectionEnd + startTag.length(), endTag); + toggleButton.setChecked(false); + mContentEditText.setSelection(selectionEnd + startTag.length() + endTag.length()); + } else if (toggleButton.isChecked()) { + content.insert(selectionStart, startTag); + mContentEditText.setSelection(selectionEnd + startTag.length()); + } else if (!toggleButton.isChecked()) { + content.insert(selectionEnd, endTag); + mContentEditText.setSelection(selectionEnd + endTag.length()); + } + } + } + + /** + * Rich Text Editor + */ + public void showImageSettings(final View alertView, final EditText titleText, + final EditText caption, final EditText imageWidthText, + final CheckBox featuredCheckBox, final CheckBox featuredInPostCheckBox, + final int maxWidth, final Spinner alignmentSpinner, final WPImageSpan imageSpan) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(getString(R.string.image_settings)); + builder.setView(alertView); + builder.setPositiveButton(getString(android.R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + String title = (titleText.getText() != null) ? titleText.getText().toString() : ""; + MediaFile mediaFile = imageSpan.getMediaFile(); + if (mediaFile == null) { + return; + } + mediaFile.setTitle(title); + mediaFile.setHorizontalAlignment(alignmentSpinner.getSelectedItemPosition()); + mediaFile.setWidth(getEditTextIntegerClamped(imageWidthText, 10, maxWidth)); + String captionText = (caption.getText() != null) ? caption.getText().toString() : ""; + mediaFile.setCaption(captionText); + mediaFile.setFeatured(featuredCheckBox.isChecked()); + if (featuredCheckBox.isChecked()) { + // remove featured flag from all other images + Spannable contentSpannable = mContentEditText.getText(); + WPImageSpan[] imageSpans = + contentSpannable.getSpans(0, contentSpannable.length(), WPImageSpan.class); + if (imageSpans.length > 1) { + for (WPImageSpan postImageSpan : imageSpans) { + if (postImageSpan != imageSpan) { + MediaFile postMediaFile = postImageSpan.getMediaFile(); + postMediaFile.setFeatured(false); + postMediaFile.setFeaturedInPost(false); + // TODO: remove this + mEditorFragmentListener.saveMediaFile(postMediaFile); + } + } + } + } + mediaFile.setFeaturedInPost(featuredInPostCheckBox.isChecked()); + // TODO: remove this + mEditorFragmentListener.saveMediaFile(mediaFile); + } + }); + builder.setNegativeButton(getString(android.R.string.cancel), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + dialog.dismiss(); + } + }); + AlertDialog alertDialog = builder.create(); + alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); + alertDialog.show(); + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + float pos = event.getY(); + + if (event.getAction() == 0) + mLastYPos = pos; + + if (event.getAction() > 1) { + int scrollThreshold = DisplayUtils.dpToPx(getActivity(), 2); + if (((mLastYPos - pos) > scrollThreshold) || ((pos - mLastYPos) > scrollThreshold)) + mScrollDetected = true; + } + + mLastYPos = pos; + + if (event.getAction() == MotionEvent.ACTION_UP) { + if (isAdded() && mActivity.getSupportActionBar() != null && mActivity.getSupportActionBar().isShowing()) { + setContentEditingModeVisible(true); + return false; + } + } + + if (event.getAction() == MotionEvent.ACTION_UP && !mScrollDetected) { + Layout layout = ((TextView) v).getLayout(); + int x = (int) event.getX(); + int y = (int) event.getY(); + + x += v.getScrollX(); + y += v.getScrollY(); + if (layout != null) { + int line = layout.getLineForVertical(y); + int charPosition = layout.getOffsetForHorizontal(line, x); + + Spannable spannable = mContentEditText.getText(); + if (spannable == null) { + return false; + } + // check if image span was tapped + WPImageSpan[] imageSpans = spannable.getSpans(charPosition, charPosition, WPImageSpan.class); + + if (imageSpans.length != 0) { + final WPImageSpan imageSpan = imageSpans[0]; + MediaFile mediaFile = imageSpan.getMediaFile(); + if (mediaFile == null) + return false; + if (!mediaFile.isVideo()) { + LayoutInflater factory = LayoutInflater.from(getActivity()); + final View alertView = factory.inflate(R.layout.alert_image_options, null); + if (alertView == null) + return false; + final EditText imageWidthText = (EditText) alertView.findViewById(R.id.imageWidthText); + final EditText titleText = (EditText) alertView.findViewById(R.id.title); + final EditText caption = (EditText) alertView.findViewById(R.id.caption); + final CheckBox featuredCheckBox = (CheckBox) alertView.findViewById(R.id.featuredImage); + final CheckBox featuredInPostCheckBox = (CheckBox) alertView.findViewById(R.id.featuredInPost); + + // show featured image checkboxes if supported + if (mFeaturedImageSupported) { + featuredCheckBox.setVisibility(View.VISIBLE); + featuredInPostCheckBox.setVisibility(View.VISIBLE); + } + + featuredCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + featuredInPostCheckBox.setVisibility(View.VISIBLE); + } else { + featuredInPostCheckBox.setVisibility(View.GONE); + } + + } + }); + + final SeekBar seekBar = (SeekBar) alertView.findViewById(R.id.imageWidth); + final Spinner alignmentSpinner = (Spinner) alertView.findViewById(R.id.alignment_spinner); + ArrayAdapter adapter = + ArrayAdapter.createFromResource(getActivity(), R.array.alignment_array, + android.R.layout.simple_spinner_item); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + alignmentSpinner.setAdapter(adapter); + + imageWidthText.setText(String.valueOf(mediaFile.getWidth()) + "px"); + seekBar.setProgress(mediaFile.getWidth()); + titleText.setText(mediaFile.getTitle()); + caption.setText(mediaFile.getCaption()); + featuredCheckBox.setChecked(mediaFile.isFeatured()); + + if (mediaFile.isFeatured()) { + featuredInPostCheckBox.setVisibility(View.VISIBLE); + } else { + featuredInPostCheckBox.setVisibility(View.GONE); + } + + featuredInPostCheckBox.setChecked(mediaFile.isFeaturedInPost()); + + alignmentSpinner.setSelection(mediaFile.getHorizontalAlignment(), true); + + final int maxWidth = MediaUtils.getMinimumImageWidth(getActivity(), + imageSpan.getImageSource(), mBlogSettingMaxImageWidth); + seekBar.setMax(maxWidth / 10); + if (mediaFile.getWidth() != 0) { + seekBar.setProgress(mediaFile.getWidth() / 10); + } + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (progress == 0) { + progress = 1; + } + imageWidthText.setText(progress * 10 + "px"); + } + }); + + imageWidthText.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + imageWidthText.setText(""); + } + } + }); + + imageWidthText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + int width = getEditTextIntegerClamped(imageWidthText, 10, maxWidth); + seekBar.setProgress(width / 10); + imageWidthText.setSelection((String.valueOf(width).length())); + + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(imageWidthText.getWindowToken(), + InputMethodManager.RESULT_UNCHANGED_SHOWN); + + return true; + } + }); + + showImageSettings(alertView, titleText, caption, imageWidthText, featuredCheckBox, + featuredInPostCheckBox, maxWidth, alignmentSpinner, imageSpan); + mScrollDetected = false; + return true; + } + + } else { + mContentEditText.setMovementMethod(ArrowKeyMovementMethod.getInstance()); + int selectionStart = mContentEditText.getSelectionStart(); + if (selectionStart >= 0 && mContentEditText.getSelectionEnd() >= selectionStart) + mContentEditText.setSelection(selectionStart, mContentEditText.getSelectionEnd()); + } + + // get media gallery spans + MediaGalleryImageSpan[] gallerySpans = spannable.getSpans(charPosition, charPosition, MediaGalleryImageSpan.class); + if (gallerySpans.length > 0) { + final MediaGalleryImageSpan gallerySpan = gallerySpans[0]; + // TODO: send action to create media gallery + // startMediaGalleryActivity(gallerySpan.getMediaGallery()); + } + } + } else if (event.getAction() == 1) { + mScrollDetected = false; + } + return false; + } + + @Override + public void afterTextChanged(Editable s) { + int position = Selection.getSelectionStart(mContentEditText.getText()); + if ((mIsBackspace && position != 1) || mLastPosition == position || !mIsLocalDraft) + return; + + if (position < 0) { + position = 0; + } + mLastPosition = position; + if (position > 0) { + if (mStyleStart > position) { + mStyleStart = position - 1; + } + + boolean shouldBold = mBoldToggleButton.isChecked(); + boolean shouldEm = mEmToggleButton.isChecked(); + boolean shouldUnderline = mUnderlineToggleButton.isChecked(); + boolean shouldStrike = mStrikeToggleButton.isChecked(); + boolean shouldQuote = mBquoteToggleButton.isChecked(); + + Object[] allSpans = s.getSpans(mStyleStart, position, Object.class); + for (Object span : allSpans) { + if (span instanceof StyleSpan) { + StyleSpan styleSpan = (StyleSpan) span; + if (styleSpan.getStyle() == Typeface.BOLD) + shouldBold = false; + else if (styleSpan.getStyle() == Typeface.ITALIC) + shouldEm = false; + } else if (span instanceof WPUnderlineSpan) { + shouldUnderline = false; + } else if (span instanceof StrikethroughSpan) { + shouldStrike = false; + } else if (span instanceof QuoteSpan) { + shouldQuote = false; + } + } + + if (shouldBold) + s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), mStyleStart, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + if (shouldEm) + s.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), mStyleStart, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + if (shouldUnderline) + s.setSpan(new WPUnderlineSpan(), mStyleStart, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + if (shouldStrike) + s.setSpan(new StrikethroughSpan(), mStyleStart, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + if (shouldQuote) + s.setSpan(new QuoteSpan(), mStyleStart, position, Spannable.SPAN_INCLUSIVE_INCLUSIVE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + mIsBackspace = (count - after == 1) || (s.length() == 0); + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void onSelectionChanged() { + if (!mIsLocalDraft) { + return; + } + + final Spannable s = mContentEditText.getText(); + if (s == null) + return; + // set toggle buttons if cursor is inside of a matching span + mStyleStart = mContentEditText.getSelectionStart(); + Object[] spans = s.getSpans(mContentEditText.getSelectionStart(), mContentEditText.getSelectionStart(), Object.class); + + mBoldToggleButton.setChecked(false); + mEmToggleButton.setChecked(false); + mBquoteToggleButton.setChecked(false); + mUnderlineToggleButton.setChecked(false); + mStrikeToggleButton.setChecked(false); + for (Object span : spans) { + if (span instanceof StyleSpan) { + StyleSpan ss = (StyleSpan) span; + if (ss.getStyle() == android.graphics.Typeface.BOLD) { + mBoldToggleButton.setChecked(true); + } + if (ss.getStyle() == android.graphics.Typeface.ITALIC) { + mEmToggleButton.setChecked(true); + } + } + if (span instanceof QuoteSpan) { + mBquoteToggleButton.setChecked(true); + } + if (span instanceof WPUnderlineSpan) { + mUnderlineToggleButton.setChecked(true); + } + if (span instanceof StrikethroughSpan) { + mStrikeToggleButton.setChecked(true); + } + } + } + + private int getEditTextIntegerClamped(EditText editText, int min, int max) { + int width = 10; + try { + if (editText.getText() != null) + width = Integer.parseInt(editText.getText().toString().replace("px", "")); + } catch (NumberFormatException e) { + AppLog.e(T.POSTS, e); + } + width = Math.min(max, Math.max(width, min)); + return width; + } + + private void loadWPImageSpanThumbnail(MediaFile mediaFile, String imageURL, ImageLoader imageLoader) { + if (mediaFile == null || imageURL == null) { + return; + } + final String mediaId = mediaFile.getMediaId(); + if (mediaId == null) { + return; + } + + final int maxThumbWidth = ImageUtils.getMaximumThumbnailWidthForEditor(getActivity()); + + imageLoader.get(imageURL, new ImageLoader.ImageListener() { + @Override + public void onErrorResponse(VolleyError arg0) { + } + + @Override + public void onResponse(ImageLoader.ImageContainer container, boolean arg1) { + Bitmap downloadedBitmap = container.getBitmap(); + if (downloadedBitmap == null) { + // no bitmap downloaded from the server. + return; + } + + if (downloadedBitmap.getWidth() < MIN_THUMBNAIL_WIDTH) { + // Picture is too small. Show the placeholder in this case. + return; + } + + Bitmap resizedBitmap; + // resize the downloaded bitmap + resizedBitmap = ImageUtils.getScaledBitmapAtLongestSide(downloadedBitmap, maxThumbWidth); + + if (resizedBitmap == null) { + return; + } + + final EditText editText = mContentEditText; + Editable s = editText.getText(); + if (s == null) { + return; + } + WPImageSpan[] spans = s.getSpans(0, s.length(), WPImageSpan.class); + if (spans.length != 0) { + for (WPImageSpan is : spans) { + MediaFile mediaFile = is.getMediaFile(); + if (mediaFile == null) { + continue; + } + if (mediaId.equals(mediaFile.getMediaId()) && !is.isNetworkImageLoaded()) { + // replace the existing span with a new one with the correct image, re-add + // it to the same position. + int spanStart = s.getSpanStart(is); + int spanEnd = s.getSpanEnd(is); + WPEditImageSpan imageSpan = new WPEditImageSpan(getActivity(), resizedBitmap, + is.getImageSource()); + imageSpan.setMediaFile(is.getMediaFile()); + imageSpan.setNetworkImageLoaded(true); + s.removeSpan(is); + s.setSpan(imageSpan, spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + break; + } + } + } + } + }, 0, 0); + } + + @Override + public void appendMediaFile(MediaFile mediaFile, String imageUrl, ImageLoader imageLoader) { + WPEditImageSpan imageSpan = createWPEditImageSpan(getActivity(), mediaFile); + + // Insert the WPImageSpan in the content field + int selectionStart = mContentEditText.getSelectionStart(); + int selectionEnd = mContentEditText.getSelectionEnd(); + + if (selectionStart > selectionEnd) { + int temp = selectionEnd; + selectionEnd = selectionStart; + selectionStart = temp; + } + + int line, column = 0; + if (mContentEditText.getLayout() != null) { + line = mContentEditText.getLayout().getLineForOffset(selectionStart); + column = mContentEditText.getSelectionStart() - mContentEditText.getLayout().getLineStart(line); + } + + Editable s = mContentEditText.getText(); + if (s == null) { + return; + } + + WPImageSpan[] imageSpans = s.getSpans(selectionStart, selectionEnd, WPImageSpan.class); + if (imageSpans.length != 0) { + // insert a few line breaks if the cursor is already on an image + s.insert(selectionEnd, "\n\n"); + selectionStart = selectionStart + 2; + selectionEnd = selectionEnd + 2; + } else if (column != 0) { + // insert one line break if the cursor is not at the first column + s.insert(selectionEnd, "\n"); + selectionStart = selectionStart + 1; + selectionEnd = selectionEnd + 1; + } + + s.insert(selectionStart, " "); + s.setSpan(imageSpan, selectionStart, selectionEnd + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + AlignmentSpan.Standard as = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER); + s.setSpan(as, selectionStart, selectionEnd + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + s.insert(selectionEnd + 1, "\n\n"); + + // Fetch and replace the WPImageSpan if it's a remote media + if (mediaFile.getFileURL() != null) { + loadWPImageSpanThumbnail(mediaFile, imageUrl, imageLoader); + } + } } diff --git a/WordPressEditor/src/main/java/org/wordpress/android/editor/legacy/EditLinkActivity.java b/WordPressEditor/src/main/java/org/wordpress/android/editor/legacy/EditLinkActivity.java new file mode 100644 index 000000000000..86cba3a1cd6e --- /dev/null +++ b/WordPressEditor/src/main/java/org/wordpress/android/editor/legacy/EditLinkActivity.java @@ -0,0 +1,76 @@ +package org.wordpress.android.editor.legacy; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; + +import org.wordpress.android.editor.R; + +public class EditLinkActivity extends ActionBarActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.alert_create_link); + + Bundle extras = getIntent().getExtras(); + if (extras != null) { + String selectedText = extras.getString("selectedText"); + if (selectedText != null) { + EditText linkTextET = (EditText) findViewById(R.id.linkText); + linkTextET.setText(selectedText); + } + } + + final Button cancelButton = (Button) findViewById(R.id.cancel); + final Button okButton = (Button) findViewById(R.id.ok); + + final EditText urlEditText = (EditText) findViewById(R.id.linkURL); + urlEditText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (urlEditText.getText().toString().equals("")) { + urlEditText.setText("http://"); + urlEditText.setSelection(7); + } + } + + }); + + okButton.setOnClickListener(new Button.OnClickListener() { + public void onClick(View v) { + EditText linkURLET = (EditText) findViewById(R.id.linkURL); + String linkURL = linkURLET.getText().toString(); + + EditText linkTextET = (EditText) findViewById(R.id.linkText); + String linkText = linkTextET.getText().toString(); + + Bundle bundle = new Bundle(); + bundle.putString("linkURL", linkURL); + if (!linkText.equals("")) { + bundle.putString("linkText", linkText); + } + + Intent mIntent = new Intent(); + mIntent.putExtras(bundle); + setResult(RESULT_OK, mIntent); + finish(); + + } + }); + + cancelButton.setOnClickListener(new Button.OnClickListener() { + public void onClick(View v) { + Intent mIntent = new Intent(); + setResult(RESULT_CANCELED, mIntent); + finish(); + } + }); + + // select end of url + urlEditText.performClick(); + } +} diff --git a/WordPressEditor/src/main/res/drawable-hdpi/media_movieclip.png b/WordPressEditor/src/main/res/drawable-hdpi/media_movieclip.png new file mode 100644 index 0000000000000000000000000000000000000000..bb49bcdc2cbe35b3bab737d8d1a23fc65551a5f8 GIT binary patch literal 4208 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 Y0qAJy+KkBSZcP9>nuZ#65c}8v1AH>}TmS$7 literal 0 HcmV?d00001 diff --git a/WordPressEditor/src/main/res/drawable-xxhdpi/media_movieclip.png b/WordPressEditor/src/main/res/drawable-xxhdpi/media_movieclip.png new file mode 100644 index 0000000000000000000000000000000000000000..90e9b768a96d19187d2ce43191681edaca769712 GIT binary patch literal 2240 zcmaJ@e_T`b8lDBafI>nwQ54pMOxdrq!C({6!8TbmK)@IVvR`Lx!gj{aU{eGWKcS__ zC-N>Z(emCd-XfZSpfS@)V8R4ZlOJ*o+y$-yBB7QjaKA%P>Z9$m?Y!qb@B6&Z`+T22 z&WEwl8(dwMxnM9DSAHZX4qPk1?`J10_)p&xTn8>obzGq?9+B(xVl9ke%Mb~S=c~kN za2za_ZOgm}hhQ)-`zjNJI-%elmK0Hu#r7JqL8SrR7);1IgGMY(hjn-foTgNV5=QIK z67Wh{C?PRWKow{rV1+VryB3b$9-ScFo-Sp|2JGtfECDK z(Sq=^9|D-BmC0Fg9Nz3Ka2HBY=yVzug`(H%$$B~&(WX%#CX;E$pwUR6f`o2U>%<0< z8eKVuz=2VzR;ke`5jEb9D3%~ux=;dO`eX%_<|(Wios|g)Mlpyr6o^c|h=Qap`OxlgH%+ zb7>I_dlWd=%R!`BDp;+X>yr!_e2z_GO)*sta|ZsTk1$8e{WuWseZ<2oN*I*iT#9Q_U*oM;Vs#axf@1`i+A z4jdW1NxwFd?eBRoy8PKaC1!wv9H1;KsAA``lVK zn8{CaN7oE&u@pCwvTF3sMxy$gf28;etAs1Y+13^Le*13xqPXA?g_CC0eC-&8>#yo< zDA@$kC+|}v{ve_6Xs=vMOzP1GZtxdQU7CbOoA$dHiPwK>cUx#AdY|e(_BwI8-%@hB z#0yjpNt>gmy|9x@lCIl2Quij=cDVKQm5_3$=!|RaVeTlDZc3E2-iCY0l*>oy-Y88T zZ$-$?KZ*zg-<0%&v4zkoN#(1=q=R+!-l_jnI7U&LPYz!Tc}(^d;;aKDQm6wAuWeeM zvRC2QvZD)!{_|&nv+-fgnL}qjgnWfno$l!I)OHtRUguKO@(O$U(>{?WD6h|yww9uH~uusG` z#gckgt-6{>Nvw|1U+gXXYR_Pf=!A1vn9nugK_=f3 zWZc1n83eo#JaDuSgnKZ5E?f;8nk+WR=Gt+js5IkLHe!uDkG|{u{TP3D)^9&#AY-|| zH70vxjCvP#UDb?~;w)h+(46z4oeIz4GSY$f#v}!z6p!9z^Co{V)vU4g-YJuhGR*0raN^y~Egj9%<~r7m~J-8`4# zy{U98I+5vJ?p0B}D`)-0$z6~By=JglepcaG;o38+@A+Ffe;28&hYHeLcK3&6Z%*r3 zUR~KZQ6!mKoH3f6Fv8FjDYKd)Af!&X&SSjV&gR*vv|KUvHCfg|gI<+qdJncftlgT| z@Z~Ar&WD-bZLJlT?wkl4cz+)MMc;Z7PpP6DLUsC5GUzu|s$5IQO}ZRrc=Cw1)^2yzT6g!ke7U_IC + + + + + + +