/*
* 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.fragment;
import static com.dwdesign.tweetings.util.HtmlEscapeHelper.unescape;
import static com.dwdesign.tweetings.util.Utils.clearUserColor;
import static com.dwdesign.tweetings.util.Utils.findStatusInDatabases;
import static com.dwdesign.tweetings.util.Utils.formatToLongTimeString;
import static com.dwdesign.tweetings.util.Utils.getAccountColor;
import static com.dwdesign.tweetings.util.Utils.getActivatedAccountIds;
import static com.dwdesign.tweetings.util.Utils.getBiggerTwitterProfileImage;
import static com.dwdesign.tweetings.util.Utils.getImagesInStatus;
import static com.dwdesign.tweetings.util.Utils.getQuoteStatus;
import static com.dwdesign.tweetings.util.Utils.getTwitterInstance;
import static com.dwdesign.tweetings.util.Utils.getUserColor;
import static com.dwdesign.tweetings.util.Utils.getUserTypeIconRes;
import static com.dwdesign.tweetings.util.Utils.isMyActivatedAccount;
import static com.dwdesign.tweetings.util.Utils.isMyRetweet;
import static com.dwdesign.tweetings.util.Utils.isNullOrEmpty;
import static com.dwdesign.tweetings.util.Utils.openConversation;
import static com.dwdesign.tweetings.util.Utils.openUserProfile;
import static com.dwdesign.tweetings.util.Utils.openUserRetweetedStatus;
import static com.dwdesign.tweetings.util.Utils.openUserTimeline;
import static com.dwdesign.tweetings.util.Utils.parseURL;
import static com.dwdesign.tweetings.util.Utils.setMenuForStatus;
import static com.dwdesign.tweetings.util.Utils.setUserColor;
import static com.dwdesign.tweetings.util.Utils.showErrorToast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.List;
import java.util.Locale;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import com.dwdesign.menubar.MenuBar;
import com.dwdesign.menubar.MenuBar.OnMenuItemClickListener;
import com.dwdesign.tweetings.R;
import com.dwdesign.tweetings.activity.ComposeActivity;
import com.dwdesign.tweetings.app.TweetingsApplication;
import com.dwdesign.tweetings.model.ImageSpec;
import com.dwdesign.tweetings.model.Panes;
import com.dwdesign.tweetings.model.ParcelableLocation;
import com.dwdesign.tweetings.model.ParcelableStatus;
import com.dwdesign.tweetings.provider.TweetStore.Accounts;
import com.dwdesign.tweetings.provider.TweetStore.Filters;
import com.dwdesign.tweetings.provider.TweetStore.Mentions;
import com.dwdesign.tweetings.provider.TweetStore.Statuses;
import com.dwdesign.tweetings.util.HtmlEscapeHelper;
import com.dwdesign.tweetings.util.ImageLoaderWrapper;
import com.dwdesign.tweetings.util.OnLinkClickHandler;
import com.dwdesign.tweetings.util.ServiceInterface;
import com.dwdesign.tweetings.util.TwidereLinkify;
import twitter4j.Relationship;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.internal.org.json.JSONArray;
import twitter4j.internal.org.json.JSONException;
import twitter4j.internal.org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Html;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.twitter.Extractor;
public class StatusFragment extends BaseFragment implements OnClickListener, OnMenuItemClickListener, Panes.Right {
private long mAccountId, mStatusId;
private boolean mLoadMoreAutomatically;
private boolean mFollowInfoDisplayed, mLocationInfoDisplayed;
private ServiceInterface mService;
private SharedPreferences mPreferences;
private TextView mNameView, mScreenNameView, mTextView, mTimeAndSourceView, mInReplyToView, mLocationView,
mRetweetedStatusView;
private ImageView mProfileImageView;
private Button mFollowButton;
private View mStatusContent, mProfileView, mFollowIndicator, mImagesPreviewContainer, mContentScroller,
mUserColorLabel;
private MenuBar mMenuBar;
private ProgressBar mStatusLoadProgress, mFollowInfoProgress;
private FollowInfoTask mFollowInfoTask;
private ImagesPreviewFragment mImagesPreviewFragment;
private GetStatusTask mGetStatusTask;
private LocationInfoTask mLocationInfoTask;
private ParcelableStatus mStatus;
private RelativeLayout mConversationView;
private RelativeLayout mMarketView;
private PlayStoreInfoTask mPlayInfoTask;
private ImageLoaderWrapper mLazyImageLoader;
private String mAppAwareUrl;
private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
if (BROADCAST_FRIENDSHIP_CHANGED.equals(action)) {
if (mStatus != null && mStatus.user_id == intent.getLongExtra(INTENT_KEY_USER_ID, -1)
&& intent.getBooleanExtra(INTENT_KEY_SUCCEED, false)) {
showFollowInfo(true);
}
} else if (BROADCAST_FAVORITE_CHANGED.equals(action)) {
final long status_id = intent.getLongExtra(INTENT_KEY_STATUS_ID, -1);
if (status_id > 0 && status_id == mStatusId) {
getStatus(true);
}
} else if (BROADCAST_RETWEET_CHANGED.equals(action)) {
final long status_id = intent.getLongExtra(INTENT_KEY_STATUS_ID, -1);
if (status_id > 0 && status_id == mStatusId) {
getStatus(true);
}
} else if (BROADCAST_TWITLONGER_EXPANDED.equals(action)) {
final String expanded_status_text = intent.getStringExtra(INTENT_KEY_TWITLONGER_EXPANDED_TEXT);
Spanned expanded_text = Html.fromHtml(expanded_status_text);
mTextView.setText(expanded_text);
final TwidereLinkify linkify = new TwidereLinkify(mTextView);
linkify.setOnLinkClickListener(new OnLinkClickHandler(getActivity(), mAccountId, mStatus.is_possibly_sensitive));
linkify.addAllLinks();
final ContentResolver resolver = context.getContentResolver();
final ContentValues values = new ContentValues();
values.put(Statuses.TEXT, expanded_status_text);
values.put(Statuses.TEXT_PLAIN, unescape(expanded_status_text));
int updated = resolver.update(Statuses.CONTENT_URI, values, Statuses.STATUS_ID + " = " + mStatus.status_id, null);
if (updated > 0) {
context.sendBroadcast(new Intent(BROADCAST_HOME_TIMELINE_DATABASE_UPDATED));
}
values.clear();
values.put(Mentions.TEXT, expanded_status_text);
values.put(Mentions.TEXT_PLAIN, unescape(expanded_status_text));
updated = resolver.update(Mentions.CONTENT_URI, values, Mentions.STATUS_ID + " = " + mStatus.status_id, null);
if (updated > 0) {
context.sendBroadcast(new Intent(BROADCAST_MENTIONS_DATABASE_UPDATED));
}
}
}
};
@SuppressWarnings("deprecation")
public void displayStatus(final ParcelableStatus status) {
mStatus = null;
mImagesPreviewFragment.clear();
if (status == null || getActivity() == null) return;
mStatus = status;
final String buffer_authorised = mPreferences.getString(PREFERENCE_KEY_BUFFERAPP_ACCESS_TOKEN, null);
mMenuBar.inflate(R.menu.menu_status);
final MenuItem bufferView = mMenuBar.getMenu().findItem(MENU_ADD_TO_BUFFER);
if (bufferView != null) {
if (buffer_authorised != null && !buffer_authorised.equals("")) {
bufferView.setVisible(true);
}
else {
bufferView.setVisible(false);
}
}
setMenuForStatus(getActivity(), mMenuBar.getMenu(), status);
mMenuBar.show();
final boolean is_multiple_account_enabled = getActivatedAccountIds(getActivity()).length > 1;
updateUserColor();
mContentScroller.setBackgroundResource(is_multiple_account_enabled ? R.drawable.ic_label_account_nopadding : 0);
if (is_multiple_account_enabled) {
final Drawable d = mContentScroller.getBackground();
if (d != null) {
d.mutate().setColorFilter(getAccountColor(getActivity(), status.account_id), PorterDuff.Mode.MULTIPLY);
mContentScroller.invalidate();
}
}
mNameView.setText(status.name);
mScreenNameView.setText("@" + status.screen_name);
mScreenNameView.setCompoundDrawablesWithIntrinsicBounds(
getUserTypeIconRes(status.is_verified, status.is_protected), 0, 0, 0);
mTextView.setText(status.text);
final TwidereLinkify linkify = new TwidereLinkify(mTextView);
linkify.setOnLinkClickListener(new OnLinkClickHandler(getActivity(), mAccountId));
linkify.addAllLinks();
final boolean is_reply = status.in_reply_to_status_id > 0;
final String time = formatToLongTimeString(getActivity(), status.status_timestamp);
final String strTime = "<a href=\"https://twitter.com/" + status.screen_name + "/status/" + String.valueOf(status.status_id) + "\">" + time + "</a>";
final String source_html = status.source;
if (!isNullOrEmpty(time) && !isNullOrEmpty(source_html)) {
mTimeAndSourceView.setText(Html.fromHtml(getString(R.string.time_source, strTime, source_html)));
} else if (isNullOrEmpty(time) && !isNullOrEmpty(source_html)) {
mTimeAndSourceView.setText(Html.fromHtml(getString(R.string.source, source_html)));
} else if (!isNullOrEmpty(time) && isNullOrEmpty(source_html)) {
mTimeAndSourceView.setText(time);
}
mTimeAndSourceView.setMovementMethod(LinkMovementMethod.getInstance());
mInReplyToView.setVisibility(is_reply ? View.VISIBLE : View.GONE);
mConversationView.setVisibility(is_reply ? View.VISIBLE : View.GONE);
if (is_reply) {
mInReplyToView.setText(getString(R.string.in_reply_to, status.in_reply_to_screen_name));
Display display = getActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth(); // deprecated
int height = display.getHeight(); // deprecated
int heightOfConversation = (height / 2) - 48 - 44;
ViewGroup.LayoutParams params = mConversationView.getLayoutParams();
params.height = heightOfConversation;
mConversationView.setLayoutParams(params);
FragmentManager fragmentManager=getFragmentManager();
FragmentTransaction ft=null;
ft = fragmentManager.beginTransaction();
final Fragment fragment = new ConversationFragment();
final Bundle args = new Bundle();
args.putLong(INTENT_KEY_ACCOUNT_ID, mAccountId);
args.putLong(INTENT_KEY_STATUS_ID, status.in_reply_to_status_id);
fragment.setArguments(args);
ft.replace(R.id.conversation, fragment, getString(R.string.view_conversation));
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
if (status.play_package != null) {
mMarketView.setVisibility(View.VISIBLE);
mPlayInfoTask = new PlayStoreInfoTask();
mPlayInfoTask.execute();
}
else {
mMarketView.setVisibility(View.GONE);
}
final boolean hires_profile_image = getResources().getBoolean(R.bool.hires_profile_image);
final String preview_image = hires_profile_image ? getBiggerTwitterProfileImage(status.profile_image_url_string) : status.profile_image_url_string;
mLazyImageLoader.displayProfileImage(mProfileImageView, preview_image);
final List<ImageSpec> images = getImagesInStatus(status.text_html);
mImagesPreviewContainer.setVisibility(images.size() > 0 ? View.VISIBLE : View.GONE);
mImagesPreviewFragment.addAll(images);
mImagesPreviewFragment.update();
if (mLoadMoreAutomatically == true) {
mImagesPreviewFragment.show();
}
mRetweetedStatusView.setVisibility(status.is_protected ? View.GONE : View.VISIBLE);
if (status.retweet_id > 0) {
final boolean display_name = mPreferences.getBoolean(PREFERENCE_KEY_DISPLAY_NAME, false);
final String retweeted_by = display_name ? status.retweeted_by_name : status.retweeted_by_screen_name;
mRetweetedStatusView.setText(status.retweet_count > 1 ? getString(R.string.retweeted_by_with_count,
retweeted_by, status.retweet_count - 1) : getString(R.string.retweeted_by, retweeted_by));
mRetweetedStatusView.setVisibility(View.VISIBLE);
} else {
mRetweetedStatusView.setVisibility(View.GONE);
mRetweetedStatusView.setText(R.string.users_retweeted_this);
}
mLocationView.setVisibility(ParcelableLocation.isValidLocation(status.location) ? View.VISIBLE : View.GONE);
if (mLoadMoreAutomatically) {
showFollowInfo(true);
showLocationInfo(true);
} else {
mFollowIndicator.setVisibility(View.GONE);
}
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
final TweetingsApplication application = getApplication();
mService = application.getServiceInterface();
mLazyImageLoader = application.getImageLoaderWrapper();
mImagesPreviewFragment = (ImagesPreviewFragment) Fragment.instantiate(getActivity(),
ImagesPreviewFragment.class.getName());
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
mLoadMoreAutomatically = mPreferences.getBoolean(PREFERENCE_KEY_LOAD_MORE_AUTOMATICALLY, true);
final Bundle bundle = getArguments();
if (bundle != null) {
mAccountId = bundle.getLong(INTENT_KEY_ACCOUNT_ID);
mStatusId = bundle.getLong(INTENT_KEY_STATUS_ID);
bundle.setClassLoader(ParcelableStatus.class.getClassLoader());
mStatus = bundle.getParcelable(INTENT_KEY_STATUS);
mImagesPreviewFragment.setStatus(mStatus);
}
mInReplyToView.setOnClickListener(this);
mFollowButton.setOnClickListener(this);
mProfileView.setOnClickListener(this);
mLocationView.setOnClickListener(this);
mRetweetedStatusView.setOnClickListener(this);
mMenuBar.setOnMenuItemClickListener(this);
final FragmentManager fm = getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.images_preview, mImagesPreviewFragment);
ft.commit();
//if (mStatus != null) {
//displayStatus(mStatus);
//} else {
//getStatus(false);
//}
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (intent == null || mStatus == null) return;
switch (requestCode) {
case REQUEST_SET_COLOR: {
if (resultCode == Activity.RESULT_OK) if (intent != null && intent.getExtras() != null) {
final int color = intent.getIntExtra(Accounts.USER_COLOR, Color.TRANSPARENT);
setUserColor(getActivity(), mStatus.user_id, color);
updateUserColor();
}
break;
}
}
}
@Override
public void onClick(final View view) {
if (mStatus == null) return;
switch (view.getId()) {
case R.id.profile: {
openUserProfile(getActivity(), mStatus.account_id, mStatus.user_id, null);
break;
}
case R.id.follow: {
mService.createFriendship(mAccountId, mStatus.user_id);
break;
}
case R.id.in_reply_to: {
openConversation(getActivity(), mStatus.account_id, mStatus.status_id);
break;
}
case R.id.location_view: {
if (mStatus.location == null) return;
final ParcelableLocation location = mStatus.location;
if (location == null || !location.isValid()) return;
final Uri.Builder builder = new Uri.Builder();
builder.scheme(SCHEME_TWEETINGS);
builder.authority(AUTHORITY_MAP);
builder.appendQueryParameter(QUERY_PARAM_LAT, String.valueOf(location.latitude));
builder.appendQueryParameter(QUERY_PARAM_LNG, String.valueOf(location.longitude));
startActivity(new Intent(Intent.ACTION_VIEW, builder.build()));
break;
}
case R.id.retweet_view: {
openUserRetweetedStatus(getActivity(), mStatus.account_id, mStatus.retweet_id > 0 ? mStatus.retweet_id
: mStatus.status_id);
break;
}
}
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.view_status, container, false);
mStatusContent = view.findViewById(R.id.content);
mStatusLoadProgress = (ProgressBar) view.findViewById(R.id.status_load_progress);
mUserColorLabel = view.findViewById(R.id.user_color_label);
mContentScroller = view.findViewById(R.id.content_scroller);
mImagesPreviewContainer = view.findViewById(R.id.images_preview);
mLocationView = (TextView) view.findViewById(R.id.location_view);
mRetweetedStatusView = (TextView) view.findViewById(R.id.retweet_view);
mNameView = (TextView) view.findViewById(R.id.name);
mScreenNameView = (TextView) view.findViewById(R.id.screen_name);
mTextView = (TextView) view.findViewById(R.id.text);
mProfileImageView = (ImageView) view.findViewById(R.id.profile_image);
mTimeAndSourceView = (TextView) view.findViewById(R.id.time_source);
mInReplyToView = (TextView) view.findViewById(R.id.in_reply_to);
mFollowButton = (Button) view.findViewById(R.id.follow);
mFollowIndicator = view.findViewById(R.id.follow_indicator);
mFollowInfoProgress = (ProgressBar) view.findViewById(R.id.follow_info_progress);
mProfileView = view.findViewById(R.id.profile);
mMenuBar = (MenuBar) view.findViewById(R.id.menu_bar);
mConversationView = (RelativeLayout) view.findViewById(R.id.conversation);
mMarketView = (RelativeLayout) view.findViewById(R.id.market);
return view;
}
@Override
public void onDestroyView() {
mStatus = null;
mAccountId = -1;
mStatusId = -1;
if (mGetStatusTask != null) {
mGetStatusTask.cancel(true);
}
if (mFollowInfoTask != null) {
mFollowInfoTask.cancel(true);
}
if (mLocationInfoTask != null) {
mLocationInfoTask.cancel(true);
}
if (mPlayInfoTask != null) {
mPlayInfoTask.cancel(true);
}
super.onDestroyView();
}
@SuppressLint({ "NewApi", "NewApi", "NewApi" })
@Override
public boolean onMenuItemClick(final MenuItem item) {
if (mStatus == null) return false;
final String text_plain = mStatus.text_plain;
final String screen_name = mStatus.screen_name;
final String name = mStatus.name;
switch (item.getItemId()) {
case MENU_SHARE: {
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "@" + mStatus.screen_name + ": " + text_plain);
startActivity(Intent.createChooser(intent, getString(R.string.share)));
break;
}
case MENU_RETWEET: {
if (isMyRetweet(mStatus)) {
mService.destroyStatus(mAccountId, mStatus.retweet_id);
} else {
final long id_to_retweet = mStatus.is_retweet && mStatus.retweet_id > 0 ? mStatus.retweet_id
: mStatus.status_id;
mService.retweetStatus(mAccountId, id_to_retweet);
}
break;
}
case MENU_TRANSLATE: {
translate(mStatus);
break;
}
case MENU_QUOTE_REPLY: {
final Intent intent = new Intent(INTENT_ACTION_COMPOSE);
final Bundle bundle = new Bundle();
bundle.putLong(INTENT_KEY_ACCOUNT_ID, mAccountId);
bundle.putLong(INTENT_KEY_IN_REPLY_TO_ID, mStatusId);
bundle.putString(INTENT_KEY_IN_REPLY_TO_SCREEN_NAME, screen_name);
bundle.putString(INTENT_KEY_IN_REPLY_TO_NAME, name);
bundle.putBoolean(INTENT_KEY_IS_QUOTE, true);
bundle.putString(INTENT_KEY_TEXT, getQuoteStatus(getActivity(), screen_name, text_plain));
intent.putExtras(bundle);
startActivity(intent);
break;
}
case MENU_QUOTE: {
final Intent intent = new Intent(INTENT_ACTION_COMPOSE);
final Bundle bundle = new Bundle();
bundle.putLong(INTENT_KEY_ACCOUNT_ID, mAccountId);
bundle.putBoolean(INTENT_KEY_IS_QUOTE, true);
bundle.putString(INTENT_KEY_TEXT, getQuoteStatus(getActivity(), screen_name, text_plain));
intent.putExtras(bundle);
startActivity(intent);
break;
}
case MENU_ADD_TO_BUFFER: {
final Intent intent = new Intent(INTENT_ACTION_COMPOSE);
final Bundle bundle = new Bundle();
bundle.putLong(INTENT_KEY_ACCOUNT_ID, mAccountId);
bundle.putBoolean(INTENT_KEY_IS_BUFFER, true);
bundle.putString(INTENT_KEY_TEXT, getQuoteStatus(getActivity(), screen_name, text_plain));
intent.putExtras(bundle);
startActivity(intent);
break;
}
case MENU_REPLY: {
final Intent intent = new Intent(INTENT_ACTION_COMPOSE);
final Bundle bundle = new Bundle();
final List<String> mentions = new Extractor().extractMentionedScreennames(text_plain);
mentions.remove(screen_name);
mentions.add(0, screen_name);
bundle.putStringArray(INTENT_KEY_MENTIONS, mentions.toArray(new String[mentions.size()]));
bundle.putLong(INTENT_KEY_ACCOUNT_ID, mAccountId);
bundle.putLong(INTENT_KEY_IN_REPLY_TO_ID, mStatusId);
bundle.putString(INTENT_KEY_IN_REPLY_TO_TWEET, text_plain);
bundle.putString(INTENT_KEY_IN_REPLY_TO_SCREEN_NAME, screen_name);
bundle.putString(INTENT_KEY_IN_REPLY_TO_NAME, name);
intent.putExtras(bundle);
startActivity(intent);
break;
}
case MENU_FAV: {
if (mStatus.is_favorite) {
mService.destroyFavorite(mAccountId, mStatusId);
} else {
mService.createFavorite(mAccountId, mStatusId);
}
break;
}
case MENU_COPY_CLIPBOARD: {
final String textToCopy = "@" + mStatus.screen_name + ": " + mStatus.text_plain;
int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
android.text.ClipboardManager clipboard = (android.text.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(textToCopy);
} else {
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("Status", textToCopy);
clipboard.setPrimaryClip(clip);
}
Toast.makeText(getActivity(), R.string.text_copied, Toast.LENGTH_SHORT).show();
break;
}
case MENU_DELETE: {
mService.destroyStatus(mAccountId, mStatusId);
break;
}
case MENU_EXTENSIONS: {
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_OPEN_STATUS);
final Bundle extras = new Bundle();
extras.putParcelable(INTENT_KEY_STATUS, mStatus);
intent.putExtras(extras);
startActivity(Intent.createChooser(intent, getString(R.string.open_with_extensions)));
break;
}
case MENU_MUTE_SOURCE: {
final String source = HtmlEscapeHelper.unescape(mStatus.source);
if (source == null) return false;
final Uri uri = Filters.Sources.CONTENT_URI;
final ContentValues values = new ContentValues();
final SharedPreferences.Editor editor = getSharedPreferences(SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE).edit();
final ContentResolver resolver = getContentResolver();
values.put(Filters.TEXT, source);
resolver.delete(uri, Filters.TEXT + " = '" + source + "'", null);
resolver.insert(uri, values);
editor.putBoolean(PREFERENCE_KEY_ENABLE_FILTER, true).commit();
Toast.makeText(getActivity(), getString(R.string.source_muted, source), Toast.LENGTH_SHORT).show();
break;
}
case MENU_SET_COLOR: {
final Intent intent = new Intent(INTENT_ACTION_SET_COLOR);
startActivityForResult(intent, REQUEST_SET_COLOR);
break;
}
case MENU_CLEAR_COLOR: {
clearUserColor(getActivity(), mStatus.user_id);
updateUserColor();
break;
}
case MENU_RECENT_TWEETS: {
openUserTimeline(getActivity(), mAccountId, mStatus.user_id, mStatus.screen_name);
break;
}
case MENU_FIND_RETWEETS: {
openUserRetweetedStatus(getActivity(), mStatus.account_id, mStatus.retweet_id > 0 ? mStatus.retweet_id
: mStatus.status_id);
break;
}
default:
return false;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_FRIENDSHIP_CHANGED);
filter.addAction(BROADCAST_FAVORITE_CHANGED);
filter.addAction(BROADCAST_RETWEET_CHANGED);
filter.addAction(BROADCAST_TWITLONGER_EXPANDED);
registerReceiver(mStatusReceiver, filter);
if (mStatus != null) {
displayStatus(mStatus);
}
else {
getStatus(false);
}
updateUserColor();
}
@Override
public void onStop() {
unregisterReceiver(mStatusReceiver);
super.onStop();
}
protected void translate(final ParcelableStatus status) {
ThreadPolicy tp = ThreadPolicy.LAX;
StrictMode.setThreadPolicy(tp);
String language = Locale.getDefault().getLanguage();
String url = "http://api.microsofttranslator.com/v2/Http.svc/Translate?contentType=" + URLEncoder.encode("text/plain") + "&appId=" + BING_TRANSLATE_API_KEY + "&from=&to=" + language + "&text=";
url = url + URLEncoder.encode(status.text_plain);
try {
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(new HttpGet(url));
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);
}
String finalString = s.toString();
finalString = finalString.replace("<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">", "");
finalString = finalString.replace("</string>", "");
AlertDialog.Builder builder = new AlertDialog.Builder(this.getActivity());
builder.setTitle(getString(R.string.translate));
builder.setMessage(finalString);
builder.setCancelable(true);
builder.setPositiveButton(getString(R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
//Toast.makeText(getActivity(), finalString, Toast.LENGTH_LONG).show();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void getStatus(final boolean omit_intent_extra) {
if (mGetStatusTask != null) {
mGetStatusTask.cancel(true);
}
mGetStatusTask = new GetStatusTask(omit_intent_extra);
mGetStatusTask.execute();
}
private void showFollowInfo(final boolean force) {
if (mFollowInfoDisplayed && !force) return;
if (mFollowInfoTask != null) {
mFollowInfoTask.cancel(true);
}
mFollowInfoTask = new FollowInfoTask();
mFollowInfoTask.execute();
}
private void showLocationInfo(final boolean force) {
if (mLocationInfoDisplayed && !force) return;
if (mLocationInfoTask != null) {
mLocationInfoTask.cancel(true);
}
mLocationInfoTask = new LocationInfoTask();
mLocationInfoTask.execute();
}
private void updateUserColor() {
if (mUserColorLabel != null && mStatus != null) {
final Drawable d = mUserColorLabel.getBackground();
if (d != null) {
d.mutate().setColorFilter(getUserColor(getActivity(), mStatus.user_id), Mode.MULTIPLY);
mUserColorLabel.invalidate();
}
}
}
class FollowInfoTask extends AsyncTask<Void, Void, Response<Boolean>> {
@Override
protected Response<Boolean> doInBackground(Void... params) {
return isAllFollowing();
}
@Override
protected void onPostExecute(Response<Boolean> result) {
if (getActivity() == null) return;
if (result.exception == null) {
mFollowIndicator.setVisibility(result.value == null || result.value ? View.GONE : View.VISIBLE);
if (result.value != null) {
mFollowButton.setVisibility(result.value ? View.GONE : View.VISIBLE);
mFollowInfoDisplayed = true;
}
}
mFollowInfoProgress.setVisibility(View.GONE);
super.onPostExecute(result);
mFollowInfoTask = null;
}
@Override
protected void onPreExecute() {
if (getActivity() == null) return;
mFollowIndicator.setVisibility(View.VISIBLE);
mFollowButton.setVisibility(View.GONE);
mFollowInfoProgress.setVisibility(View.VISIBLE);
super.onPreExecute();
}
private Response<Boolean> isAllFollowing() {
if (mStatus == null) return new Response<Boolean>(null, null);
if (isMyActivatedAccount(getActivity(), mStatus.user_id)) return new Response<Boolean>(true, null);
final Twitter twitter = getTwitterInstance(getActivity(), mStatus.account_id, false);
if (twitter == null) return new Response<Boolean>(null, null);
try {
final Relationship result = twitter.showFriendship(mStatus.account_id, mStatus.user_id);
if (!result.isSourceFollowingTarget()) return new Response<Boolean>(false, null);
} catch (final TwitterException e) {
return new Response<Boolean>(null, e);
}
return new Response<Boolean>(null, null);
}
}
class GetStatusTask extends AsyncTask<Void, Void, Response<ParcelableStatus>> {
private final boolean omit_intent_extra;
public GetStatusTask(boolean omit_intent_extra) {
this.omit_intent_extra = omit_intent_extra;
}
@Override
protected Response<ParcelableStatus> doInBackground(Void... params) {
ParcelableStatus status = null;
if (!omit_intent_extra) {
status = getArguments().getParcelable(INTENT_KEY_STATUS);
if (status != null) return new Response<ParcelableStatus>(status, null);
}
status = findStatusInDatabases(getActivity(), mAccountId, mStatusId);
if (status != null) return new Response<ParcelableStatus>(status, null);
final Twitter twitter = getTwitterInstance(getActivity(), mAccountId, false);
try {
return new Response<ParcelableStatus>(new ParcelableStatus(twitter.showStatus(mStatusId), mAccountId,
false), null);
} catch (final TwitterException e) {
return new Response<ParcelableStatus>(null, e);
}
}
@Override
protected void onPostExecute(Response<ParcelableStatus> result) {
if (getActivity() == null) return;
if (result.value == null) {
showErrorToast(getActivity(), null, result.exception, true);
} else {
displayStatus(result.value);
mStatusLoadProgress.setVisibility(View.GONE);
mStatusContent.setVisibility(View.VISIBLE);
mStatusContent.setEnabled(true);
}
setProgressBarIndeterminateVisibility(false);
super.onPostExecute(result);
}
@Override
protected void onPreExecute() {
if (getActivity() == null) return;
mStatusLoadProgress.setVisibility(View.VISIBLE);
mStatusContent.setVisibility(View.INVISIBLE);
mStatusContent.setEnabled(false);
setProgressBarIndeterminateVisibility(true);
super.onPreExecute();
}
}
class LocationInfoTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
if (getActivity() == null || mStatus == null) return null;
final ParcelableLocation location = mStatus.location;
if (location == null) return null;
try {
final Geocoder coder = new Geocoder(getActivity());
final List<Address> addresses = coder.getFromLocation(location.latitude, location.longitude, 1);
if (addresses.size() == 1) {
final Address address = addresses.get(0);
final StringBuilder builder = new StringBuilder();
final int max_idx = address.getMaxAddressLineIndex();
for (int i = 0; i < max_idx; i++) {
builder.append(address.getAddressLine(i));
if (i != max_idx - 1) {
builder.append(", ");
}
}
return builder.toString();
}
} catch (final IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
if (result != null) {
mLocationView.setText(result);
mLocationInfoDisplayed = true;
} else {
mLocationView.setText(R.string.view_map);
mLocationInfoDisplayed = false;
}
super.onPostExecute(result);
}
}
class Response<T> {
public final T value;
public final TwitterException exception;
public Response(T value, TwitterException exception) {
this.value = value;
this.exception = exception;
}
}
private class PlayStoreInfoTask extends AsyncTask<Void, Void, String> {
// can use UI thread here
protected void onPreExecute() {
}
// automatically done on worker thread (separate from UI thread)
protected String doInBackground(final Void... args) {
Uri playUrl = Uri.parse(mStatus.play_package);
String packageId = playUrl.getQueryParameter("id");
String finalUrl = "http://dev.appaware.com/1/app/show.json?p=" + packageId + "&client_token=" + APPAWARE_CLIENT_TOKEN;
StringBuilder s = new StringBuilder();
try {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
response = httpclient.execute(new HttpGet(finalUrl));
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse;
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return s.toString();
}
// can use UI thread here
protected void onPostExecute(final String result) {
try {
JSONObject playObj = new JSONObject(result);
mAppAwareUrl = playObj.getString("url");
String name = playObj.getString("name");
String icon = playObj.getString("icon");
JSONArray screenshots = playObj.getJSONArray("screenshots");
String screenshot = screenshots.getString(0);
TextView playTitleView = (TextView) getView().findViewById(R.id.play_title);
playTitleView.setText(name);
ImageView playIconView = (ImageView) getView().findViewById(R.id.play_icon);
mLazyImageLoader.displayPreviewImage(playIconView, icon);
ImageView playSSView = (ImageView) getView().findViewById(R.id.play_screenshot);
mLazyImageLoader.displayPreviewImage(playSSView, screenshot);
ImageView playButtonView = (ImageView) getView().findViewById(R.id.play_button);
playButtonView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mStatus.play_package));
startActivity(browserIntent);
}
});
TextView playAttributionView = (TextView) getView().findViewById(R.id.play_attribution);
playAttributionView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mAppAwareUrl));
startActivity(browserIntent);
}
});
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}