de.vanita5.twittnuker.fragment.support.StatusFragment.java Source code

Java tutorial

Introduction

Here is the source code for de.vanita5.twittnuker.fragment.support.StatusFragment.java

Source

/*
 * Twittnuker - Twitter client for Android
 *
 * Copyright (C) 2013-2014 vanita5 <mail@vanita5.de>
 *
 * This program incorporates a modified version of Twidere.
 * Copyright (C) 2012-2014 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 de.vanita5.twittnuker.fragment.support;

import static android.text.TextUtils.isEmpty;
import static de.vanita5.twittnuker.util.UserColorNicknameUtils.clearUserColor;
import static de.vanita5.twittnuker.util.UserColorNicknameUtils.clearUserNickname;
import static de.vanita5.twittnuker.util.UserColorNicknameUtils.getUserColor;
import static de.vanita5.twittnuker.util.UserColorNicknameUtils.getUserNickname;
import static de.vanita5.twittnuker.util.UserColorNicknameUtils.setUserColor;
import static de.vanita5.twittnuker.util.Utils.findStatus;
import static de.vanita5.twittnuker.util.Utils.formatToLongTimeString;
import static de.vanita5.twittnuker.util.Utils.getAccountColor;
import static de.vanita5.twittnuker.util.Utils.getDefaultTextSize;
import static de.vanita5.twittnuker.util.Utils.getDisplayName;
import static de.vanita5.twittnuker.util.Utils.getLocalizedNumber;
import static de.vanita5.twittnuker.util.Utils.getMapStaticImageUri;
import static de.vanita5.twittnuker.util.Utils.getTwitterInstance;
import static de.vanita5.twittnuker.util.Utils.getUserTypeIconRes;
import static de.vanita5.twittnuker.util.Utils.isSameAccount;
import static de.vanita5.twittnuker.util.Utils.openImageDirectly;
import static de.vanita5.twittnuker.util.Utils.openMap;
import static de.vanita5.twittnuker.util.Utils.openStatus;
import static de.vanita5.twittnuker.util.Utils.openStatusFavoriters;
import static de.vanita5.twittnuker.util.Utils.openStatusReplies;
import static de.vanita5.twittnuker.util.Utils.openStatusRetweeters;
import static de.vanita5.twittnuker.util.Utils.openUserProfile;
import static de.vanita5.twittnuker.util.Utils.scrollListToPosition;
import static de.vanita5.twittnuker.util.Utils.setMenuForStatus;
import static de.vanita5.twittnuker.util.Utils.showErrorMessage;
import static de.vanita5.twittnuker.util.Utils.showOkMessage;
import static de.vanita5.twittnuker.util.Utils.startStatusShareChooser;
import static de.vanita5.twittnuker.util.Utils.retweet;
import static de.vanita5.twittnuker.util.Utils.favorite;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Color;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.text.Html;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.URLUtil;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import org.mariotaku.menucomponent.widget.MenuBar;
import org.mariotaku.refreshnow.widget.RefreshMode;

import de.vanita5.twittnuker.R;
import de.vanita5.twittnuker.activity.support.AccountSelectorActivity;
import de.vanita5.twittnuker.activity.support.ColorPickerDialogActivity;
import de.vanita5.twittnuker.activity.support.LinkHandlerActivity;
import de.vanita5.twittnuker.adapter.ParcelableStatusesAdapter;
import de.vanita5.twittnuker.adapter.iface.IStatusesAdapter;
import de.vanita5.twittnuker.app.TwittnukerApplication;
import de.vanita5.twittnuker.menu.TwidereMenuInflater;
import de.vanita5.twittnuker.model.Account;
import de.vanita5.twittnuker.model.Account.AccountWithCredentials;
import de.vanita5.twittnuker.model.Panes;
import de.vanita5.twittnuker.model.ParcelableLocation;
import de.vanita5.twittnuker.model.ParcelableMedia;
import de.vanita5.twittnuker.model.ParcelableStatus;
import de.vanita5.twittnuker.model.SingleResponse;
import de.vanita5.twittnuker.task.AsyncTask;
import de.vanita5.twittnuker.text.method.StatusContentMovementMethod;
import de.vanita5.twittnuker.util.AsyncTwitterWrapper;
import de.vanita5.twittnuker.util.ClipboardUtils;
import de.vanita5.twittnuker.util.FlymeUtils;
import de.vanita5.twittnuker.util.ImageLoaderWrapper;
import de.vanita5.twittnuker.util.MediaPreviewUtils;
import de.vanita5.twittnuker.util.MediaPreviewUtils.OnMediaClickListener;
import de.vanita5.twittnuker.util.OnLinkClickHandler;
import de.vanita5.twittnuker.util.ParseUtils;
import de.vanita5.twittnuker.util.ThemeUtils;
import de.vanita5.twittnuker.util.TwidereLinkify;
import de.vanita5.twittnuker.util.Utils;
import de.vanita5.twittnuker.view.ColorLabelRelativeLayout;
import de.vanita5.twittnuker.view.ExtendedFrameLayout;

import de.vanita5.twittnuker.view.StatusTextView;
import twitter4j.Relationship;
import twitter4j.Twitter;
import twitter4j.TwitterException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;

public class StatusFragment extends ParcelableStatusesListFragment implements OnClickListener, Panes.Right,
        OnMediaClickListener, OnSharedPreferenceChangeListener, ActionMode.Callback {

    private static final int LOADER_ID_STATUS = 1;
    private static final int LOADER_ID_FOLLOW = 2;
    private static final int LOADER_ID_LOCATION = 3;

    private ParcelableStatus mStatus;

    private Locale mLocale;

    private boolean mLoadMoreAutomatically, mLoadConversationsAutomatically;
    private boolean mFollowInfoDisplayed, mLocationInfoDisplayed;
    private boolean mStatusLoaderInitialized, mLocationLoaderInitialized;
    private boolean mFollowInfoLoaderInitialized;
    private boolean mShouldScroll;
    private SharedPreferences mPreferences;
    private AsyncTwitterWrapper mTwitterWrapper;
    private ImageLoaderWrapper mImageLoader;
    private Handler mHandler;
    private TextView mNameView, mScreenNameView, mTimeSourceView, mInReplyToView, mLocationView, mRepliesView;
    private TextView mRetweetsCountView, mFavoritesCountView;
    private StatusTextView mTextView;

    private ImageView mProfileImageView, mMapView;
    private Button mFollowButton;
    private Button mRetryButton;
    private View mMainContent, mFollowIndicator, mImagePreviewContainer, mLocationContainer,
            mLocationBackgroundView;
    private ColorLabelRelativeLayout mProfileView;
    private MenuBar mMenuBar;
    private ProgressBar mDetailsLoadProgress, mFollowInfoProgress;
    private LinearLayout mImagePreviewGrid;
    private View mHeaderView;
    private View mLoadImagesIndicator;
    private View mRetweetsContainer, mFavoritesContainer;
    private ExtendedFrameLayout mDetailsContainer;
    private ListView mListView;

    private LoadConversationTask mConversationTask;

    private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (getActivity() == null || !isAdded() || isDetached())
                return;
            final String action = intent.getAction();
            if (BROADCAST_FRIENDSHIP_CHANGED.equals(action)) {
                if (mStatus != null && mStatus.user_id == intent.getLongExtra(EXTRA_USER_ID, -1)
                        && intent.getBooleanExtra(EXTRA_SUCCEED, false)) {
                    showFollowInfo(true);
                }
            } else if (BROADCAST_FAVORITE_CHANGED.equals(action)) {
                final ParcelableStatus status = intent.getParcelableExtra(EXTRA_STATUS);
                if (mStatus != null && status != null
                        && isSameAccount(context, status.account_id, mStatus.account_id)
                        && status.id == getStatusId()) {
                    getStatus(true);
                }
            } else if (BROADCAST_RETWEET_CHANGED.equals(action)) {
                final long status_id = intent.getLongExtra(EXTRA_STATUS_ID, -1);
                if (status_id > 0 && status_id == getStatusId()) {
                    getStatus(true);
                }
            } else if (BROADCAST_HOTOTIN_EXPANDED.equals(action)) {
                final String expanded_status = intent.getStringExtra(EXTRA_HOTOTIN_EXPANDED_TEXT);
                Spanned expanded_text = Html.fromHtml(expanded_status);

                mTextView.setText(expanded_text);

                final TwidereLinkify linkify = new TwidereLinkify(
                        new OnLinkClickHandler(getActivity(), getMultiSelectManager()));
                linkify.setLinkTextColor(ThemeUtils.getUserLinkTextColor(getActivity()));
                linkify.applyAllLinks(mTextView, mStatus.account_id, mStatus.is_possibly_sensitive);
                setProgressBarIndeterminateVisibility(false);
            }
        }
    };

    private final LoaderCallbacks<SingleResponse<ParcelableStatus>> mStatusLoaderCallbacks = new LoaderCallbacks<SingleResponse<ParcelableStatus>>() {

        @Override
        public Loader<SingleResponse<ParcelableStatus>> onCreateLoader(final int id, final Bundle args) {
            mDetailsLoadProgress.setVisibility(View.VISIBLE);
            mMainContent.setVisibility(View.INVISIBLE);
            mRetryButton.setVisibility(View.GONE);
            mMainContent.setEnabled(false);
            setProgressBarIndeterminateVisibility(true);
            final boolean omitIntentExtra = args.getBoolean(EXTRA_OMIT_INTENT_EXTRA, true);
            final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
            final long statusId = args.getLong(EXTRA_STATUS_ID, -1);
            return new ParcelableStatusLoader(getActivity(), omitIntentExtra, getArguments(), accountId, statusId);
        }

        @Override
        public void onLoaderReset(final Loader<SingleResponse<ParcelableStatus>> loader) {

        }

        @Override
        public void onLoadFinished(final Loader<SingleResponse<ParcelableStatus>> loader,
                final SingleResponse<ParcelableStatus> data) {
            if (data.getData() == null) {
                // TODO
                mRetryButton.setVisibility(View.VISIBLE);
                showErrorMessage(getActivity(), getString(R.string.action_getting_status), data.getException(),
                        true);
            } else {
                mRetryButton.setVisibility(View.GONE);
                displayStatus(data.getData());
                mDetailsLoadProgress.setVisibility(View.GONE);
                mMainContent.setVisibility(View.VISIBLE);
                mMainContent.setEnabled(true);
            }
            setProgressBarIndeterminateVisibility(false);
        }

    };

    private final LoaderCallbacks<String> mLocationLoaderCallbacks = new LoaderCallbacks<String>() {

        @Override
        public Loader<String> onCreateLoader(final int id, final Bundle args) {
            return new LocationInfoLoader(getActivity(), mStatus != null ? mStatus.location : null);
        }

        @Override
        public void onLoaderReset(final Loader<String> loader) {

        }

        @Override
        public void onLoadFinished(final Loader<String> loader, final String data) {
            if (data != null) {
                mLocationView.setText(data);
                mLocationInfoDisplayed = true;
            } else {
                mLocationView.setText(R.string.view_map);
                mLocationInfoDisplayed = false;
            }
        }

    };

    private final LoaderCallbacks<SingleResponse<Boolean>> mFollowInfoLoaderCallbacks = new LoaderCallbacks<SingleResponse<Boolean>>() {

        @Override
        public Loader<SingleResponse<Boolean>> onCreateLoader(final int id, final Bundle args) {
            mFollowIndicator.setVisibility(View.VISIBLE);
            mFollowButton.setVisibility(View.GONE);
            mFollowInfoProgress.setVisibility(View.VISIBLE);
            return new FollowInfoLoader(getActivity(), mStatus);
        }

        @Override
        public void onLoaderReset(final Loader<SingleResponse<Boolean>> loader) {

        }

        @Override
        public void onLoadFinished(final Loader<SingleResponse<Boolean>> loader,
                final SingleResponse<Boolean> data) {
            if (!data.hasException()) {
                mFollowIndicator.setVisibility(!data.hasData() || data.getData() ? View.GONE : View.VISIBLE);
                if (data.getData() != null) {
                    mFollowButton.setVisibility(data.getData() ? View.GONE : View.VISIBLE);
                    mFollowInfoDisplayed = true;
                }
            }
            mFollowInfoProgress.setVisibility(View.GONE);
        }

    };

    private final OnMenuItemClickListener mMenuItemClickListener = new OnMenuItemClickListener() {

        @Override
        public boolean onMenuItemClick(final MenuItem item) {
            return handleMenuItemClick(item);
        }
    };

    public void displayStatus(final ParcelableStatus status) {
        final boolean status_unchanged = mStatus != null && status != null && status.equals(mStatus);
        if (!status_unchanged) {
            getListAdapter().setData(null);
        } else {
            setSelection(0);
        }
        if (mConversationTask != null && mConversationTask.getStatus() == AsyncTask.Status.RUNNING) {
            mConversationTask.cancel(true);
        }
        mStatus = status;
        if (!status_unchanged) {
            clearPreviewImages();
            hidePreviewImages();
        }
        if (status == null || getActivity() == null)
            return;
        final Bundle args = getArguments();
        args.putLong(EXTRA_ACCOUNT_ID, status.account_id);
        args.putLong(EXTRA_STATUS_ID, status.id);
        args.putParcelable(EXTRA_STATUS, status);
        if (shouldUseNativeMenu()) {
            getActivity().supportInvalidateOptionsMenu();
        } else {
            setMenuForStatus(getActivity(), mMenuBar.getMenu(), status);
            mMenuBar.show();
        }

        updateUserColor();
        mProfileView.drawEnd(getAccountColor(getActivity(), status.account_id));
        final boolean nickname_only = mPreferences.getBoolean(KEY_NICKNAME_ONLY, false);
        final boolean name_first = mPreferences.getBoolean(KEY_NAME_FIRST, true);
        final boolean display_image_preview = mPreferences.getBoolean(KEY_DISPLAY_IMAGE_PREVIEW, false);
        final String nick = getUserNickname(getActivity(), status.user_id, true);
        mNameView.setText(TextUtils.isEmpty(nick) ? status.user_name
                : nickname_only ? nick : getString(R.string.name_with_nickname, status.user_name, nick));
        mNameView.setCompoundDrawablesWithIntrinsicBounds(0, 0,
                getUserTypeIconRes(status.user_is_verified, status.user_is_protected), 0);
        mScreenNameView.setText("@" + status.user_screen_name);
        mTextView.setText(Html.fromHtml(status.text_html));
        final TwidereLinkify linkify = new TwidereLinkify(
                new OnLinkClickHandler(getActivity(), getMultiSelectManager()));
        linkify.setLinkTextColor(ThemeUtils.getUserLinkTextColor(getActivity()));
        linkify.applyAllLinks(mTextView, status.account_id, status.is_possibly_sensitive);
        mTextView.setMovementMethod(StatusContentMovementMethod.getInstance());
        mTextView.setCustomSelectionActionModeCallback(this);
        final String timeString = formatToLongTimeString(getActivity(), status.timestamp);
        final String sourceHtml = status.source;
        if (!isEmpty(timeString) && !isEmpty(sourceHtml)) {
            mTimeSourceView.setText(Html.fromHtml(getString(R.string.time_source, timeString, sourceHtml)));
        } else if (isEmpty(timeString) && !isEmpty(sourceHtml)) {
            mTimeSourceView.setText(Html.fromHtml(getString(R.string.source, sourceHtml)));
        } else if (!isEmpty(timeString) && isEmpty(sourceHtml)) {
            mTimeSourceView.setText(timeString);
        }
        mTimeSourceView.setMovementMethod(LinkMovementMethod.getInstance());

        final String in_reply_to = getDisplayName(getActivity(), status.in_reply_to_user_id,
                status.in_reply_to_name, status.in_reply_to_screen_name, name_first, nickname_only, true);
        mInReplyToView.setText(getString(R.string.in_reply_to, in_reply_to));

        if (mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true)) {
            mImageLoader.displayProfileImage(mProfileImageView, status.user_profile_image_url);
        } else {
            mProfileImageView.setImageResource(R.drawable.ic_profile_image_default);
        }
        mImagePreviewContainer
                .setVisibility(status.medias == null || status.medias.length == 0 ? View.GONE : View.VISIBLE);
        if (display_image_preview) {
            loadPreviewImages();
        }
        mRetweetsContainer.setVisibility(!status.user_is_protected ? View.VISIBLE : View.GONE);
        mRetweetsCountView.setText(getLocalizedNumber(mLocale, status.retweet_count));
        mFavoritesCountView.setText(getLocalizedNumber(mLocale, status.favorite_count));
        final ParcelableLocation location = status.location;
        final boolean is_valid_location = ParcelableLocation.isValidLocation(location);
        mLocationContainer.setVisibility(is_valid_location ? View.VISIBLE : View.GONE);
        if (display_image_preview) {
            mMapView.setVisibility(is_valid_location ? View.VISIBLE : View.GONE);
            mLocationBackgroundView.setVisibility(is_valid_location ? View.VISIBLE : View.GONE);
            mLocationView.setVisibility(View.VISIBLE);
            if (is_valid_location) {
                mHandler.post(new DisplayMapRunnable(location, mImageLoader, mMapView));
            } else {
                mMapView.setImageDrawable(null);
            }
        } else {
            mMapView.setVisibility(View.GONE);
            mLocationBackgroundView.setVisibility(View.GONE);
            mMapView.setImageDrawable(null);
            mLocationView.setVisibility(View.VISIBLE);
        }
        if (mLoadMoreAutomatically) {
            showFollowInfo(true);
            showLocationInfo(true);
            showConversation();
        } else if (mLoadConversationsAutomatically) {
            showConversation();
        } else {
            mFollowIndicator.setVisibility(View.GONE);
        }
        updateConversationInfo();
        scrollToStart();
    }

    @Override
    public Loader<List<ParcelableStatus>> newLoaderInstance(final Context context, final Bundle args) {
        return null;
    }

    @Override
    public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.copyUrl: {
            final int start = mTextView.getSelectionStart(), end = mTextView.getSelectionEnd();
            final SpannableString string = SpannableString.valueOf(mTextView.getText());
            final URLSpan[] spans = string.getSpans(start, end, URLSpan.class);
            if (spans == null || spans.length != 1)
                return true;
            ClipboardUtils.setText(getActivity(), spans[0].getURL());
            mode.finish();
            return true;
        }
        }
        return false;
    }

    @Override
    public void onActivityCreated(final Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mLocale = getResources().getConfiguration().locale;
        setRefreshMode(shouldEnablePullToRefresh() ? RefreshMode.BOTH : RefreshMode.NONE);
        setHasOptionsMenu(shouldUseNativeMenu());
        setListShownNoAnimation(true);
        mHandler = new Handler();
        mListView = getListView();
        getListAdapter().setGapDisallowed(true);
        final TwittnukerApplication application = getApplication();
        mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
        getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE)
                .registerOnSharedPreferenceChangeListener(this);
        getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE)
                .registerOnSharedPreferenceChangeListener(this);
        mImageLoader = application.getImageLoaderWrapper();
        mTwitterWrapper = getTwitterWrapper();
        mLoadMoreAutomatically = mPreferences.getBoolean(KEY_LOAD_MORE_AUTOMATICALLY, false);
        mLoadConversationsAutomatically = mPreferences.getBoolean(KEY_LOAD_CONVERSATIONS_AUTOMATICALLY, true);
        mLoadImagesIndicator.setOnClickListener(this);
        mInReplyToView.setOnClickListener(this);
        mRepliesView.setOnClickListener(this);
        mFollowButton.setOnClickListener(this);
        mProfileView.setOnClickListener(this);
        mLocationContainer.setOnClickListener(this);
        mRetweetsContainer.setOnClickListener(this);
        mFavoritesContainer.setOnClickListener(this);
        mMenuBar.setVisibility(shouldUseNativeMenu() ? View.GONE : View.VISIBLE);
        mMenuBar.inflate(R.menu.menu_status);
        mMenuBar.setIsBottomBar(true);
        mMenuBar.setOnMenuItemClickListener(mMenuItemClickListener);
        getStatus(false);
    }

    @Override
    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        switch (requestCode) {
        case REQUEST_SET_COLOR: {
            if (mStatus == null)
                return;
            if (resultCode == Activity.RESULT_OK) {
                if (data == null)
                    return;
                final int color = data.getIntExtra(EXTRA_COLOR, Color.TRANSPARENT);
                setUserColor(getActivity(), mStatus.user_id, color);
            } else if (resultCode == ColorPickerDialogActivity.RESULT_CLEARED) {
                clearUserColor(getActivity(), mStatus.user_id);
            }
            break;
        }
        case REQUEST_SELECT_ACCOUNT: {
            if (mStatus == null)
                return;
            if (resultCode == Activity.RESULT_OK) {
                if (data == null || !data.hasExtra(EXTRA_ID))
                    return;
                final long accountId = data.getLongExtra(EXTRA_ID, -1);
                openStatus(getActivity(), accountId, mStatus.id);
            }
            break;
        }
        }
    }

    @Override
    public void onClick(final View view) {
        if (mStatus == null)
            return;
        final ParcelableStatus status = mStatus;
        switch (view.getId()) {
        case R.id.profile: {
            openUserProfile(getActivity(), status.account_id, status.user_id, null);
            break;
        }
        case R.id.follow: {
            mTwitterWrapper.createFriendshipAsync(status.account_id, status.user_id);
            break;
        }
        case R.id.in_reply_to: {
            showConversation();
            break;
        }
        case R.id.replies_view: {
            openStatusReplies(getActivity(), status.account_id, status.id, status.user_screen_name);
            break;
        }
        case R.id.location_container: {
            final ParcelableLocation location = status.location;
            if (!ParcelableLocation.isValidLocation(location))
                return;
            openMap(getActivity(), location.latitude, location.longitude);
            break;
        }
        case R.id.load_images: {
            if (status.is_possibly_sensitive) {
                final LoadSensitiveImageConfirmDialogFragment f = new LoadSensitiveImageConfirmDialogFragment();
                f.show(getChildFragmentManager(), "load_sensitive_image_confirmation");
            } else {
                loadPreviewImages();
            }
            break;
        }
        case R.id.retweets_container: {
            openStatusRetweeters(getActivity(), status.account_id,
                    status.retweet_id > 0 ? status.retweet_id : status.id);
            break;
        }
        case R.id.favorites_container: {
            // TODO
            final AccountWithCredentials account = Account.getAccountWithCredentials(getActivity(),
                    status.account_id);
            if (AccountWithCredentials.isOfficialCredentials(getActivity(), account)) {
                openStatusFavoriters(getActivity(), status.account_id,
                        status.retweet_id > 0 ? status.retweet_id : status.id);
            }
            break;
        }
        }

    }

    @Override
    public boolean onCreateActionMode(final ActionMode mode, final Menu menu) {
        final FragmentActivity a = getActivity();
        if (a == null)
            return false;
        a.getMenuInflater().inflate(R.menu.action_status_text_selection, menu);
        return true;
    }

    @Override
    public void onCreateOptionsMenu(final Menu menu, final TwidereMenuInflater inflater) {
        if (!shouldUseNativeMenu())
            return;
        inflater.inflate(R.menu.menu_status, menu);
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
            final Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.fragment_details_page, null, false);
        mMainContent = view.findViewById(R.id.content);
        mDetailsLoadProgress = (ProgressBar) view.findViewById(R.id.details_load_progress);
        mMenuBar = (MenuBar) view.findViewById(R.id.menu_bar);
        mDetailsContainer = (ExtendedFrameLayout) view.findViewById(R.id.details_container);
        mDetailsContainer.addView(super.onCreateView(inflater, container, savedInstanceState));
        mHeaderView = inflater.inflate(R.layout.header_status, null, false);
        mImagePreviewContainer = mHeaderView.findViewById(R.id.image_preview);
        mLocationContainer = mHeaderView.findViewById(R.id.location_container);
        mLocationView = (TextView) mHeaderView.findViewById(R.id.location_view);
        mLocationBackgroundView = mHeaderView.findViewById(R.id.location_background_view);
        mMapView = (ImageView) mHeaderView.findViewById(R.id.map_view);
        mNameView = (TextView) mHeaderView.findViewById(R.id.name);
        mScreenNameView = (TextView) mHeaderView.findViewById(R.id.screen_name);
        mTextView = (StatusTextView) mHeaderView.findViewById(R.id.text);
        mProfileImageView = (ImageView) mHeaderView.findViewById(R.id.profile_image);
        mTimeSourceView = (TextView) mHeaderView.findViewById(R.id.time_source);
        mInReplyToView = (TextView) mHeaderView.findViewById(R.id.in_reply_to);
        mRepliesView = (TextView) mHeaderView.findViewById(R.id.replies_view);
        mFollowButton = (Button) mHeaderView.findViewById(R.id.follow);
        mFollowIndicator = mHeaderView.findViewById(R.id.follow_indicator);
        mFollowInfoProgress = (ProgressBar) mHeaderView.findViewById(R.id.follow_info_progress);
        mProfileView = (ColorLabelRelativeLayout) mHeaderView.findViewById(R.id.profile);
        mImagePreviewGrid = (LinearLayout) mHeaderView.findViewById(R.id.image_grid);
        mRetweetsContainer = mHeaderView.findViewById(R.id.retweets_container);
        mFavoritesContainer = mHeaderView.findViewById(R.id.favorites_container);
        mRetweetsCountView = (TextView) mHeaderView.findViewById(R.id.retweets_count);
        mFavoritesCountView = (TextView) mHeaderView.findViewById(R.id.favorites_count);
        mLoadImagesIndicator = mHeaderView.findViewById(R.id.load_images);
        mRetryButton = (Button) view.findViewById(R.id.retry);
        final View cardView = mHeaderView.findViewById(R.id.card);
        ThemeUtils.applyThemeAlphaToDrawable(cardView.getContext(), cardView.getBackground());
        return view;
    }

    @Override
    public void onDestroyActionMode(final ActionMode mode) {
    }

    @Override
    public void onDestroyView() {
        mStatus = null;
        final LoaderManager lm = getLoaderManager();
        lm.destroyLoader(LOADER_ID_STATUS);
        lm.destroyLoader(LOADER_ID_LOCATION);
        lm.destroyLoader(LOADER_ID_FOLLOW);
        if (mConversationTask != null && mConversationTask.getStatus() == AsyncTask.Status.RUNNING) {
            mConversationTask.cancel(true);
        }
        super.onDestroyView();
    }

    @Override
    public void onItemsCleared() {

    }

    @Override
    public void onMediaClick(final View view, final ParcelableMedia media) {
        final ParcelableStatus status = mStatus;
        if (status == null)
            return;
        openImageDirectly(getActivity(), status.account_id, media.url);
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        if (!shouldUseNativeMenu() || mStatus == null)
            return false;
        return handleMenuItemClick(item);
    }

    @Override
    public boolean onPrepareActionMode(final ActionMode mode, final Menu menu) {
        final int start = mTextView.getSelectionStart(), end = mTextView.getSelectionEnd();
        final SpannableString string = SpannableString.valueOf(mTextView.getText());
        final URLSpan[] spans = string.getSpans(start, end, URLSpan.class);
        final boolean avail = spans != null && spans.length == 1 && URLUtil.isValidUrl(spans[0].getURL());
        Utils.setMenuItemAvailability(menu, android.R.id.copyUrl, avail);
        return false;
    }

    @Override
    public void onPrepareOptionsMenu(final Menu menu) {
        if (!shouldUseNativeMenu() || mStatus == null)
            return;
        setMenuForStatus(getActivity(), menu, mStatus);
    }

    @Override
    public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
            final int totalItemCount) {
    }

    @Override
    public void onScrollStateChanged(final AbsListView view, final int scrollState) {
        super.onScrollStateChanged(view, scrollState);
        mShouldScroll = false;
    }

    @Override
    public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
        if (mStatus == null || !ParseUtils.parseString(mStatus.user_id).equals(key))
            return;
        displayStatus(mStatus);
    }

    @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_HOTOTIN_EXPANDED);
        registerReceiver(mStatusReceiver, filter);
        updateUserColor();
        final int text_size = mPreferences.getInt(KEY_TEXT_SIZE, getDefaultTextSize(getActivity()));
        mTextView.setTextSize(text_size * 1.25f);
        mNameView.setTextSize(text_size * 1.25f);
        mScreenNameView.setTextSize(text_size * 0.85f);
        mTimeSourceView.setTextSize(text_size * 0.85f);
        mInReplyToView.setTextSize(text_size * 0.85f);
        mLocationView.setTextSize(text_size * 0.85f);
        //mRetweetView.setTextSize(text_size * 0.85f);
        mRepliesView.setTextSize(text_size * 0.85f);
    }

    @Override
    public void onStop() {
        unregisterReceiver(mStatusReceiver);
        super.onStop();
    }

    @Override
    public boolean scrollToStart() {
        if (mListView == null)
            return false;
        final IStatusesAdapter<List<ParcelableStatus>> adapter = getListAdapter();
        scrollListToPosition(mListView, adapter.getCount() + mListView.getFooterViewsCount() - 1, 0);
        return true;
    }

    // @Override
    // protected void setItemSelected(final ParcelableStatus status, final int
    // position, final boolean selected) {
    // final MultiSelectManager manager = getMultiSelectManager();
    // final Object only_item = manager.getCount() == 1 ?
    // manager.getSelectedItems().get(0) : null;
    // final boolean only_item_selected = only_item != null &&
    // !only_item.equals(mStatus);
    // mListView.setItemChecked(0, only_item_selected);
    // if (mStatus != null) {
    // if (only_item_selected) {
    // manager.selectItem(mStatus);
    // } else {
    // manager.unselectItem(mStatus);
    // }
    // }
    // super.setItemSelected(status, position, selected);
    // }

    @Override
    protected String[] getSavedStatusesFileArgs() {
        return null;
    }

    protected boolean handleMenuItemClick(final MenuItem item) {
        if (mStatus == null)
            return false;
        final ParcelableStatus status = mStatus;
        switch (item.getItemId()) {
        case MENU_SHARE: {
            startStatusShareChooser(getActivity(), status);
            break;
        }
        case MENU_COPY: {
            if (ClipboardUtils.setText(getActivity(), status.text_plain)) {
                showOkMessage(getActivity(), R.string.text_copied, false);
            }
            break;
        }
        case MENU_RETWEET: {
            retweet(status, mTwitterWrapper);
            break;
        }
        case MENU_QUOTE: {
            final Intent intent = new Intent(INTENT_ACTION_QUOTE);
            final Bundle bundle = new Bundle();
            bundle.putParcelable(EXTRA_STATUS, status);
            intent.putExtras(bundle);
            startActivity(intent);
            break;
        }
        case MENU_LOVE: {
            retweet(status, mTwitterWrapper);
            favorite(status, mTwitterWrapper);
            break;
        }
        case MENU_REPLY: {
            final Intent intent = new Intent(INTENT_ACTION_REPLY);
            final Bundle bundle = new Bundle();
            bundle.putParcelable(EXTRA_STATUS, status);
            intent.putExtras(bundle);
            startActivity(intent);
            break;
        }
        case MENU_FAVORITE: {
            favorite(status, mTwitterWrapper);
            break;
        }
        case MENU_DELETE: {
            DestroyStatusDialogFragment.show(getFragmentManager(), status);
            break;
        }
        case MENU_ADD_TO_FILTER: {
            AddStatusFilterDialogFragment.show(getFragmentManager(), status);
            break;
        }
        case MENU_SET_COLOR: {
            final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class);
            final int color = getUserColor(getActivity(), status.user_id, true);
            if (color != 0) {
                intent.putExtra(EXTRA_COLOR, color);
            }
            intent.putExtra(EXTRA_CLEAR_BUTTON, color != 0);
            intent.putExtra(EXTRA_ALPHA_SLIDER, false);
            startActivityForResult(intent, REQUEST_SET_COLOR);
            break;
        }
        case MENU_CLEAR_NICKNAME: {
            clearUserNickname(getActivity(), status.user_id);
            displayStatus(status);
            break;
        }
        case MENU_SET_NICKNAME: {
            final String nick = getUserNickname(getActivity(), status.user_id, true);
            SetUserNicknameDialogFragment.show(getFragmentManager(), status.user_id, nick);
            break;
        }
        case MENU_TRANSLATE: {
            final AccountWithCredentials account = Account.getAccountWithCredentials(getActivity(),
                    status.account_id);
            if (AccountWithCredentials.isOfficialCredentials(getActivity(), account)) {
                StatusTranslateDialogFragment.show(getFragmentManager(), status);
            } else {

            }
            break;
        }
        case MENU_OPEN_WITH_ACCOUNT: {
            final Intent intent = new Intent(INTENT_ACTION_SELECT_ACCOUNT);
            intent.setClass(getActivity(), AccountSelectorActivity.class);
            intent.putExtra(EXTRA_SINGLE_SELECTION, true);
            startActivityForResult(intent, REQUEST_SELECT_ACCOUNT);
            break;
        }
        default: {
            if (item.getIntent() != null) {
                try {
                    startActivity(item.getIntent());
                } catch (final ActivityNotFoundException e) {
                    if (Utils.isDebugBuild())
                        Log.w(LOGTAG, e);
                    return false;
                }
            }
            break;
        }
        }
        return true;
    }

    @Override
    protected void onReachedBottom() {

    }

    @Override
    protected void setItemSelected(final ParcelableStatus status, final int position, final boolean selected) {
    }

    @Override
    protected void setListHeaderFooters(final ListView list) {
        if (getActivity() == null || isDetached())
            return;
        list.addHeaderView(mHeaderView, null, true);
    }

    @Override
    protected boolean shouldEnablePullToRefresh() {
        return false;
    }

    @Override
    protected boolean shouldShowAccountColor() {
        return false;
    }

    private void addConversationStatus(final ParcelableStatus status) {
        if (getActivity() == null || isDetached())
            return;
        final List<ParcelableStatus> data = getData();
        if (data == null)
            return;
        data.add(status);
        final ParcelableStatusesAdapter adapter = (ParcelableStatusesAdapter) getListAdapter();
        adapter.setData(data);
        if (!mLoadMoreAutomatically && !mLoadConversationsAutomatically && mShouldScroll) {
            setSelection(0);
        }
    }

    private void clearPreviewImages() {
        mImagePreviewGrid.removeAllViews();
    }

    private void getStatus(final boolean omit_intent_extra) {
        final LoaderManager lm = getLoaderManager();
        lm.destroyLoader(LOADER_ID_STATUS);
        final Bundle args = new Bundle(getArguments());
        args.putBoolean(EXTRA_OMIT_INTENT_EXTRA, omit_intent_extra);
        if (!mStatusLoaderInitialized) {
            lm.initLoader(LOADER_ID_STATUS, args, mStatusLoaderCallbacks);
            mStatusLoaderInitialized = true;
        } else {
            lm.restartLoader(LOADER_ID_STATUS, args, mStatusLoaderCallbacks);
        }
    }

    private long getStatusId() {
        return mStatus != null ? mStatus.id : -1;
    }

    private void hidePreviewImages() {
        mLoadImagesIndicator.setVisibility(View.VISIBLE);
        mImagePreviewGrid.setVisibility(View.GONE);
    }

    private void loadPreviewImages() {
        if (mStatus == null)
            return;
        mLoadImagesIndicator.setVisibility(View.GONE);
        mImagePreviewGrid.setVisibility(View.VISIBLE);
        mImagePreviewGrid.removeAllViews();
        if (mStatus.medias != null) {
            final int maxColumns = getResources().getInteger(R.integer.grid_column_image_preview);
            MediaPreviewUtils.addToLinearLayout(mImagePreviewGrid, mImageLoader, mStatus.medias, maxColumns, this);
        }
    }

    private boolean shouldUseNativeMenu() {
        final boolean isInLinkHandler = getActivity() instanceof LinkHandlerActivity;
        return isInLinkHandler && FlymeUtils.hasSmartBar();
    }

    private void showConversation() {
        if (mConversationTask != null && mConversationTask.getStatus() == AsyncTask.Status.RUNNING) {
            mConversationTask.cancel(true);
            return;
        }
        final IStatusesAdapter<List<ParcelableStatus>> adapter = getListAdapter();
        final int count = adapter.getCount();
        final ParcelableStatus status;
        if (count == 0) {
            mShouldScroll = !mLoadMoreAutomatically && !mLoadConversationsAutomatically;
            status = mStatus;
        } else {
            status = adapter.getStatus(adapter.getCount() - 1);
        }
        if (status == null || status.in_reply_to_status_id <= 0)
            return;
        mConversationTask = new LoadConversationTask(this);
        mConversationTask.execute(status);
    }

    private void showFollowInfo(final boolean force) {
        if (mFollowInfoDisplayed && !force)
            return;
        final LoaderManager lm = getLoaderManager();
        lm.destroyLoader(LOADER_ID_FOLLOW);
        if (!mFollowInfoLoaderInitialized) {
            lm.initLoader(LOADER_ID_FOLLOW, null, mFollowInfoLoaderCallbacks);
            mFollowInfoLoaderInitialized = true;
        } else {
            lm.restartLoader(LOADER_ID_FOLLOW, null, mFollowInfoLoaderCallbacks);
        }
    }

    private void showLocationInfo(final boolean force) {
        if (mLocationInfoDisplayed && !force)
            return;
        final LoaderManager lm = getLoaderManager();
        lm.destroyLoader(LOADER_ID_LOCATION);
        if (!mLocationLoaderInitialized) {
            lm.initLoader(LOADER_ID_LOCATION, null, mLocationLoaderCallbacks);
            mLocationLoaderInitialized = true;
        } else {
            lm.restartLoader(LOADER_ID_LOCATION, null, mLocationLoaderCallbacks);
        }
    }

    private void updateConversationInfo() {
        final boolean has_converstion = mStatus != null && mStatus.in_reply_to_status_id > 0;
        final IStatusesAdapter<List<ParcelableStatus>> adapter = getListAdapter();
        final boolean load_not_finished = adapter.isEmpty()
                || adapter.getStatus(adapter.getCount() - 1).in_reply_to_status_id > 0;
        final boolean enable = has_converstion && load_not_finished;
        mInReplyToView.setVisibility(enable ? View.VISIBLE : View.GONE);
        mInReplyToView.setClickable(enable);
    }

    private void updateUserColor() {
        if (mStatus == null)
            return;
        mProfileView.drawStart(getUserColor(getActivity(), mStatus.user_id, true));
    }

    public static final class LoadSensitiveImageConfirmDialogFragment extends BaseSupportDialogFragment
            implements DialogInterface.OnClickListener {

        @Override
        public void onClick(final DialogInterface dialog, final int which) {
            switch (which) {
            case DialogInterface.BUTTON_POSITIVE: {
                final Fragment f = getParentFragment();
                if (f instanceof StatusFragment) {
                    ((StatusFragment) f).loadPreviewImages();
                }
                break;
            }
            }

        }

        @Override
        public Dialog onCreateDialog(final Bundle savedInstanceState) {
            final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
            final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
            builder.setTitle(android.R.string.dialog_alert_title);
            builder.setMessage(R.string.sensitive_content_warning);
            builder.setPositiveButton(android.R.string.ok, this);
            builder.setNegativeButton(android.R.string.cancel, null);
            return builder.create();
        }
    }

    private static class DisplayMapRunnable implements Runnable {
        private final ParcelableLocation mLocation;
        private final ImageLoaderWrapper mLoader;
        private final ImageView mView;

        DisplayMapRunnable(final ParcelableLocation location, final ImageLoaderWrapper loader,
                final ImageView view) {
            mLocation = location;
            mLoader = loader;
            mView = view;
        }

        @Override
        public void run() {
            final String uri = getMapStaticImageUri(mLocation.latitude, mLocation.longitude, mView);
            mLoader.displayPreviewImage(mView, uri);
        }
    }

    static class FollowInfoLoader extends AsyncTaskLoader<SingleResponse<Boolean>> {

        private final ParcelableStatus status;
        private final Context context;

        public FollowInfoLoader(final Context context, final ParcelableStatus status) {
            super(context);
            this.context = context;
            this.status = status;
        }

        @Override
        public SingleResponse<Boolean> loadInBackground() {
            return isAllFollowing();
        }

        @Override
        protected void onStartLoading() {
            forceLoad();
        }

        private SingleResponse<Boolean> isAllFollowing() {
            if (status == null)
                return SingleResponse.getInstance();
            if (status.user_id == status.account_id)
                return SingleResponse.getInstance(true);
            final Twitter twitter = getTwitterInstance(context, status.account_id, false);
            if (twitter == null)
                return SingleResponse.getInstance();
            try {
                final Relationship result = twitter.showFriendship(status.account_id, status.user_id);
                if (!result.isSourceFollowingTarget()) {
                    SingleResponse.getInstance(false);
                }
            } catch (final TwitterException e) {
                return SingleResponse.getInstance(e);
            }
            return SingleResponse.getInstance();
        }
    }

    static class ImagesAdapter extends BaseAdapter {

        private final List<ParcelableMedia> mImages = new ArrayList<ParcelableMedia>();
        private final ImageLoaderWrapper mImageLoader;
        private final LayoutInflater mInflater;

        public ImagesAdapter(final Context context) {
            mImageLoader = TwittnukerApplication.getInstance(context).getImageLoaderWrapper();
            mInflater = LayoutInflater.from(context);
        }

        public boolean addAll(final Collection<? extends ParcelableMedia> images) {
            final boolean ret = images != null && mImages.addAll(images);
            notifyDataSetChanged();
            return ret;
        }

        public void clear() {
            mImages.clear();
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mImages.size();
        }

        @Override
        public ParcelableMedia getItem(final int position) {
            return mImages.get(position);
        }

        @Override
        public long getItemId(final int position) {
            final ParcelableMedia spec = getItem(position);
            return spec != null ? spec.hashCode() : 0;
        }

        @Override
        public View getView(final int position, final View convertView, final ViewGroup parent) {
            final View view = convertView != null ? convertView
                    : mInflater.inflate(R.layout.gallery_item_image_preview, null);
            final ImageView image = (ImageView) view.findViewById(R.id.image);
            final ParcelableMedia spec = getItem(position);
            mImageLoader.displayPreviewImage(image, spec != null ? spec.media_url : null);
            return view;
        }

    }

    static class LoadConversationTask extends AsyncTask<ParcelableStatus, Void, SingleResponse<Boolean>> {

        final Handler handler;
        final Context context;
        final StatusFragment fragment;

        LoadConversationTask(final StatusFragment fragment) {
            context = fragment.getActivity();
            this.fragment = fragment;
            handler = new Handler();
        }

        @Override
        protected SingleResponse<Boolean> doInBackground(final ParcelableStatus... params) {
            if (params == null || params.length != 1)
                return new SingleResponse<Boolean>(false, null);
            try {
                final long account_id = params[0].account_id;
                ParcelableStatus status = params[0];
                while (status != null && status.in_reply_to_status_id > 0 && !isCancelled()) {
                    status = findStatus(context, account_id, status.in_reply_to_status_id);
                    if (status == null) {
                        break;
                    }
                    handler.post(new AddStatusRunnable(status));
                }
            } catch (final TwitterException e) {
                return new SingleResponse<Boolean>(false, e);
            }
            return new SingleResponse<Boolean>(true, null);
        }

        @Override
        protected void onCancelled() {
            fragment.setProgressBarIndeterminateVisibility(false);
            fragment.updateConversationInfo();
        }

        @Override
        protected void onPostExecute(final SingleResponse<Boolean> data) {
            fragment.setProgressBarIndeterminateVisibility(false);
            fragment.updateConversationInfo();
            if (data.getData() == null || !data.getData()) {
                showErrorMessage(context, context.getString(R.string.action_getting_status), data.getException(),
                        true);
            }
        }

        @Override
        protected void onPreExecute() {
            fragment.setProgressBarIndeterminateVisibility(true);
            fragment.updateConversationInfo();
        }

        class AddStatusRunnable implements Runnable {

            final ParcelableStatus status;

            AddStatusRunnable(final ParcelableStatus status) {
                this.status = status;
            }

            @Override
            public void run() {
                fragment.addConversationStatus(status);
            }
        }
    }

    static class LocationInfoLoader extends AsyncTaskLoader<String> {

        private final Context context;
        private final ParcelableLocation location;

        public LocationInfoLoader(final Context context, final ParcelableLocation location) {
            super(context);
            this.context = context;
            this.location = location;
        }

        @Override
        public String loadInBackground() {
            if (location == null)
                return null;
            try {
                final Geocoder coder = new Geocoder(context);
                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();
                    for (int i = 0, max_idx = address.getMaxAddressLineIndex(); 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 onStartLoading() {
            forceLoad();
        }

    }

    static class ParcelableStatusLoader extends AsyncTaskLoader<SingleResponse<ParcelableStatus>> {

        private final boolean mOmitIntentExtra;
        private final Bundle mExtras;
        private final long mAccountId, mStatusId;

        public ParcelableStatusLoader(final Context context, final boolean omitIntentExtra, final Bundle extras,
                final long accountId, final long statusId) {
            super(context);
            mOmitIntentExtra = omitIntentExtra;
            mExtras = extras;
            mAccountId = accountId;
            mStatusId = statusId;
        }

        @Override
        public SingleResponse<ParcelableStatus> loadInBackground() {
            if (!mOmitIntentExtra && mExtras != null) {
                final ParcelableStatus cache = mExtras.getParcelable(EXTRA_STATUS);
                if (cache != null)
                    return SingleResponse.getInstance(cache);
            }
            try {
                return SingleResponse.getInstance(findStatus(getContext(), mAccountId, mStatusId));
            } catch (final TwitterException e) {
                return SingleResponse.getInstance(e);
            }
        }

        @Override
        protected void onStartLoading() {
            forceLoad();
        }

    }

}