/*
* Tweetings - Twitter client for Android
*
* Copyright (C) 2012-2013 RBD Solutions Limited <apps@tweetings.net>
* Copyright (C) 2012 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.dwdesign.tweetings.activity;
import static android.os.Environment.getExternalStorageDirectory;
import static android.os.Environment.getExternalStorageState;
import static com.dwdesign.tweetings.util.Utils.getAccountColors;
import static com.dwdesign.tweetings.util.Utils.getAccountUsername;
import static com.dwdesign.tweetings.util.Utils.getActivatedAccountIds;
import static com.dwdesign.tweetings.util.Utils.getImagePathFromUri;
import static com.dwdesign.tweetings.util.Utils.getImageUploadStatus;
import static com.dwdesign.tweetings.util.Utils.getShareStatus;
import static com.dwdesign.tweetings.util.Utils.isNullOrEmpty;
import static com.dwdesign.tweetings.util.Utils.parseString;
import static com.dwdesign.tweetings.util.Utils.showErrorToast;
import static com.dwdesign.tweetings.util.Utils.openImage;
import static com.dwdesign.tweetings.util.Utils.getTwitterAccessToken;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;
import org.w3c.dom.Document;
//import com.aviary.android.feather.FeatherActivity;
//import com.aviary.android.feather.library.utils.StringUtils;
import com.dwdesign.actionbarcompat.ActionBar;
import com.dwdesign.menubar.MenuBar;
import com.dwdesign.menubar.MenuBar.OnMenuItemClickListener;
import com.dwdesign.popupmenu.PopupMenu;
import com.dwdesign.tweetings.R;
import com.dwdesign.tweetings.provider.TweetStore.Drafts;
import com.dwdesign.tweetings.util.ArrayUtils;
import com.dwdesign.tweetings.service.TweetingsService;
import com.dwdesign.tweetings.util.GetExternalCacheDirAccessor;
import com.dwdesign.tweetings.util.ServiceInterface;
import com.dwdesign.tweetings.util.EnvironmentAccessor;
import com.dwdesign.tweetings.view.ColorView;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.NavUtils;
import android.support.v4.app.FragmentActivity;
import android.text.Editable;
import android.text.InputType;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.text.method.ArrowKeyMovementMethod;
import android.text.style.ClickableSpan;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.twitter.Validator;
import com.dwdesign.tweetings.fragment.BaseDialogFragment;
import twitter4j.TwitterException;
import twitter4j.auth.AccessToken;
import twitter4j.auth.OAuthAuthorization;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.internal.http.HttpParameter;
import twitter4j.media.ImageUpload;
import twitter4j.media.ImageUploadFactory;
import twitter4j.media.MediaProvider;
public class ComposeActivity extends BaseActivity implements TextWatcher, LocationListener, OnMenuItemClickListener,
OnClickListener, OnLongClickListener, PopupMenu.OnMenuItemClickListener, OnEditorActionListener {
private static final String FAKE_IMAGE_LINK = "https://www.example.com/fake_image.jpg";
private static final String INTENT_KEY_CONTENT_MODIFIED = "content_modified";
private static final String INTENT_KEY_IS_NAVIGATE_UP = "is_navigate_up";
private static final String INTENT_KEY_IS_POSSIBLY_SENSITIVE = "is_possibly_sensitive";
private ImageUpload upload;
private Timer uploadTimer;
private ServiceInterface mService;
private LocationManager mLocationManager;
private SharedPreferences mPreferences;
private Location mRecentLocation;
private ContentResolver mResolver;
private final Validator mValidator = new Validator();
private AttachedImageThumbnailTask mAttachedImageThumbnailTask;
private ActionBar mActionBar;
private PopupMenu mPopupMenu;
private static final int THUMBNAIL_SIZE = 36;
private static final int ACTION_REQUEST_FEATHER = 100;
private ColorView mColorIndicator;
private EditText mEditText;
private TextView mTextCount;
private ImageView mImageThumbnailPreview;
private MenuBar mMenuBar;
private boolean mIsImageAttached, mIsPhotoAttached;
private long[] mAccountIds;
private String mText;
private Uri mImageUri;
private long mInReplyToStatusId = -1;
private String mInReplyToText = null;
private String mInReplyToScreenName, mInReplyToName;
private boolean mIsQuote, mUploadUseExtension, mIsBuffer, mContentModified, mIsPossiblySensitive;
private String mUploadProvider;
private ProgressDialog progressDialog;
private ArrayList<String> tweetParts;
private String mScheduleDate;
private DialogFragment mUnsavedTweetDialogFragment;
@Override
public void afterTextChanged(final Editable s) {
}
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
switch (requestCode) {
case REQUEST_SCHEDULE_DATE: {
if (resultCode == Activity.RESULT_OK) {
Bundle bundle = intent.getExtras();
mScheduleDate = bundle.getString(INTENT_KEY_SCHEDULE_DATE_TIME);
}
else {
if (mScheduleDate != null) {
mScheduleDate = null;
}
}
setMenu();
break;
}
case REQUEST_TAKE_PHOTO: {
if (resultCode == Activity.RESULT_OK) {
final File file = new File(mImageUri.getPath());
if (file.exists()) {
mIsImageAttached = false;
mIsPhotoAttached = true;
mImageThumbnailPreview.setVisibility(View.VISIBLE);
reloadAttachedImageThumbnail(file);
} else {
mIsPhotoAttached = false;
}
setMenu();
boolean isAutoUpload = mPreferences.getBoolean(PREFERENCE_KEY_AUTO_UPLOAD, false);
if (!isNullOrEmpty(mUploadProvider) && mIsPhotoAttached && isAutoUpload) {
postMedia();
}
}
break;
}
case REQUEST_PICK_IMAGE: {
if (resultCode == Activity.RESULT_OK) {
final Uri uri = intent.getData();
final File file = uri == null ? null : new File(getImagePathFromUri(this, uri));
if (file != null && file.exists()) {
mImageUri = Uri.fromFile(file);
mIsPhotoAttached = false;
mIsImageAttached = true;
mImageThumbnailPreview.setVisibility(View.VISIBLE);
reloadAttachedImageThumbnail(file);
} else {
mIsImageAttached = false;
}
setMenu();
boolean isAutoUpload = mPreferences.getBoolean(PREFERENCE_KEY_AUTO_UPLOAD, false);
if (!isNullOrEmpty(mUploadProvider) && mIsImageAttached && isAutoUpload) {
postMedia();
}
}
break;
}
case REQUEST_SELECT_ACCOUNT: {
if (resultCode == Activity.RESULT_OK) {
final Bundle bundle = intent.getExtras();
if (bundle == null) {
break;
}
final long[] account_ids = bundle.getLongArray(INTENT_KEY_IDS);
if (account_ids != null) {
mAccountIds = account_ids;
if (mInReplyToStatusId <= 0 && !Intent.ACTION_SEND.equals(getIntent().getAction())) {
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putString(PREFERENCE_KEY_COMPOSE_ACCOUNTS, ArrayUtils.toString(mAccountIds, ',', false));
editor.commit();
}
mColorIndicator.setColor(getAccountColors(this, account_ids));
}
}
break;
}
case REQUEST_EDIT_IMAGE: {
if (resultCode == Activity.RESULT_OK) {
final Uri uri = intent.getData();
final File file = uri == null ? null : new File(getImagePathFromUri(this, uri));
if (file != null && file.exists()) {
mImageUri = Uri.fromFile(file);
reloadAttachedImageThumbnail(file);
} else {
break;
}
setMenu();
}
break;
}
case REQUEST_EXTENSION_COMPOSE: {
if (resultCode == Activity.RESULT_OK) {
final Bundle extras = intent.getExtras();
if (extras == null) {
break;
}
final String text = extras.getString(INTENT_KEY_TEXT);
final String append = extras.getString(INTENT_KEY_APPEND_TEXT);
if (text != null) {
mEditText.setText(text);
mText = parseString(mEditText.getText());
} else if (append != null) {
mEditText.append(append);
mText = parseString(mEditText.getText());
}
}
break;
}
case ACTION_REQUEST_FEATHER:
if( resultCode == RESULT_OK ) {
final Uri uri = intent.getData();
final File file = uri == null ? null : new File(getImagePathFromUri(this, uri));
if (file != null && file.exists()) {
mImageUri = Uri.fromFile(file);
reloadAttachedImageThumbnail(file);
} else {
break;
}
setMenu();
}
break;
}
}
@Override
public void onBackPressed() {
final String text = mEditText != null ? parseString(mEditText.getText()) : null;
if (mContentModified && !isNullOrEmpty(text)) {
mUnsavedTweetDialogFragment = (DialogFragment) Fragment.instantiate(this,
UnsavedTweetDialogFragment.class.getName());
final Bundle args = new Bundle();
args.putBoolean(INTENT_KEY_IS_NAVIGATE_UP, false);
mUnsavedTweetDialogFragment.setArguments(args);
mUnsavedTweetDialogFragment.show(getSupportFragmentManager(), "unsaved_tweet");
return;
}
super.onBackPressed();
}
@Override
public void onClick(final View view) {
switch (view.getId()) {
case R.id.image_thumbnail_preview: {
if (mPopupMenu != null) {
mPopupMenu.dismiss();
}
mPopupMenu = PopupMenu.getInstance(this, view);
mPopupMenu.inflate(R.menu.action_attached_image);
mPopupMenu.setOnMenuItemClickListener(this);
final Menu menu = mPopupMenu.getMenu();
final MenuItem itemUpload = menu.findItem(MENU_UPLOAD);
if (!isNullOrEmpty(mUploadProvider) && itemUpload != null) {
itemUpload.setVisible(true);
}
mPopupMenu.show();
break;
}
}
}
@Override
public void onContentChanged() {
super.onContentChanged();
mColorIndicator = (ColorView) findViewById(R.id.account_colors);
mEditText = (EditText) findViewById(R.id.edit_text);
mTextCount = (TextView) findViewById(R.id.text_count);
mImageThumbnailPreview = (ImageView) findViewById(R.id.image_thumbnail_preview);
mMenuBar = (MenuBar) findViewById(R.id.menu_bar);
}
@Override
public void onCreate(final Bundle savedInstanceState) {
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mService = getTweetingsApplication().getServiceInterface();
mResolver = getContentResolver();
super.onCreate(savedInstanceState);
setContentView(R.layout.compose);
mActionBar = getSupportActionBar();
mActionBar.setDisplayHomeAsUpEnabled(true);
mUploadProvider = mPreferences.getString(PREFERENCE_KEY_IMAGE_UPLOADER, null);
final Bundle bundle = savedInstanceState != null ? savedInstanceState : getIntent().getExtras();
final long account_id = bundle != null ? bundle.getLong(INTENT_KEY_ACCOUNT_ID) : -1;
mAccountIds = bundle != null ? bundle.getLongArray(INTENT_KEY_IDS) : null;
mInReplyToStatusId = bundle != null ? bundle.getLong(INTENT_KEY_IN_REPLY_TO_ID) : -1;
mInReplyToScreenName = bundle != null ? bundle.getString(INTENT_KEY_IN_REPLY_TO_SCREEN_NAME) : null;
mInReplyToName = bundle != null ? bundle.getString(INTENT_KEY_IN_REPLY_TO_NAME) : null;
mInReplyToText = bundle != null ? bundle.getString(INTENT_KEY_IN_REPLY_TO_TWEET) : null;
mIsImageAttached = bundle != null ? bundle.getBoolean(INTENT_KEY_IS_IMAGE_ATTACHED) : false;
mIsPhotoAttached = bundle != null ? bundle.getBoolean(INTENT_KEY_IS_PHOTO_ATTACHED) : false;
mImageUri = bundle != null ? (Uri) bundle.getParcelable(INTENT_KEY_IMAGE_URI) : null;
final String[] mentions = bundle != null ? bundle.getStringArray(INTENT_KEY_MENTIONS) : null;
final String account_username = getAccountUsername(this, account_id);
int text_selection_start = -1;
mIsBuffer = bundle != null ? bundle.getBoolean(INTENT_KEY_IS_BUFFER, false): false;
if (mInReplyToStatusId > 0) {
if (bundle != null && bundle.getString(INTENT_KEY_TEXT) != null
&& (mentions == null || mentions.length < 1)) {
mText = bundle.getString(INTENT_KEY_TEXT);
} else if (mentions != null) {
final StringBuilder builder = new StringBuilder();
for (final String mention : mentions) {
if (mentions.length == 1 && mentions[0].equalsIgnoreCase(account_username)) {
builder.append('@' + account_username + ' ');
} else if (!mention.equalsIgnoreCase(account_username)) {
builder.append('@' + mention + ' ');
}
}
mText = builder.toString();
text_selection_start = mText.indexOf(' ') + 1;
}
mIsQuote = bundle != null ? bundle.getBoolean(INTENT_KEY_IS_QUOTE, false) : false;
final boolean display_name = mPreferences.getBoolean(PREFERENCE_KEY_DISPLAY_NAME, false);
final String name = display_name ? mInReplyToName : mInReplyToScreenName;
if (name != null) {
setTitle(getString(mIsQuote ? R.string.quote_user : R.string.reply_to, name));
}
if (mAccountIds == null || mAccountIds.length == 0) {
mAccountIds = new long[] { account_id };
}
TextView replyText = (TextView) findViewById(R.id.reply_text);
if (!isNullOrEmpty(mInReplyToText)) {
replyText.setVisibility(View.VISIBLE);
replyText.setText(mInReplyToText);
}
else {
replyText.setVisibility(View.GONE);
}
} else {
if (mentions != null) {
final StringBuilder builder = new StringBuilder();
for (final String mention : mentions) {
if (mentions.length == 1 && mentions[0].equalsIgnoreCase(account_username)) {
builder.append('@' + account_username + ' ');
} else if (!mention.equalsIgnoreCase(account_username)) {
builder.append('@' + mention + ' ');
}
}
mText = builder.toString();
}
if (mAccountIds == null || mAccountIds.length == 0) {
final long[] ids_in_prefs = ArrayUtils.fromString(
mPreferences.getString(PREFERENCE_KEY_COMPOSE_ACCOUNTS, null), ',');
final long[] activated_ids = getActivatedAccountIds(this);
final long[] intersection = ArrayUtils.intersection(ids_in_prefs, activated_ids);
mAccountIds = intersection.length > 0 ? intersection : activated_ids;
}
final String action = getIntent().getAction();
if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
setTitle(R.string.share);
final Bundle extras = getIntent().getExtras();
if (extras != null) {
if (mText == null) {
final CharSequence extra_subject = extras.getCharSequence(Intent.EXTRA_SUBJECT);
final CharSequence extra_text = extras.getCharSequence(Intent.EXTRA_TEXT);
mText = getShareStatus(this, parseString(extra_subject), parseString(extra_text));
} else {
mText = bundle.getString(INTENT_KEY_TEXT);
}
if (mImageUri == null) {
final Uri extra_stream = extras.getParcelable(Intent.EXTRA_STREAM);
final String content_type = getIntent().getType();
if (extra_stream != null && content_type != null && content_type.startsWith("image/")) {
final String real_path = getImagePathFromUri(this, extra_stream);
final File file = real_path != null ? new File(real_path) : null;
if (file != null && file.exists()) {
mImageUri = Uri.fromFile(file);
mIsImageAttached = true;
mIsPhotoAttached = false;
} else {
mImageUri = null;
mIsImageAttached = false;
}
}
}
}
} else if (bundle != null) {
if (bundle.getString(INTENT_KEY_TEXT) != null) {
mText = bundle.getString(INTENT_KEY_TEXT);
}
}
}
final File image_file = mImageUri != null && "file".equals(mImageUri.getScheme()) ? new File(
mImageUri.getPath()) : null;
final boolean image_file_valid = image_file != null && image_file.exists();
mImageThumbnailPreview.setVisibility(image_file_valid ? View.VISIBLE : View.GONE);
if (image_file_valid) {
reloadAttachedImageThumbnail(image_file);
}
mImageThumbnailPreview.setOnClickListener(this);
mImageThumbnailPreview.setOnLongClickListener(this);
mMenuBar.setOnMenuItemClickListener(this);
mMenuBar.inflate(R.menu.menu_compose);
mMenuBar.show();
if (mPreferences.getBoolean(PREFERENCE_KEY_QUICK_SEND, false)) {
mEditText.setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
mEditText.setMovementMethod(ArrowKeyMovementMethod.getInstance());
mEditText.setImeOptions(EditorInfo.IME_ACTION_GO);
mEditText.setOnEditorActionListener(this);
}
mEditText.addTextChangedListener(this);
if (mText != null) {
mEditText.setText(mText);
if (mIsQuote) {
mEditText.setSelection(0);
} else if (text_selection_start != -1 && text_selection_start < mEditText.length()
&& mEditText.length() > 0) {
mEditText.setSelection(text_selection_start, mEditText.length() - 1);
} else if (mEditText.length() > 0) {
mEditText.setSelection(mEditText.length());
}
}
invalidateSupportOptionsMenu();
setMenu();
if (mColorIndicator != null) {
mColorIndicator.setOrientation(ColorView.VERTICAL);
mColorIndicator.setColor(getAccountColors(this, mAccountIds));
}
mContentModified = savedInstanceState != null ? savedInstanceState.getBoolean(
INTENT_KEY_CONTENT_MODIFIED) : false;
mIsPossiblySensitive = savedInstanceState != null ? savedInstanceState
.getBoolean(INTENT_KEY_IS_POSSIBLY_SENSITIVE) : false;
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.menu_compose_actionbar, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onEditorAction(final TextView view, final int actionId, final KeyEvent event) {
if (event == null) return false;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_ENTER: {
if (event.getAction() == KeyEvent.ACTION_UP) {
send();
}
return true;
}
}
return false;
}
/** Sets the mRecentLocation object to the current location of the device **/
@Override
public void onLocationChanged(final Location location) {
mRecentLocation = location;
}
@Override
public boolean onLongClick(final View view) {
switch (view.getId()) {
case R.id.image_thumbnail_preview: {
onClick(view);
return true;
}
}
return false;
}
public void removeAttachments() {
if (mIsImageAttached && !mIsPhotoAttached) {
mImageUri = null;
} else if (mIsPhotoAttached && !mIsImageAttached) {
final File image_file = mImageUri != null && "file".equals(mImageUri.getScheme()) ? new File(
mImageUri.getPath()) : null;
if (image_file != null) {
image_file.delete();
}
mImageUri = null;
}
mIsPhotoAttached = false;
mIsImageAttached = false;
reloadAttachedImageThumbnail(null);
setMenu();
}
@SuppressWarnings("deprecation")
@Override
public boolean onMenuItemClick(final MenuItem item) {
switch (item.getItemId()) {
case MENU_TAKE_PHOTO: {
if (item.getTitle().equals(getString(R.string.remove_photo))) {
if (mImageUri == null) return false;
removeAttachments();
}
else {
takePhoto();
}
break;
}
case MENU_LAST_PHOTO: {
String[] projection = new String[]{MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE
};
final Cursor cursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
if (cursor.moveToFirst()) {
String imageLocation = cursor.getString(1);
File imageFile = new File(imageLocation);
if (imageFile != null && imageFile.exists()) { // TODO: is there a better way to do this?
mImageUri = Uri.fromFile(imageFile);
mIsPhotoAttached = false;
mIsImageAttached = true;
mImageThumbnailPreview.setVisibility(View.VISIBLE);
reloadAttachedImageThumbnail(imageFile);
} else {
mIsImageAttached = false;
}
setMenu();
boolean isAutoUpload = mPreferences.getBoolean(PREFERENCE_KEY_AUTO_UPLOAD, false);
if (!isNullOrEmpty(mUploadProvider) && mIsImageAttached && isAutoUpload) {
postMedia();
}
}
break;
}
case MENU_ADD_IMAGE: {
if (item.getTitle().equals(getString(R.string.remove_image))) {
if (mImageUri == null) return false;
removeAttachments();
}
else {
pickImage();
}
break;
}
case MENU_SHORTEN_LINKS: {
String s = parseString(mEditText.getText());
new UrlShortenerTask().execute(s);
break;
}
case MENU_ADD_TO_BUFFER: {
if (mIsBuffer) {
mIsBuffer = false;
}
else {
mIsBuffer = true;
}
setMenu();
break;
}
case MENU_SCHEDULE_TWEET: {
if (mScheduleDate != null) {
mScheduleDate = null;
setMenu();
}
else {
Intent intent = new Intent(INTENT_ACTION_SCHEDULE_TWEET);
if (mScheduleDate != null) {
Bundle bundle = new Bundle();
bundle.putString(INTENT_KEY_SCHEDULE_DATE_TIME, mScheduleDate);
intent.putExtras(bundle);
}
startActivityForResult(intent, REQUEST_SCHEDULE_DATE);
}
break;
}
case MENU_UPLOAD: {
if (!isNullOrEmpty(mUploadProvider) && mIsImageAttached) {
postMedia(true);
}
break;
}
case MENU_ADD_LOCATION: {
final boolean attach_location = mPreferences.getBoolean(PREFERENCE_KEY_ATTACH_LOCATION, false);
if (!attach_location) {
getLocation();
}
mPreferences.edit().putBoolean(PREFERENCE_KEY_ATTACH_LOCATION, !attach_location).commit();
setMenu();
break;
}
case MENU_DRAFTS: {
startActivity(new Intent(INTENT_ACTION_DRAFTS));
break;
}
case MENU_DELETE: {
if (mImageUri == null) return false;
removeAttachments();
break;
}
case MENU_EDIT: {
if (mImageUri == null) return false;
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_EDIT_IMAGE);
intent.setData(mImageUri);
startActivityForResult(Intent.createChooser(intent, getString(R.string.open_with_extensions)),
REQUEST_EDIT_IMAGE);
// Create the intent needed to start feather
/*Intent newIntent = new Intent( this, FeatherActivity.class );
// set the source image uri
newIntent.setData( mImageUri );
// pass the required api key ( http://developers.aviary.com/ )
newIntent.putExtra( "API_KEY", AVIARY_SDK_API_KEY );
// pass the uri of the destination image file (optional)
// This will be the same uri you will receive in the onActivityResult
//newIntent.putExtra( "output", mImageUri);
// format of the destination image (optional)
newIntent.putExtra( "output-format", Bitmap.CompressFormat.JPEG.name() );
// output format quality (optional)
newIntent.putExtra( "output-quality", 85 );
// you can force feather to display only a certain tools
// newIntent.putExtra( "tools-list", new String[]{"ADJUST", "BRIGHTNESS" } );
// enable fast rendering preview
newIntent.putExtra( "effect-enable-fast-preview", true );
// limit the image size
// You can pass the current display size as max image size because after
// the execution of Aviary you can save the HI-RES image so you don't need a big
// image for the preview
// newIntent.putExtra( "max-image-size", 800 );
// you want to hide the exit alert dialog shown when back is pressed
// without saving image first
// newIntent.putExtra( "hide-exit-unsave-confirmation", true );
// ..and start feather
startActivityForResult( newIntent, ACTION_REQUEST_FEATHER );*/
break;
}
case MENU_VIEW: {
openImage(this, mImageUri, false);
break;
}
case MENU_TOGGLE_SENSITIVE: {
final boolean has_media = (mIsImageAttached || mIsPhotoAttached) && mImageUri != null;
if (!has_media) return false;
mIsPossiblySensitive = !mIsPossiblySensitive;
setMenu();
break;
}
}
return true;
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case MENU_HOME: {
final String text = mEditText != null ? parseString(mEditText.getText()) : null;
if (mContentModified && !isNullOrEmpty(text)) {
mUnsavedTweetDialogFragment = (DialogFragment) Fragment.instantiate(this,
UnsavedTweetDialogFragment.class.getName());
final Bundle args = new Bundle();
args.putBoolean(INTENT_KEY_IS_NAVIGATE_UP, true);
mUnsavedTweetDialogFragment.setArguments(args);
mUnsavedTweetDialogFragment.show(getSupportFragmentManager(), "unsaved_tweet");
} else {
NavUtils.navigateUpFromSameTask(this);
}
break;
}
case MENU_SEND: {
send();
break;
}
case MENU_SELECT_ACCOUNT: {
final Intent intent = new Intent(INTENT_ACTION_SELECT_ACCOUNT);
final Bundle bundle = new Bundle();
bundle.putBoolean(INTENT_KEY_ACTIVATED_ONLY, true);
bundle.putLongArray(INTENT_KEY_IDS, mAccountIds);
intent.putExtras(bundle);
startActivityForResult(intent, REQUEST_SELECT_ACCOUNT);
break;
}
}
return super.onOptionsItemSelected(item);
}
protected void send() {
final String text_orig = mEditText != null ? parseString(mEditText.getText()) : null;
final String atext = mIsPhotoAttached || mIsImageAttached ? mUploadUseExtension ? getImageUploadStatus(this,
FAKE_IMAGE_LINK, text_orig) : text_orig + " " + FAKE_IMAGE_LINK : text_orig;
final int count = mValidator.getTweetLength(atext);
if (!isNullOrEmpty(mUploadProvider) && (mIsPhotoAttached || mIsImageAttached)) {
postMedia();
}
else if (count > 140) {
if (mScheduleDate != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.schedule_tweet));
builder.setMessage(getString(R.string.schedule_tweet_too_long));
builder.setCancelable(true);
AlertDialog alert = builder.create();
alert.show();
}
else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.tweet_too_long));
builder.setMessage(getString(R.string.confirm_twitlonger));
builder.setCancelable(true);
builder.setPositiveButton(getString(R.string.send_to_twitlonger),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
postTwitlonger();
}
});
builder.setNeutralButton(getString(R.string.split_tweets), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
splitTweets();
}
});
builder.setNegativeButton(getString(R.string.cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
//actuallyPost();
}
});
//
AlertDialog alert = builder.create();
alert.show();
}
}
else {
if (mScheduleDate != null && isNullOrEmpty(mUploadProvider) && (mIsPhotoAttached || mIsImageAttached)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.schedule_tweet));
builder.setMessage(getString(R.string.schedule_tweet_pic_twitter));
builder.setCancelable(true);
AlertDialog alert = builder.create();
alert.show();
}
else if (mScheduleDate != null && mIsBuffer == true) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.schedule_tweet));
builder.setMessage(getString(R.string.schedule_tweet_buffer));
builder.setCancelable(true);
AlertDialog alert = builder.create();
alert.show();
}
else if (mIsBuffer == true && isNullOrEmpty(mUploadProvider) && (mIsPhotoAttached || mIsImageAttached)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.add_to_buffer));
builder.setMessage(getString(R.string.buffer_pic_twitter));
builder.setCancelable(true);
AlertDialog alert = builder.create();
alert.show();
}
else {
actuallyPost();
}
}
}
protected void splitTweets() {
String text = mEditText != null ? parseString(mEditText.getText()) : null;
String[] chunks = text.split("\\s+");
String replyTo = null;
if (chunks.length >= 1) {
final String firstWord = chunks[0];
final char firstCharacter = firstWord.charAt(0);
if (Character.toString(firstCharacter).equals("@")) {
replyTo = firstWord;
}
}
String currentPart = "";
tweetParts = new ArrayList<String>();
for (final String word : chunks) {
int checkLength = 120;
if (tweetParts.size() > 1 && replyTo != null) {
checkLength = 120 - replyTo.length() + 1;
}
if (currentPart.length() + word.length() + 1 > checkLength) {
if (tweetParts.size() >= 1 && replyTo != null) {
tweetParts.add(replyTo + " " + currentPart);
}
else {
tweetParts.add(currentPart);
}
currentPart = "";
}
if (currentPart.equals("")) {
currentPart = word;
}
else {
currentPart = currentPart + " " + word;
}
}
if (!currentPart.equals("")) {
if (tweetParts.size() >= 1 && replyTo != null) {
tweetParts.add(replyTo + " " + currentPart);
}
else {
tweetParts.add(currentPart);
}
}
if (tweetParts.size() >= 1) {
for (int i=tweetParts.size(); i>0; i--) {
String part = tweetParts.get(i-1);
String postString = part + " (" + getString(R.string.split_part) + " " + Integer.toString(i) + ")";
final boolean attach_location = mPreferences.getBoolean(PREFERENCE_KEY_ATTACH_LOCATION, false);
final boolean has_media = (mIsImageAttached || mIsPhotoAttached) && mImageUri != null;
mService.updateStatus(mAccountIds, postString, attach_location ? mRecentLocation : null, mImageUri,
mInReplyToStatusId, has_media && mIsPossiblySensitive, mIsPhotoAttached && !mIsImageAttached);
}
setResult(Activity.RESULT_OK);
finish();
}
}
protected void actuallyPost() {
final String text = mEditText != null ? parseString(mEditText.getText()) : null;
final boolean attach_location = mPreferences.getBoolean(PREFERENCE_KEY_ATTACH_LOCATION, false);
if (mScheduleDate != null) {
mService.scheduleStatus(mScheduleDate, mAccountIds, text, attach_location ? mRecentLocation : null, mImageUri,
mInReplyToStatusId, mIsPhotoAttached && !mIsImageAttached);
}
else if (mIsBuffer == true) {
mService.bufferStatus(mAccountIds, text);
}
else {
final boolean has_media = (mIsImageAttached || mIsPhotoAttached) && mImageUri != null;
mService.updateStatus(mAccountIds, text, attach_location ? mRecentLocation : null, mImageUri,
mInReplyToStatusId, has_media && mIsPossiblySensitive, mIsPhotoAttached && !mIsImageAttached);
}
setResult(Activity.RESULT_OK);
finish();
}
protected void postMedia() {
postMedia(false);
}
protected void postMedia(boolean immediate_upload) {
final String image_path = getImagePathFromUri(this, mImageUri);
//final File image_file = image_path != null ? new File(image_path) : null;
UploadMediaTask task = new UploadMediaTask();
task.setUploadImmediately(immediate_upload);
long accountId = 0;
if (mAccountIds != null && mAccountIds.length > 0) {
accountId = mAccountIds[0];
}
final AccessToken accessToken = getTwitterAccessToken(this, accountId);
task.setAccessToken(accessToken);
task.execute(image_path);
}
private class UploadMediaTask extends AsyncTask<String, Integer, String> {
private ProgressDialog dialog;
private AccessToken accessToken;
private boolean uploadImmediately = false;
public void setAccessToken(AccessToken accessToken) {
this.accessToken = accessToken;
}
public void setUploadImmediately(boolean uploadImmediately) {
this.uploadImmediately = uploadImmediately;
}
// can use UI thread here
protected void onPreExecute() {
dialog = new ProgressDialog(ComposeActivity.this);
dialog.setMessage(getString(R.string.uploading_media));
dialog.setIndeterminate(false);
dialog.setCancelable(false);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
dialog.show();
}
// automatically done on worker thread (separate from UI thread)
protected String doInBackground(final String... args) {
String path = args[0];
uploadTimer = new Timer();
uploadTimer.schedule(new TimerTask() {
@Override
public void run() {
UploadProgressMethod(dialog);
}
}, 0, 50);
String url = null;
String consumer_key = mPreferences.getString(PREFERENCE_KEY_CONSUMER_KEY, CONSUMER_KEY);
String consumer_secret = mPreferences.getString(PREFERENCE_KEY_CONSUMER_SECRET, CONSUMER_SECRET);
if (isNullOrEmpty(consumer_key) || isNullOrEmpty(consumer_secret)) {
consumer_key = CONSUMER_KEY;
consumer_secret = CONSUMER_SECRET;
}
if (mUploadProvider.equals("twitpic")) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setMediaProviderAPIKey(TWITPIC_API_KEY);
cb.setOAuthConsumerKey(consumer_key);
cb.setOAuthConsumerSecret(consumer_secret);
cb.setOAuthAccessToken(accessToken.getToken());
cb.setOAuthAccessTokenSecret(accessToken.getTokenSecret());
Configuration conf = cb.build();
upload = new ImageUploadFactory(conf).getInstance(MediaProvider.TWITPIC);
}
else if (mUploadProvider.equals("yfrog")) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setMediaProviderAPIKey(YFROG_API_KEY);
cb.setOAuthConsumerKey(consumer_key);
cb.setOAuthConsumerSecret(consumer_secret);
cb.setOAuthAccessToken(accessToken.getToken());
cb.setOAuthAccessTokenSecret(accessToken.getTokenSecret());
Configuration conf = cb.build();
upload = new ImageUploadFactory(conf).getInstance(MediaProvider.YFROG);
}
else if (mUploadProvider.equals("imgly")) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey(consumer_key);
cb.setOAuthConsumerSecret(consumer_secret);
cb.setOAuthAccessToken(accessToken.getToken());
cb.setOAuthAccessTokenSecret(accessToken.getTokenSecret());
Configuration conf = cb.build();
upload = new ImageUploadFactory(conf).getInstance(MediaProvider.IMG_LY);
}
else if (mUploadProvider.equals("lockerz")) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setMediaProviderAPIKey(PLIXI_API_KEY);
cb.setOAuthConsumerKey(consumer_key);
cb.setOAuthConsumerSecret(consumer_secret);
cb.setOAuthAccessToken(accessToken.getToken());
cb.setOAuthAccessTokenSecret(accessToken.getTokenSecret());
Configuration conf = cb.build();
upload = new ImageUploadFactory(conf).getInstance(MediaProvider.LOCKERZ);
}
else if (mUploadProvider.equals("moby")) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setMediaProviderAPIKey(MOBY_API_KEY);
cb.setOAuthConsumerKey(consumer_key);
cb.setOAuthConsumerSecret(consumer_secret);
cb.setOAuthAccessToken(accessToken.getToken());
cb.setOAuthAccessTokenSecret(accessToken.getTokenSecret());
Configuration conf = cb.build();
upload = new ImageUploadFactory(conf).getInstance(MediaProvider.MOBYPICTURE);
}
try {
url = upload.upload(new File(path));
} catch (TwitterException te) {
te.printStackTrace();
}
if (uploadTimer != null) {
uploadTimer.cancel();
}
return url;
}
protected void onProgressUpdate(Integer... progress) {
}
// can use UI thread here
protected void onPostExecute(final String result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (result == null) {
Dialog superSimpleDlg = new Dialog(ComposeActivity.this);
superSimpleDlg.setTitle(R.string.error_upload);
superSimpleDlg.show();
}
else {
ComposeActivity.this.uploadComplete(result);
boolean isAutoUpload = mPreferences.getBoolean(PREFERENCE_KEY_AUTO_UPLOAD, false);
if (!isAutoUpload && !uploadImmediately) {
ComposeActivity.this.send();
}
}
}
}
public void uploadComplete(String text) {
String oldText = parseString(mEditText.getText());
mEditText.setText(oldText + " " + text);
removeAttachments();
}
private void UploadProgressMethod(final ProgressDialog dialog)
{
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(new Runnable() {
public void run() {
// use data here
if (upload != null && upload.getRequestLength() > 0) {
float progress = (float)upload.getRequestStatus()/(float)upload.getRequestLength();
float longPc = progress * 100;
int percentage = Math.round(longPc);
if (percentage >= 100) {
dialog.setProgress(100);
dialog.setIndeterminate(true);
dialog.setMessage(getString(R.string.uploading_media_wait));
}
else {
dialog.setProgress(percentage);
}
}
}
});
}
private class UrlShortenerTask extends AsyncTask<String, Void, String> {
private ProgressDialog dialog;
// can use UI thread here
protected void onPreExecute() {
dialog = new ProgressDialog(ComposeActivity.this);
dialog.setMessage(getString(R.string.shortening));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
// automatically done on worker thread (separate from UI thread)
protected String doInBackground(final String... args) {
String text = ComposeActivity.this.doShrink(args[0]);
return text;
}
// can use UI thread here
protected void onPostExecute(final String result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (result == null) {
Dialog superSimpleDlg = new Dialog(ComposeActivity.this);
superSimpleDlg.setTitle(R.string.error_shorten);
superSimpleDlg.show();
}
else {
ComposeActivity.this.urlShortenerComplete(result);
}
}
}
public void urlShortenerComplete(String text) {
//String s = parseString(mEditText.getText());
mEditText.setText(text);
}
private final void gatherLinks(ArrayList<Hyperlink> links,
Spannable s, Pattern pattern)
{
// Matcher matching the pattern
Matcher m = pattern.matcher(s);
while (m.find())
{
int start = m.start();
int end = m.end();
/*
* Hyperlink is basically used like a structure for storing the information about
* where the link was found.
*/
Hyperlink spec = new Hyperlink();
spec.textSpan = s.subSequence(start, end);
spec.span = new InternalURLSpan(spec.textSpan.toString());
spec.start = start;
spec.end = end;
links.add(spec);
}
}
public class InternalURLSpan extends ClickableSpan
{
private String clickedSpan;
public InternalURLSpan (String clickedString)
{
clickedSpan = clickedString;
}
@Override
public void onClick(View textView)
{
}
}
/*
* Class for storing the information about the Link Location
*/
class Hyperlink
{
CharSequence textSpan;
InternalURLSpan span;
int start;
int end;
}
private String doShrink(String text) {
ArrayList<Hyperlink> listOfLinks = new ArrayList<Hyperlink>();
SpannableString linkableText = new SpannableString(text);
Pattern hyperLinksPattern = Pattern.compile("([Hh][tT][tT][pP][sS]?:\\/\\/[^ ,'\">\\]\\)]*[^\\. ,'\">\\]\\)])");
gatherLinks(listOfLinks, linkableText, hyperLinksPattern);
for (int i = 0; i<listOfLinks.size(); i++) {
Hyperlink link = listOfLinks.get(i);
final String provider = mPreferences.getString(PREFERENCE_KEY_URL_SHORTENER, "tinyurl");
if (!link.textSpan.toString().toLowerCase().contains("http://tl.gd") &&
!link.textSpan.toString().toLowerCase().contains("http://bit.ly") &&
!link.textSpan.toString().toLowerCase().contains("http://t.co") &&
!link.textSpan.toString().toLowerCase().contains("http://tinyurl.com") &&
!link.textSpan.toString().toLowerCase().contains("http://is.gd") &&
!link.textSpan.toString().toLowerCase().contains("http://tr.im") &&
!link.textSpan.toString().toLowerCase().contains("http://twitpic.com") &&
!link.textSpan.toString().toLowerCase().contains("http://yfrog.com") &&
!link.textSpan.toString().toLowerCase().contains("http://pic.gd") &&
!link.textSpan.toString().toLowerCase().contains("http://lockerz.com") &&
!link.textSpan.toString().toLowerCase().contains("http://twitgoo.com") &&
!link.textSpan.toString().toLowerCase().contains("http://twitrpix.com") &&
!link.textSpan.toString().toLowerCase().contains("http://img.ly") &&
!link.textSpan.toString().toLowerCase().contains("http://j.mp") &&
!link.textSpan.toString().toLowerCase().contains("http://cli.cs")
) {
try {
String finalUrl = "";
if (provider.equals("googl")) {
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("https://www.googleapis.com/urlshortener/v1/url");
postRequest.addHeader("Content-Type", "application/json");
StringEntity reqEntity = new StringEntity("{\"longUrl\": \"" + link.textSpan.toString() + "\"}", HTTP.UTF_8);
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
JSONObject jObject = new JSONObject(s.toString());
text = text.replace(link.textSpan.toString(), jObject.getString("id"));
}
else {
if (provider.equals("tinyurl")) {
finalUrl = "http://tinyurl.com/api-create.php?url=" + URLEncoder.encode(link.textSpan.toString());
}
else if (provider.equals("isgd")) {
finalUrl = "http://is.gd/api.php?longurl=" + URLEncoder.encode(link.textSpan.toString());
}
else if (provider.equals("bitly")) {
finalUrl = "http://api.bitly.com/v3/shorten?format=txt&login=" + BITLY_USER + "&apiKey=" + BITLY_API_KEY + "&longUrl=" + URLEncoder.encode(link.textSpan.toString());
}
else if (provider.equals("jmp")) {
finalUrl = "http://api.bitly.com/v3/shorten?domain=j.mp&format=txt&login=" + BITLY_USER + "&apiKey=" + BITLY_API_KEY + "&longUrl=" + URLEncoder.encode(link.textSpan.toString());
}
else if (provider.equals("vgd")) {
finalUrl = "http://v.gd/create.php?format=simple&url=" + URLEncoder.encode(link.textSpan.toString());
}
else if (provider.equals("trim")) {
finalUrl = "http://api.tr.im/v1/trim_simple?url=" + URLEncoder.encode(link.textSpan.toString());
}
else if (provider.equals("googl")) {
finalUrl = "http://v.gd/create.php?format=simple&url=" + URLEncoder.encode(link.textSpan.toString());
}
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(new HttpGet(finalUrl));
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
text = text.replace(link.textSpan.toString(), s.toString());
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Network exception" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
return text;
}
private class TwitlongerTask extends AsyncTask<String, Void, String> {
//private final ProgressDialog dialog = new ProgressDialog(ComposeActivity.this);
private ProgressDialog dialog;
// can use UI thread here
protected void onPreExecute() {
dialog = new ProgressDialog(ComposeActivity.this);
dialog.setMessage(getString(R.string.twitlongering));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
// automatically done on worker thread (separate from UI thread)
protected String doInBackground(final String... args) {
String text = ComposeActivity.this.uploadTwitlonger(args[0]);
return text;
}
// can use UI thread here
protected void onPostExecute(final String result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (result == null) {
Dialog superSimpleDlg = new Dialog(ComposeActivity.this);
superSimpleDlg.setTitle(R.string.error_upload_twitlonger);
superSimpleDlg.show();
}
else {
ComposeActivity.this.twitlongerComplete(result);
ComposeActivity.this.actuallyPost();
}
}
}
private String uploadTwitlonger(String text) {
String finalUrl = "http://www.twitlonger.com/api_post/";
final String atext = parseString(mEditText.getText());
String screen_name = null;
if (mAccountIds != null && mAccountIds.length > 0) {
screen_name = getAccountUsername(this, mAccountIds[0]);
}
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(finalUrl);
MultipartEntity reqEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("username", new StringBody(screen_name));
reqEntity.addPart("application", new StringBody(TWIT_LONGER_USER));
reqEntity.addPart("api_key", new StringBody(TWIT_LONGER_API_KEY));
reqEntity.addPart("message", new StringBody(atext, Charset.forName("UTF-8")));
postRequest.setEntity(reqEntity);
HttpResponse response = httpclient.execute(postRequest);
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(response.getEntity().getContent());
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr;
expr = xpath.compile("//twitlonger/post/content/text()");
Object result = expr.evaluate(doc, XPathConstants.STRING);
Log.d("ComposeActivity.uploadTwitlonger","path: " + atext + " " + result.toString());
return result.toString();
} catch (Exception e) {
//Toast.makeText(getApplicationContext(), "Network exception" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
return null;
}
protected void postTwitlonger() {
final String text = mEditText != null ? parseString(mEditText.getText()) : null;
new TwitlongerTask().execute(text);
}
public void twitlongerComplete(String text) {
mEditText.setText(text);
}
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
if (menu == null || mEditText == null || mTextCount == null) return false;
final String text_orig = parseString(mEditText.getText());
final String text = mIsPhotoAttached || mIsImageAttached ? mUploadUseExtension ? getImageUploadStatus(this,
FAKE_IMAGE_LINK, text_orig) : text_orig + " " + FAKE_IMAGE_LINK : text_orig;
final int count = mValidator.getTweetLength(text);
final float hue = count < 140 ? count >= 130 ? 5 * (140 - count) : 50 : 0;
final float[] hsv = new float[] { hue, 1.0f, 1.0f };
mTextCount.setTextColor(count >= 130 ? Color.HSVToColor(0x80, hsv) : 0x80808080);
mTextCount.setText(parseString(140-count));
final MenuItem sendItem = menu.findItem(MENU_SEND);
if (sendItem != null) {
sendItem.setEnabled(text_orig.length() > 0);
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public void onProviderDisabled(final String provider) {
}
@Override
public void onProviderEnabled(final String provider) {
}
@Override
public void onSaveInstanceState(final Bundle outState) {
mText = parseString(mEditText.getText());
outState.putLongArray(INTENT_KEY_IDS, mAccountIds);
outState.putString(INTENT_KEY_TEXT, mText);
outState.putLong(INTENT_KEY_IN_REPLY_TO_ID, mInReplyToStatusId);
outState.putString(INTENT_KEY_IN_REPLY_TO_NAME, mInReplyToName);
outState.putString(INTENT_KEY_IN_REPLY_TO_SCREEN_NAME, mInReplyToScreenName);
outState.putBoolean(INTENT_KEY_IS_QUOTE, mIsQuote);
outState.putBoolean(INTENT_KEY_IS_IMAGE_ATTACHED, mIsImageAttached);
outState.putBoolean(INTENT_KEY_IS_PHOTO_ATTACHED, mIsPhotoAttached);
outState.putParcelable(INTENT_KEY_IMAGE_URI, mImageUri);
outState.putBoolean(INTENT_KEY_CONTENT_MODIFIED, mContentModified);
outState.putBoolean(INTENT_KEY_IS_POSSIBLY_SENSITIVE, mIsPossiblySensitive);
super.onSaveInstanceState(outState);
}
@Override
public void onStart() {
super.onStart();
final String component = mPreferences.getString(PREFERENCE_KEY_IMAGE_UPLOADER, null);
mUploadUseExtension = !isNullOrEmpty(component);
if (mMenuBar != null) {
setMenu();
}
}
@Override
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
}
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
invalidateSupportOptionsMenu();
mContentModified = true;
}
public void saveToDrafts() {
final String text = mEditText != null ? parseString(mEditText.getText()) : null;
final ContentValues values = new ContentValues();
values.put(Drafts.TEXT, text);
values.put(Drafts.ACCOUNT_IDS, ArrayUtils.toString(mAccountIds, ',', false));
values.put(Drafts.IN_REPLY_TO_STATUS_ID, mInReplyToStatusId);
values.put(Drafts.IN_REPLY_TO_NAME, mInReplyToName);
values.put(Drafts.IN_REPLY_TO_SCREEN_NAME, mInReplyToScreenName);
values.put(Drafts.IS_QUOTE, mIsQuote ? 1 : 0);
values.put(Drafts.IS_QUEUED, false);
values.put(Drafts.IS_POSSIBLY_SENSITIVE, mIsPossiblySensitive ? 1 : 0);
if (mImageUri != null) {
values.put(Drafts.IS_IMAGE_ATTACHED, mIsImageAttached);
values.put(Drafts.IS_PHOTO_ATTACHED, mIsPhotoAttached);
values.put(Drafts.IMAGE_URI, parseString(mImageUri));
}
mResolver.insert(Drafts.CONTENT_URI, values);
}
@Override
public void onStop() {
if (mPopupMenu != null) {
mPopupMenu.dismiss();
}
super.onStop();
}
/**
* The Location Manager manages location providers. This code searches for
* the best provider of data (GPS, WiFi/cell phone tower lookup, some other
* mechanism) and finds the last known location.
**/
private boolean getLocation() {
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
final String provider = mLocationManager.getBestProvider(criteria, true);
if (provider != null) {
mRecentLocation = mLocationManager.getLastKnownLocation(provider);
} else {
Toast.makeText(this, R.string.cannot_get_location, Toast.LENGTH_SHORT).show();
}
return provider != null;
}
private void pickImage() {
final Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
try {
startActivityForResult(i, REQUEST_PICK_IMAGE);
} catch (final ActivityNotFoundException e) {
showErrorToast(this, null, e, false);
}
}
private void reloadAttachedImageThumbnail(final File file) {
if (mAttachedImageThumbnailTask != null && mAttachedImageThumbnailTask.getStatus() == AsyncTask.Status.RUNNING) {
mAttachedImageThumbnailTask.cancel(true);
}
mAttachedImageThumbnailTask = new AttachedImageThumbnailTask(file);
mAttachedImageThumbnailTask.execute();
}
private void setMenu() {
final Menu menu = mMenuBar.getMenu();
final int activated_color = getResources().getColor(R.color.holo_blue_bright);
final MenuItem itemAddImage = menu.findItem(MENU_ADD_IMAGE);
final MenuItem itemLibrary = menu.findItem(MENU_LIBRARY_MENU);
final Drawable iconAddImage = itemAddImage.getIcon().mutate();
final Drawable iconLibrary = itemLibrary.getIcon().mutate();
boolean menuSelected = false;
if (mIsImageAttached && !mIsPhotoAttached) {
iconAddImage.setColorFilter(activated_color, Mode.MULTIPLY);
itemAddImage.setTitle(R.string.remove_image);
menuSelected = true;
} else {
iconAddImage.clearColorFilter();
itemAddImage.setTitle(R.string.add_image);
}
final MenuItem itemTakePhoto = menu.findItem(MENU_TAKE_PHOTO);
final Drawable iconTakePhoto = itemTakePhoto.getIcon().mutate();
if (!mIsImageAttached && mIsPhotoAttached) {
iconTakePhoto.setColorFilter(activated_color, Mode.MULTIPLY);
itemTakePhoto.setTitle(R.string.remove_photo);
menuSelected = true;
} else {
iconTakePhoto.clearColorFilter();
itemTakePhoto.setTitle(R.string.take_photo);
}
if (menuSelected == true) {
iconLibrary.setColorFilter(activated_color, Mode.MULTIPLY);
}
else {
iconLibrary.clearColorFilter();
}
final MenuItem itemAttachLocation = menu.findItem(MENU_ADD_LOCATION);
final Drawable iconAttachLocation = itemAttachLocation.getIcon().mutate();
final boolean attach_location = mPreferences.getBoolean(PREFERENCE_KEY_ATTACH_LOCATION, false);
if (attach_location && getLocation()) {
iconAttachLocation.setColorFilter(activated_color, Mode.MULTIPLY);
itemAttachLocation.setTitle(R.string.remove_location);
} else {
mPreferences.edit().putBoolean(PREFERENCE_KEY_ATTACH_LOCATION, false).commit();
iconAttachLocation.clearColorFilter();
itemAttachLocation.setTitle(R.string.add_location);
}
final MenuItem itemMore = menu.findItem(R.id.more_submenu);
boolean moreHighlighted = false;
if (itemMore != null) {
final MenuItem itemDrafts = menu.findItem(R.id.drafts);
final MenuItem itemToggleSensitive = menu.findItem(MENU_TOGGLE_SENSITIVE);
if (itemMore != null) {
if (itemDrafts != null) {
final Cursor drafts_cur = getContentResolver().query(Drafts.CONTENT_URI, new String[0], null, null,
null);
final Drawable iconMore = itemMore.getIcon().mutate();
final Drawable iconDrafts = itemDrafts.getIcon().mutate();
if (drafts_cur.getCount() > 0) {
moreHighlighted = true;
iconDrafts.setColorFilter(activated_color, Mode.MULTIPLY);
} else {
iconDrafts.clearColorFilter();
}
drafts_cur.close();
}
if (itemToggleSensitive != null) {
final boolean has_media = (mIsImageAttached || mIsPhotoAttached) && mImageUri != null;
if (has_media && isNullOrEmpty(mUploadProvider)) {
itemToggleSensitive.setVisible(true);
}
else {
itemToggleSensitive.setVisible(false);
}
if (has_media && isNullOrEmpty(mUploadProvider)) {
final Drawable iconToggleSensitive = itemToggleSensitive.getIcon().mutate();
if (mIsPossiblySensitive) {
moreHighlighted = true;
iconToggleSensitive.setColorFilter(activated_color, Mode.MULTIPLY);
} else {
iconToggleSensitive.clearColorFilter();
}
}
}
}
}
if (mScheduleDate != null) {
final MenuItem itemSchedule = menu.findItem(R.id.schedule_tweet);
final Drawable iconSchedule = itemSchedule.getIcon().mutate();
iconSchedule.setColorFilter(activated_color, Mode.MULTIPLY);
moreHighlighted = true;
itemSchedule.setTitle(getString(R.string.schedule_clear));
}
else {
final MenuItem itemSchedule = menu.findItem(R.id.schedule_tweet);
final Drawable iconSchedule = itemSchedule.getIcon().mutate();
iconSchedule.clearColorFilter();
itemSchedule.setTitle(getString(R.string.schedule_tweet));
}
final String consumer_key = mPreferences.getString(PREFERENCE_KEY_CONSUMER_KEY, null);
final String consumer_secret = mPreferences.getString(PREFERENCE_KEY_CONSUMER_SECRET, null);
if (!isNullOrEmpty(consumer_key) && !isNullOrEmpty(consumer_secret)) {
final MenuItem itemSchedule = menu.findItem(R.id.schedule_tweet);
itemSchedule.setVisible(false);
}
final MenuItem bufferItem = menu.findItem(MENU_ADD_TO_BUFFER);
if (bufferItem != null) {
final String buffer_authorised = mPreferences.getString(PREFERENCE_KEY_BUFFERAPP_ACCESS_TOKEN, null);
final Drawable iconBuffer = bufferItem.getIcon().mutate();
if (buffer_authorised != null && !buffer_authorised.equals("")) {
bufferItem.setVisible(true);
if (mIsBuffer) {
iconBuffer.setColorFilter(activated_color, Mode.MULTIPLY);
moreHighlighted = true;
}
else {
iconBuffer.clearColorFilter();
}
}
else {
bufferItem.setVisible(false);
mIsBuffer = false;
}
}
if (itemMore != null) {
final Drawable iconMore = itemMore.getIcon().mutate();
if (moreHighlighted == true) {
iconMore.setColorFilter(activated_color, Mode.MULTIPLY);
} else {
iconMore.clearColorFilter();
}
}
mMenuBar.invalidate();
invalidateSupportOptionsMenu();
}
private void takePhoto() {
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
final File cache_dir = EnvironmentAccessor.getExternalCacheDir(this);
final File file = new File(cache_dir, "tmp_photo_" + System.currentTimeMillis() + ".jpg");
mImageUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
try {
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
} catch (final ActivityNotFoundException e) {
showErrorToast(this, null, e, false);
}
}
}
public static class UnsavedTweetDialogFragment extends BaseDialogFragment implements DialogInterface.OnClickListener {
private boolean mIsNavigateUp;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Bundle args = getArguments();
if (args != null) {
mIsNavigateUp = args.getBoolean(INTENT_KEY_IS_NAVIGATE_UP);
}
}
@Override
public void onClick(final DialogInterface dialog, final int which) {
final FragmentActivity activity = getActivity();
switch (which) {
case DialogInterface.BUTTON_POSITIVE: {
if (activity instanceof ComposeActivity) {
((ComposeActivity) activity).saveToDrafts();
if (mIsNavigateUp) {
NavUtils.navigateUpFromSameTask(activity);
} else {
activity.finish();
}
}
break;
}
case DialogInterface.BUTTON_NEGATIVE: {
if (mIsNavigateUp) {
NavUtils.navigateUpFromSameTask(activity);
} else {
activity.finish();
}
break;
}
}
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.unsaved_tweet);
builder.setPositiveButton(R.string.save, this);
builder.setNeutralButton(android.R.string.cancel, null);
builder.setNegativeButton(R.string.discard, this);
return builder.create();
}
}
class AttachedImageThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
private final File file;
public AttachedImageThumbnailTask(final File file) {
this.file = file;
}
@Override
protected Bitmap doInBackground(final Void... args) {
if (file != null && file.exists()) {
final int thumbnail_size_px = (int) (THUMBNAIL_SIZE * getResources().getDisplayMetrics().density);
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getPath(), o);
final int tmp_width = o.outWidth;
final int tmp_height = o.outHeight;
if (tmp_width == 0 || tmp_height == 0) return null;
final BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = Math.round(Math.max(tmp_width, tmp_height) / thumbnail_size_px);
return BitmapFactory.decodeFile(file.getPath(), o2);
}
return null;
}
@Override
protected void onPostExecute(final Bitmap result) {
mImageThumbnailPreview.setVisibility(result != null ? View.VISIBLE : View.GONE);
mImageThumbnailPreview.setImageBitmap(result);
super.onPostExecute(result);
}
}
}