2014-07-03 07:48:39 +02:00
|
|
|
/*
|
2014-12-06 15:40:22 +01:00
|
|
|
* Twidere - Twitter client for Android
|
|
|
|
*
|
2014-07-03 07:48:39 +02:00
|
|
|
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
2014-12-06 15:40:22 +01:00
|
|
|
*
|
2014-07-03 07:48:39 +02:00
|
|
|
* 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.
|
2014-12-06 15:40:22 +01:00
|
|
|
*
|
2014-07-03 07:48:39 +02:00
|
|
|
* 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.
|
2014-12-06 15:40:22 +01:00
|
|
|
*
|
2014-07-03 07:48:39 +02:00
|
|
|
* 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 org.mariotaku.twidere.fragment.support;
|
|
|
|
|
2014-12-08 16:16:33 +01:00
|
|
|
import android.app.Activity;
|
2015-04-08 15:26:44 +02:00
|
|
|
import android.app.AlertDialog;
|
|
|
|
import android.app.Dialog;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.content.Context;
|
2015-04-08 15:26:44 +02:00
|
|
|
import android.content.DialogInterface;
|
2014-12-07 16:13:07 +01:00
|
|
|
import android.content.Intent;
|
2014-12-06 15:40:22 +01:00
|
|
|
import android.content.res.Resources;
|
2014-12-08 16:16:33 +01:00
|
|
|
import android.graphics.Color;
|
2015-01-03 16:16:50 +01:00
|
|
|
import android.graphics.Point;
|
2014-12-06 15:40:22 +01:00
|
|
|
import android.graphics.Rect;
|
2015-03-14 16:11:20 +01:00
|
|
|
import android.nfc.NdefMessage;
|
|
|
|
import android.nfc.NdefRecord;
|
|
|
|
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
|
|
|
|
import android.nfc.NfcEvent;
|
2015-03-29 20:19:25 +02:00
|
|
|
import android.os.AsyncTask;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.os.Bundle;
|
2015-04-08 15:26:44 +02:00
|
|
|
import android.support.annotation.NonNull;
|
2014-12-06 15:40:22 +01:00
|
|
|
import android.support.annotation.Nullable;
|
2014-12-07 16:13:07 +01:00
|
|
|
import android.support.v4.app.Fragment;
|
|
|
|
import android.support.v4.app.FragmentActivity;
|
2015-01-01 11:38:34 +01:00
|
|
|
import android.support.v4.app.FragmentManager;
|
|
|
|
import android.support.v4.app.FragmentTransaction;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
|
|
|
import android.support.v4.content.Loader;
|
2014-12-07 16:13:07 +01:00
|
|
|
import android.support.v4.util.Pair;
|
2015-01-17 19:58:29 +01:00
|
|
|
import android.support.v7.widget.ActionMenuView;
|
2014-12-06 15:40:22 +01:00
|
|
|
import android.support.v7.widget.CardView;
|
2015-03-24 16:40:47 +01:00
|
|
|
import android.support.v7.widget.FixedLinearLayoutManager;
|
2014-12-06 15:40:22 +01:00
|
|
|
import android.support.v7.widget.LinearLayoutManager;
|
2015-04-04 16:31:37 +02:00
|
|
|
import android.support.v7.widget.PopupMenu;
|
|
|
|
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
|
2014-12-06 15:40:22 +01:00
|
|
|
import android.support.v7.widget.RecyclerView;
|
|
|
|
import android.support.v7.widget.RecyclerView.Adapter;
|
|
|
|
import android.support.v7.widget.RecyclerView.LayoutParams;
|
|
|
|
import android.support.v7.widget.RecyclerView.ViewHolder;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.text.Html;
|
2015-04-03 23:12:33 +02:00
|
|
|
import android.text.SpannableString;
|
2015-04-08 20:37:05 +02:00
|
|
|
import android.text.Spanned;
|
2015-04-03 19:22:00 +02:00
|
|
|
import android.text.TextUtils;
|
2015-04-03 23:12:33 +02:00
|
|
|
import android.text.style.URLSpan;
|
|
|
|
import android.view.ActionMode;
|
|
|
|
import android.view.ActionMode.Callback;
|
2015-04-04 16:31:37 +02:00
|
|
|
import android.view.Gravity;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.view.LayoutInflater;
|
2015-04-03 23:12:33 +02:00
|
|
|
import android.view.Menu;
|
2015-01-17 19:58:29 +01:00
|
|
|
import android.view.MenuInflater;
|
2014-12-07 16:13:07 +01:00
|
|
|
import android.view.MenuItem;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.view.View;
|
|
|
|
import android.view.View.OnClickListener;
|
|
|
|
import android.view.ViewGroup;
|
2015-04-03 23:12:33 +02:00
|
|
|
import android.webkit.URLUtil;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.widget.ImageView;
|
2014-12-06 15:40:22 +01:00
|
|
|
import android.widget.Space;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
import org.mariotaku.twidere.R;
|
2015-04-03 23:12:33 +02:00
|
|
|
import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
2014-12-07 16:13:07 +01:00
|
|
|
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
|
2015-01-01 11:38:34 +01:00
|
|
|
import org.mariotaku.twidere.adapter.AbsStatusesAdapter.StatusAdapterListener;
|
2014-12-06 15:40:22 +01:00
|
|
|
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
|
|
|
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.app.TwidereApplication;
|
2015-01-01 11:38:34 +01:00
|
|
|
import org.mariotaku.twidere.constant.IntentConstants;
|
2015-01-06 16:46:07 +01:00
|
|
|
import org.mariotaku.twidere.loader.support.ParcelableStatusLoader;
|
2014-12-06 15:40:22 +01:00
|
|
|
import org.mariotaku.twidere.loader.support.StatusRepliesLoader;
|
|
|
|
import org.mariotaku.twidere.model.ListResponse;
|
2014-12-07 16:13:07 +01:00
|
|
|
import org.mariotaku.twidere.model.ParcelableAccount;
|
2014-12-13 16:14:47 +01:00
|
|
|
import org.mariotaku.twidere.model.ParcelableAccount.ParcelableCredentials;
|
2015-03-30 08:46:08 +02:00
|
|
|
import org.mariotaku.twidere.model.ParcelableLocation;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.model.ParcelableMedia;
|
|
|
|
import org.mariotaku.twidere.model.ParcelableStatus;
|
|
|
|
import org.mariotaku.twidere.model.SingleResponse;
|
|
|
|
import org.mariotaku.twidere.text.method.StatusContentMovementMethod;
|
2015-03-29 20:19:25 +02:00
|
|
|
import org.mariotaku.twidere.util.AsyncTaskUtils;
|
2014-12-07 16:13:07 +01:00
|
|
|
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
2015-04-03 23:12:33 +02:00
|
|
|
import org.mariotaku.twidere.util.ClipboardUtils;
|
2014-12-08 16:16:33 +01:00
|
|
|
import org.mariotaku.twidere.util.CompareUtils;
|
2015-03-14 16:11:20 +01:00
|
|
|
import org.mariotaku.twidere.util.LinkCreator;
|
2015-03-24 16:40:47 +01:00
|
|
|
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
2015-04-16 21:38:02 +02:00
|
|
|
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
2015-04-11 23:16:13 +02:00
|
|
|
import org.mariotaku.twidere.util.MenuUtils;
|
2015-03-30 14:24:51 +02:00
|
|
|
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
2015-04-06 18:42:09 +02:00
|
|
|
import org.mariotaku.twidere.util.StatusAdapterLinkClickHandler;
|
2015-01-23 17:09:03 +01:00
|
|
|
import org.mariotaku.twidere.util.StatusLinkClickHandler;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.util.ThemeUtils;
|
|
|
|
import org.mariotaku.twidere.util.TwidereLinkify;
|
2015-01-03 16:16:50 +01:00
|
|
|
import org.mariotaku.twidere.util.TwitterCardUtils;
|
2015-01-19 18:46:14 +01:00
|
|
|
import org.mariotaku.twidere.util.UserColorNameUtils;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.util.Utils;
|
2015-01-11 10:28:45 +01:00
|
|
|
import org.mariotaku.twidere.util.Utils.OnMediaClickListener;
|
2015-04-07 17:43:03 +02:00
|
|
|
import org.mariotaku.twidere.view.CardMediaContainer;
|
2015-04-08 11:47:34 +02:00
|
|
|
import org.mariotaku.twidere.view.ColorLabelRelativeLayout;
|
2015-04-07 18:36:54 +02:00
|
|
|
import org.mariotaku.twidere.view.ForegroundColorView;
|
2014-12-24 05:39:21 +01:00
|
|
|
import org.mariotaku.twidere.view.ShapedImageView;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.view.StatusTextView;
|
2015-01-03 16:16:50 +01:00
|
|
|
import org.mariotaku.twidere.view.TwitterCardContainer;
|
2015-01-01 11:38:34 +01:00
|
|
|
import org.mariotaku.twidere.view.holder.GapViewHolder;
|
2014-12-06 15:40:22 +01:00
|
|
|
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder;
|
|
|
|
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
2014-07-03 07:48:39 +02:00
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
import java.util.ArrayList;
|
2014-07-03 07:48:39 +02:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Locale;
|
|
|
|
|
2015-03-04 09:02:32 +01:00
|
|
|
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
2015-03-22 18:38:41 +01:00
|
|
|
import edu.tsinghua.spice.Utilies.TypeMappingUtil;
|
2014-07-28 12:42:48 +02:00
|
|
|
import twitter4j.TwitterException;
|
|
|
|
|
|
|
|
import static android.text.TextUtils.isEmpty;
|
2015-01-03 16:16:50 +01:00
|
|
|
import static org.mariotaku.twidere.util.UserColorNameUtils.clearUserColor;
|
|
|
|
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserNickname;
|
|
|
|
import static org.mariotaku.twidere.util.UserColorNameUtils.setUserColor;
|
2014-07-28 12:42:48 +02:00
|
|
|
import static org.mariotaku.twidere.util.Utils.findStatus;
|
|
|
|
import static org.mariotaku.twidere.util.Utils.formatToLongTimeString;
|
|
|
|
import static org.mariotaku.twidere.util.Utils.getLocalizedNumber;
|
|
|
|
import static org.mariotaku.twidere.util.Utils.getUserTypeIconRes;
|
2014-12-08 16:16:33 +01:00
|
|
|
import static org.mariotaku.twidere.util.Utils.openStatus;
|
2014-12-07 16:13:07 +01:00
|
|
|
import static org.mariotaku.twidere.util.Utils.openUserProfile;
|
2015-04-04 16:31:37 +02:00
|
|
|
import static org.mariotaku.twidere.util.Utils.setMenuForStatus;
|
2014-07-28 12:42:48 +02:00
|
|
|
import static org.mariotaku.twidere.util.Utils.showErrorMessage;
|
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
/**
|
|
|
|
* Created by mariotaku on 14/12/5.
|
|
|
|
*/
|
2015-04-03 23:12:33 +02:00
|
|
|
public class StatusFragment extends BaseSupportFragment implements LoaderCallbacks<SingleResponse<ParcelableStatus>>,
|
|
|
|
OnMediaClickListener, StatusAdapterListener {
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
private static final int LOADER_ID_DETAIL_STATUS = 1;
|
|
|
|
private static final int LOADER_ID_STATUS_REPLIES = 2;
|
2014-12-10 13:15:09 +01:00
|
|
|
private static final int STATE_LOADED = 1;
|
|
|
|
private static final int STATE_LOADING = 2;
|
|
|
|
private static final int STATE_ERROR = 3;
|
2014-12-06 15:40:22 +01:00
|
|
|
private RecyclerView mRecyclerView;
|
|
|
|
private StatusAdapter mStatusAdapter;
|
|
|
|
private boolean mRepliesLoaderInitialized;
|
|
|
|
private LoadConversationTask mLoadConversationTask;
|
2014-12-10 13:15:09 +01:00
|
|
|
private LinearLayoutManager mLayoutManager;
|
|
|
|
private View mStatusContent;
|
|
|
|
private View mProgressContainer;
|
|
|
|
private View mErrorContainer;
|
2015-01-06 16:46:07 +01:00
|
|
|
private DividerItemDecoration mItemDecoration;
|
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
private LoaderCallbacks<List<ParcelableStatus>> mRepliesLoaderCallback = new LoaderCallbacks<List<ParcelableStatus>>() {
|
2014-07-28 12:42:48 +02:00
|
|
|
@Override
|
2014-12-06 15:40:22 +01:00
|
|
|
public Loader<List<ParcelableStatus>> onCreateLoader(int id, Bundle args) {
|
|
|
|
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
|
|
|
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
|
|
|
final long statusId = args.getLong(EXTRA_STATUS_ID, -1);
|
|
|
|
final long maxId = args.getLong(EXTRA_MAX_ID, -1);
|
|
|
|
final long sinceId = args.getLong(EXTRA_SINCE_ID, -1);
|
2015-03-04 09:02:32 +01:00
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
final StatusRepliesLoader loader = new StatusRepliesLoader(getActivity(), accountId,
|
2015-01-17 19:58:29 +01:00
|
|
|
screenName, statusId, maxId, sinceId, null, null, 0, true);
|
2014-12-06 15:40:22 +01:00
|
|
|
loader.setComparator(ParcelableStatus.REVERSE_ID_COMPARATOR);
|
2015-03-04 09:02:32 +01:00
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
return loader;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-12-06 15:40:22 +01:00
|
|
|
public void onLoadFinished(Loader<List<ParcelableStatus>> loader, List<ParcelableStatus> data) {
|
2015-04-08 11:47:34 +02:00
|
|
|
final Pair<Long, Integer> readPosition = saveReadPosition();
|
2014-12-06 15:40:22 +01:00
|
|
|
setReplies(data);
|
2015-04-08 11:47:34 +02:00
|
|
|
restoreReadPosition(readPosition);
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-12-06 15:40:22 +01:00
|
|
|
public void onLoaderReset(Loader<List<ParcelableStatus>> loader) {
|
2014-07-28 12:42:48 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
};
|
2015-04-08 11:47:34 +02:00
|
|
|
|
|
|
|
private void restoreReadPosition(@Nullable Pair<Long, Integer> position) {
|
2015-04-08 20:37:05 +02:00
|
|
|
if (position == null) return;
|
|
|
|
final int adapterPosition = mStatusAdapter.findPositionById(position.first);
|
|
|
|
if (adapterPosition == RecyclerView.NO_POSITION) return;
|
|
|
|
mLayoutManager.scrollToPositionWithOffset(adapterPosition, position.second);
|
2015-04-08 11:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
private Pair<Long, Integer> saveReadPosition() {
|
|
|
|
final int position = mLayoutManager.findFirstVisibleItemPosition();
|
|
|
|
if (position == RecyclerView.NO_POSITION) return null;
|
2015-04-08 20:37:05 +02:00
|
|
|
long itemId = mStatusAdapter.getItemId(position);
|
|
|
|
final View positionView;
|
|
|
|
if (itemId == StatusAdapter.VIEW_TYPE_CONVERSATION_LOAD_INDICATOR) {
|
|
|
|
// Should be next item
|
|
|
|
positionView = mLayoutManager.findViewByPosition(position + 1);
|
|
|
|
itemId = mStatusAdapter.getItemId(position + 1);
|
|
|
|
} else {
|
|
|
|
positionView = mLayoutManager.findViewByPosition(position);
|
|
|
|
}
|
2015-04-08 11:47:34 +02:00
|
|
|
return new Pair<>(itemId, positionView != null ? positionView.getTop() : -1);
|
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private PopupMenu mPopupMenu;
|
|
|
|
private ParcelableStatus mSelectedStatus;
|
|
|
|
private OnMenuItemClickListener mOnStatusMenuItemClickListener = new OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
final ParcelableStatus status = mSelectedStatus;
|
|
|
|
if (status == null) return false;
|
|
|
|
return Utils.handleMenuItemClick(getActivity(), StatusFragment.this,
|
|
|
|
getFragmentManager(), getTwitterWrapper(), status, item);
|
|
|
|
}
|
|
|
|
};
|
2015-03-14 16:11:20 +01:00
|
|
|
|
2014-12-08 16:16:33 +01:00
|
|
|
@Override
|
|
|
|
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
|
|
|
switch (requestCode) {
|
|
|
|
case REQUEST_SET_COLOR: {
|
|
|
|
final ParcelableStatus status = mStatusAdapter.getStatus();
|
|
|
|
if (status == null) return;
|
|
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
|
|
if (data == null) return;
|
|
|
|
final int color = data.getIntExtra(EXTRA_COLOR, Color.TRANSPARENT);
|
|
|
|
setUserColor(getActivity(), status.user_id, color);
|
|
|
|
} else if (resultCode == ColorPickerDialogActivity.RESULT_CLEARED) {
|
|
|
|
clearUserColor(getActivity(), status.user_id);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case REQUEST_SELECT_ACCOUNT: {
|
|
|
|
final ParcelableStatus status = mStatusAdapter.getStatus();
|
|
|
|
if (status == 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, status.id);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
@Override
|
|
|
|
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
|
|
|
@Nullable final Bundle savedInstanceState) {
|
|
|
|
return inflater.inflate(R.layout.fragment_status, container, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
|
|
|
super.onActivityCreated(savedInstanceState);
|
|
|
|
final View view = getView();
|
|
|
|
if (view == null) throw new AssertionError();
|
|
|
|
final Context context = view.getContext();
|
|
|
|
final boolean compact = Utils.isCompactCards(context);
|
2015-03-15 15:40:45 +01:00
|
|
|
Utils.setNdefPushMessageCallback(getActivity(), new CreateNdefMessageCallback() {
|
|
|
|
@Override
|
|
|
|
public NdefMessage createNdefMessage(NfcEvent event) {
|
|
|
|
final ParcelableStatus status = getStatus();
|
|
|
|
if (status == null) return null;
|
|
|
|
return new NdefMessage(new NdefRecord[]{
|
|
|
|
NdefRecord.createUri(LinkCreator.getTwitterStatusLink(status.user_screen_name, status.id)),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2014-12-08 16:16:33 +01:00
|
|
|
mLayoutManager = new StatusListLinearLayoutManager(context, mRecyclerView);
|
2015-01-06 16:46:07 +01:00
|
|
|
mItemDecoration = new DividerItemDecoration(context, mLayoutManager.getOrientation());
|
2014-12-07 16:13:07 +01:00
|
|
|
if (compact) {
|
2015-01-06 16:46:07 +01:00
|
|
|
mRecyclerView.addItemDecoration(mItemDecoration);
|
2014-12-07 16:13:07 +01:00
|
|
|
}
|
|
|
|
mLayoutManager.setRecycleChildrenOnDetach(true);
|
|
|
|
mRecyclerView.setLayoutManager(mLayoutManager);
|
|
|
|
mRecyclerView.setClipToPadding(false);
|
|
|
|
mStatusAdapter = new StatusAdapter(this, compact);
|
2015-01-01 11:38:34 +01:00
|
|
|
mStatusAdapter.setEventListener(this);
|
2014-12-07 16:13:07 +01:00
|
|
|
mRecyclerView.setAdapter(mStatusAdapter);
|
|
|
|
|
2014-12-10 13:15:09 +01:00
|
|
|
setState(STATE_LOADING);
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
getLoaderManager().initLoader(LOADER_ID_DETAIL_STATUS, getArguments(), this);
|
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void onBaseViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
|
|
|
super.onBaseViewCreated(view, savedInstanceState);
|
|
|
|
mStatusContent = view.findViewById(R.id.status_content);
|
|
|
|
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
|
|
|
mProgressContainer = view.findViewById(R.id.progress_container);
|
|
|
|
mErrorContainer = view.findViewById(R.id.error_retry_container);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void fitSystemWindows(Rect insets) {
|
|
|
|
super.fitSystemWindows(insets);
|
|
|
|
final View view = getView();
|
|
|
|
if (view != null) {
|
|
|
|
view.setPadding(insets.left, insets.top, insets.right, insets.bottom);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-01 11:38:34 +01:00
|
|
|
@Override
|
|
|
|
public void onGapClick(GapViewHolder holder, int position) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-03-29 09:17:42 +02:00
|
|
|
@Override
|
|
|
|
public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) {
|
|
|
|
final ParcelableStatus status = mStatusAdapter.getStatus(position);
|
|
|
|
if (status == null) return;
|
|
|
|
Utils.openMedia(getActivity(), status, media);
|
2015-03-29 14:38:28 +02:00
|
|
|
SpiceProfilingUtil.log(getActivity(),
|
|
|
|
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
|
|
|
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
|
|
|
+ "," + mStatusAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
|
|
|
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
|
|
|
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
|
|
|
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
|
|
|
+ "," + mStatusAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
2015-03-29 09:17:42 +02:00
|
|
|
}
|
|
|
|
|
2015-01-01 11:38:34 +01:00
|
|
|
@Override
|
|
|
|
public void onStatusActionClick(StatusViewHolder holder, int id, int position) {
|
|
|
|
final ParcelableStatus status = mStatusAdapter.getStatus(position);
|
|
|
|
if (status == null) return;
|
|
|
|
switch (id) {
|
|
|
|
case R.id.reply_count: {
|
|
|
|
final Context context = getActivity();
|
|
|
|
final Intent intent = new Intent(IntentConstants.INTENT_ACTION_REPLY);
|
|
|
|
intent.setPackage(context.getPackageName());
|
|
|
|
intent.putExtra(IntentConstants.EXTRA_STATUS, status);
|
|
|
|
context.startActivity(intent);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.retweet_count: {
|
|
|
|
RetweetQuoteDialogFragment.show(getFragmentManager(), status);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.favorite_count: {
|
|
|
|
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
|
|
|
if (twitter == null) return;
|
|
|
|
if (status.is_favorite) {
|
|
|
|
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
|
|
|
} else {
|
|
|
|
twitter.createFavoriteAsync(status.account_id, status.id);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onStatusClick(StatusViewHolder holder, int position) {
|
|
|
|
openStatus(getActivity(), mStatusAdapter.getStatus(position), null);
|
|
|
|
}
|
|
|
|
|
2015-04-16 14:48:24 +02:00
|
|
|
@Override
|
|
|
|
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-01-01 11:38:34 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public void onStatusMenuClick(StatusViewHolder holder, View menuView, int position) {
|
2015-01-17 19:58:29 +01:00
|
|
|
//TODO show status menu
|
2015-04-04 16:31:37 +02:00
|
|
|
if (mPopupMenu != null) {
|
|
|
|
mPopupMenu.dismiss();
|
|
|
|
}
|
|
|
|
final PopupMenu popupMenu = new PopupMenu(mStatusAdapter.getContext(), menuView,
|
|
|
|
Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0);
|
|
|
|
popupMenu.setOnMenuItemClickListener(mOnStatusMenuItemClickListener);
|
|
|
|
popupMenu.inflate(R.menu.action_status);
|
|
|
|
final ParcelableStatus status = mStatusAdapter.getStatus(position);
|
|
|
|
setMenuForStatus(mStatusAdapter.getContext(), popupMenu.getMenu(), status);
|
|
|
|
popupMenu.show();
|
|
|
|
mPopupMenu = popupMenu;
|
|
|
|
mSelectedStatus = status;
|
2015-04-05 19:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-01-01 11:38:34 +01:00
|
|
|
public Loader<SingleResponse<ParcelableStatus>> onCreateLoader(final int id, final Bundle args) {
|
|
|
|
final Bundle fragmentArgs = getArguments();
|
|
|
|
final long accountId = fragmentArgs.getLong(EXTRA_ACCOUNT_ID, -1);
|
|
|
|
final long statusId = fragmentArgs.getLong(EXTRA_STATUS_ID, -1);
|
|
|
|
return new ParcelableStatusLoader(getActivity(), false, fragmentArgs, accountId, statusId);
|
|
|
|
}
|
|
|
|
|
2014-12-08 16:16:33 +01:00
|
|
|
@Override
|
2014-12-10 13:15:09 +01:00
|
|
|
public void onMediaClick(View view, ParcelableMedia media, long accountId) {
|
2015-01-23 17:09:03 +01:00
|
|
|
final ParcelableStatus status = mStatusAdapter.getStatus();
|
|
|
|
if (status == null) return;
|
2015-03-12 16:04:45 +01:00
|
|
|
Utils.openMediaDirectly(getActivity(), accountId, status, media, status.media);
|
2015-03-04 09:02:32 +01:00
|
|
|
//spice
|
|
|
|
SpiceProfilingUtil.log(getActivity(),
|
2015-03-29 14:38:28 +02:00
|
|
|
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
|
|
|
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
|
|
|
+ "," + mStatusAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
|
|
|
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
|
|
|
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
|
|
|
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
|
|
|
+ "," + mStatusAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
2015-03-04 09:02:32 +01:00
|
|
|
//end
|
2014-12-08 16:16:33 +01:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private void addConversation(ParcelableStatus status, int position) {
|
|
|
|
mStatusAdapter.addConversation(status, position);
|
2015-01-01 11:38:34 +01:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private DividerItemDecoration getItemDecoration() {
|
|
|
|
return mItemDecoration;
|
2015-01-01 11:38:34 +01:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private ParcelableStatus getStatus() {
|
|
|
|
return mStatusAdapter.getStatus();
|
2015-04-05 19:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-12-06 15:40:22 +01:00
|
|
|
public void onLoadFinished(final Loader<SingleResponse<ParcelableStatus>> loader,
|
|
|
|
final SingleResponse<ParcelableStatus> data) {
|
|
|
|
if (data.hasData()) {
|
2014-12-08 16:16:33 +01:00
|
|
|
final long itemId = mStatusAdapter.getItemId(mLayoutManager.findFirstVisibleItemPosition());
|
|
|
|
final View firstChild = mLayoutManager.getChildAt(0);
|
|
|
|
final int top = firstChild != null ? firstChild.getTop() : 0;
|
2014-12-06 15:40:22 +01:00
|
|
|
final ParcelableStatus status = data.getData();
|
2014-12-08 16:16:33 +01:00
|
|
|
if (mStatusAdapter.setStatus(status)) {
|
|
|
|
mLayoutManager.scrollToPositionWithOffset(1, 0);
|
|
|
|
mStatusAdapter.setConversation(null);
|
|
|
|
mStatusAdapter.setReplies(null);
|
|
|
|
loadReplies(status);
|
|
|
|
loadConversation(status);
|
|
|
|
} else {
|
|
|
|
final int position = mStatusAdapter.findPositionById(itemId);
|
|
|
|
mLayoutManager.scrollToPositionWithOffset(position, top);
|
|
|
|
}
|
2014-12-10 13:15:09 +01:00
|
|
|
setState(STATE_LOADED);
|
2014-12-06 15:40:22 +01:00
|
|
|
} else {
|
|
|
|
//TODO show errors
|
2014-12-10 13:15:09 +01:00
|
|
|
setState(STATE_ERROR);
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
private void loadConversation(ParcelableStatus status) {
|
2015-03-29 20:19:25 +02:00
|
|
|
if (AsyncTaskUtils.isTaskRunning(mLoadConversationTask)) {
|
2014-12-07 16:13:07 +01:00
|
|
|
mLoadConversationTask.cancel(true);
|
|
|
|
}
|
|
|
|
mLoadConversationTask = new LoadConversationTask(this);
|
2015-03-29 20:19:25 +02:00
|
|
|
AsyncTaskUtils.executeTask(mLoadConversationTask, status);
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
private void loadReplies(ParcelableStatus status) {
|
2014-07-28 12:42:48 +02:00
|
|
|
if (status == null) return;
|
2014-12-06 15:40:22 +01:00
|
|
|
final Bundle args = new Bundle();
|
|
|
|
args.putLong(EXTRA_ACCOUNT_ID, status.account_id);
|
2015-01-08 10:13:20 +01:00
|
|
|
args.putLong(EXTRA_STATUS_ID, status.retweet_id > 0 ? status.retweet_id : status.id);
|
2014-12-06 15:40:22 +01:00
|
|
|
args.putString(EXTRA_SCREEN_NAME, status.user_screen_name);
|
|
|
|
if (mRepliesLoaderInitialized) {
|
|
|
|
getLoaderManager().restartLoader(LOADER_ID_STATUS_REPLIES, args, mRepliesLoaderCallback);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
getLoaderManager().initLoader(LOADER_ID_STATUS_REPLIES, args, mRepliesLoaderCallback);
|
|
|
|
mRepliesLoaderInitialized = true;
|
2015-03-15 15:40:45 +01:00
|
|
|
//spice
|
2015-03-11 21:19:27 +01:00
|
|
|
if (status.media == null) {
|
2015-03-04 09:02:32 +01:00
|
|
|
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
2015-03-29 08:44:43 +02:00
|
|
|
status.id + ",Words," + status.account_id + "," + status.user_id + "," + status.reply_count
|
|
|
|
+ "," + status.retweet_count + "," + status.favorite_count
|
2015-03-14 16:11:20 +01:00
|
|
|
+ "," + status.text_plain.length() + "," + status.timestamp);
|
2015-03-29 08:44:43 +02:00
|
|
|
SpiceProfilingUtil.log(getActivity(), status.id + ",Words," + status.account_id + "," + status.user_id
|
|
|
|
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
2015-03-11 21:19:27 +01:00
|
|
|
+ "," + status.text_plain.length() + "," + status.timestamp);
|
2015-03-09 13:00:06 +01:00
|
|
|
} else {
|
2015-03-11 21:19:27 +01:00
|
|
|
for (final ParcelableMedia spiceMedia : status.media) {
|
2015-03-29 13:06:55 +02:00
|
|
|
if (spiceMedia.type == ParcelableMedia.TYPE_IMAGE) {
|
2015-03-11 21:19:27 +01:00
|
|
|
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
2015-03-29 08:44:43 +02:00
|
|
|
status.id + ",PreviewM," + status.account_id + "," + status.user_id
|
|
|
|
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
|
|
|
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(spiceMedia.type)
|
|
|
|
+ "," + spiceMedia.media_url + "," + spiceMedia.width + "x" + spiceMedia.height
|
|
|
|
+ "," + status.timestamp);
|
2015-03-11 21:19:27 +01:00
|
|
|
SpiceProfilingUtil.log(getActivity(),
|
2015-03-29 08:44:43 +02:00
|
|
|
status.id + ",PreviewM," + status.account_id + "," + status.user_id
|
|
|
|
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
|
|
|
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(spiceMedia.type)
|
|
|
|
+ "," + spiceMedia.media_url + "," + spiceMedia.width + "x" + spiceMedia.height
|
|
|
|
+ "," + status.timestamp);
|
2015-03-11 21:19:27 +01:00
|
|
|
} else {
|
|
|
|
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
2015-03-29 08:44:43 +02:00
|
|
|
status.id + ",PreviewO," + status.account_id + "," + status.user_id
|
|
|
|
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
|
|
|
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(spiceMedia.type)
|
|
|
|
+ "," + spiceMedia.media_url + "," + status.timestamp);
|
2015-03-11 21:19:27 +01:00
|
|
|
SpiceProfilingUtil.log(getActivity(),
|
2015-03-29 08:44:43 +02:00
|
|
|
status.id + ",PreviewO," + status.account_id + "," + status.user_id
|
|
|
|
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
|
|
|
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(spiceMedia.type)
|
|
|
|
+ "," + spiceMedia.media_url + "," + status.timestamp);
|
2015-03-11 21:19:27 +01:00
|
|
|
}
|
|
|
|
}
|
2015-03-04 09:02:32 +01:00
|
|
|
}
|
|
|
|
//end
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
private void setConversation(List<ParcelableStatus> data) {
|
2015-04-08 11:47:34 +02:00
|
|
|
final Pair<Long, Integer> readPosition = saveReadPosition();
|
|
|
|
mStatusAdapter.setConversation(data);
|
|
|
|
restoreReadPosition(readPosition);
|
2014-12-07 16:13:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void setReplies(List<ParcelableStatus> data) {
|
|
|
|
if (mLayoutManager.getChildCount() != 0) {
|
|
|
|
final long itemId = mStatusAdapter.getItemId(mLayoutManager.findFirstVisibleItemPosition());
|
|
|
|
final int top = mLayoutManager.getChildAt(0).getTop();
|
|
|
|
mStatusAdapter.setReplies(data);
|
|
|
|
final int position = mStatusAdapter.findPositionById(itemId);
|
|
|
|
mLayoutManager.scrollToPositionWithOffset(position, top);
|
|
|
|
} else {
|
|
|
|
mStatusAdapter.setReplies(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-01 11:38:34 +01:00
|
|
|
private void setState(int state) {
|
|
|
|
mStatusContent.setVisibility(state == STATE_LOADED ? View.VISIBLE : View.GONE);
|
|
|
|
mProgressContainer.setVisibility(state == STATE_LOADING ? View.VISIBLE : View.GONE);
|
|
|
|
mErrorContainer.setVisibility(state == STATE_ERROR ? View.VISIBLE : View.GONE);
|
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private static class DetailStatusViewHolder extends ViewHolder implements OnClickListener,
|
|
|
|
ActionMenuView.OnMenuItemClickListener {
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private final StatusAdapter adapter;
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private final CardView cardView;
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private final ActionMenuView menuBar;
|
|
|
|
private final TextView nameView, screenNameView;
|
|
|
|
private final StatusTextView textView;
|
2015-04-07 18:36:54 +02:00
|
|
|
private final TextView quoteTextView;
|
|
|
|
private final TextView quotedNameView, quotedScreenNameView;
|
2015-04-04 16:31:37 +02:00
|
|
|
private final ShapedImageView profileImageView;
|
|
|
|
private final ImageView profileTypeView;
|
|
|
|
private final TextView timeSourceView;
|
|
|
|
private final TextView retweetedByView;
|
|
|
|
private final View repliesContainer, retweetsContainer, favoritesContainer;
|
|
|
|
private final TextView repliesCountView, retweetsCountView, favoritesCountView;
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-08 11:47:34 +02:00
|
|
|
private final ColorLabelRelativeLayout profileContainer;
|
2015-04-04 16:31:37 +02:00
|
|
|
private final View retweetedByContainer;
|
|
|
|
private final View mediaPreviewContainer;
|
|
|
|
private final View mediaPreviewLoad;
|
2015-04-07 17:43:03 +02:00
|
|
|
private final CardMediaContainer mediaPreview;
|
2015-04-01 15:42:07 +02:00
|
|
|
|
2015-04-07 18:36:54 +02:00
|
|
|
private final View quotedNameContainer;
|
|
|
|
private final ForegroundColorView quoteIndicator;
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private final TextView locationView;
|
|
|
|
private final TwitterCardContainer twitterCard;
|
2015-04-07 18:36:54 +02:00
|
|
|
private final StatusLinkClickHandler linkClickHandler;
|
|
|
|
private final TwidereLinkify linkify;
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public DetailStatusViewHolder(StatusAdapter adapter, View itemView) {
|
|
|
|
super(itemView);
|
2015-04-07 18:36:54 +02:00
|
|
|
this.linkClickHandler = new StatusLinkClickHandler(adapter.getContext(), null);
|
|
|
|
this.linkify = new TwidereLinkify(linkClickHandler, false);
|
2015-04-04 16:31:37 +02:00
|
|
|
this.adapter = adapter;
|
|
|
|
cardView = (CardView) itemView.findViewById(R.id.card);
|
|
|
|
menuBar = (ActionMenuView) itemView.findViewById(R.id.menu_bar);
|
|
|
|
nameView = (TextView) itemView.findViewById(R.id.name);
|
|
|
|
screenNameView = (TextView) itemView.findViewById(R.id.screen_name);
|
|
|
|
textView = (StatusTextView) itemView.findViewById(R.id.text);
|
|
|
|
profileImageView = (ShapedImageView) itemView.findViewById(R.id.profile_image);
|
|
|
|
profileTypeView = (ImageView) itemView.findViewById(R.id.profile_type);
|
|
|
|
timeSourceView = (TextView) itemView.findViewById(R.id.time_source);
|
|
|
|
retweetedByView = (TextView) itemView.findViewById(R.id.retweeted_by);
|
|
|
|
retweetedByContainer = itemView.findViewById(R.id.retweeted_by_container);
|
|
|
|
repliesContainer = itemView.findViewById(R.id.replies_container);
|
|
|
|
retweetsContainer = itemView.findViewById(R.id.retweets_container);
|
|
|
|
favoritesContainer = itemView.findViewById(R.id.favorites_container);
|
|
|
|
repliesCountView = (TextView) itemView.findViewById(R.id.replies_count);
|
|
|
|
retweetsCountView = (TextView) itemView.findViewById(R.id.retweets_count);
|
|
|
|
favoritesCountView = (TextView) itemView.findViewById(R.id.favorites_count);
|
2015-04-07 17:43:03 +02:00
|
|
|
mediaPreviewContainer = itemView.findViewById(R.id.media_preview_container);
|
2015-04-04 16:31:37 +02:00
|
|
|
mediaPreviewLoad = itemView.findViewById(R.id.media_preview_load);
|
2015-04-07 17:43:03 +02:00
|
|
|
mediaPreview = (CardMediaContainer) itemView.findViewById(R.id.media_preview);
|
2015-04-04 16:31:37 +02:00
|
|
|
locationView = (TextView) itemView.findViewById(R.id.location_view);
|
2015-04-08 11:47:34 +02:00
|
|
|
profileContainer = (ColorLabelRelativeLayout) itemView.findViewById(R.id.profile_container);
|
2015-04-04 16:31:37 +02:00
|
|
|
twitterCard = (TwitterCardContainer) itemView.findViewById(R.id.twitter_card);
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-07 18:36:54 +02:00
|
|
|
quoteTextView = (TextView) itemView.findViewById(R.id.quote_text);
|
|
|
|
quotedNameView = (TextView) itemView.findViewById(R.id.quoted_name);
|
|
|
|
quotedScreenNameView = (TextView) itemView.findViewById(R.id.quoted_screen_name);
|
|
|
|
quotedNameContainer = itemView.findViewById(R.id.quoted_name_container);
|
|
|
|
quoteIndicator = (ForegroundColorView) itemView.findViewById(R.id.quote_indicator);
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
setIsRecyclable(false);
|
|
|
|
initViews();
|
2015-03-29 08:44:43 +02:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public void displayStatus(ParcelableStatus status) {
|
|
|
|
if (status == null) return;
|
|
|
|
final StatusFragment fragment = adapter.getFragment();
|
|
|
|
final Context context = adapter.getContext();
|
|
|
|
final Resources resources = context.getResources();
|
2015-04-16 14:48:24 +02:00
|
|
|
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
2015-04-04 16:31:37 +02:00
|
|
|
final boolean nameFirst = adapter.isNameFirst();
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-07 18:36:54 +02:00
|
|
|
linkClickHandler.setStatus(status);
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
if (status.retweet_id > 0) {
|
|
|
|
final String retweetedBy = UserColorNameUtils.getDisplayName(context, status.retweeted_by_id,
|
|
|
|
status.retweeted_by_name, status.retweeted_by_screen_name, nameFirst);
|
|
|
|
retweetedByView.setText(context.getString(R.string.name_retweeted, retweetedBy));
|
|
|
|
retweetedByContainer.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
retweetedByView.setText(null);
|
|
|
|
retweetedByContainer.setVisibility(View.GONE);
|
|
|
|
}
|
2014-12-07 16:13:07 +01:00
|
|
|
|
2015-04-08 11:47:34 +02:00
|
|
|
profileContainer.drawEnd(Utils.getAccountColor(context, status.account_id));
|
2015-04-08 08:33:07 +02:00
|
|
|
|
|
|
|
final int typeIconRes, typeDescriptionRes;
|
|
|
|
final long timestamp;
|
|
|
|
final String source;
|
2015-04-07 18:36:54 +02:00
|
|
|
if (status.is_quote) {
|
|
|
|
quotedNameView.setText(getUserNickname(context, status.user_id, status.user_name, true));
|
|
|
|
quotedScreenNameView.setText("@" + status.user_screen_name);
|
|
|
|
|
|
|
|
nameView.setText(getUserNickname(context, status.quoted_by_user_id, status.quoted_by_user_name, true));
|
|
|
|
screenNameView.setText("@" + status.quoted_by_user_screen_name);
|
|
|
|
|
2015-04-08 20:37:05 +02:00
|
|
|
final int idx = status.quote_text_unescaped.lastIndexOf(" twitter.com");
|
|
|
|
final Spanned quote_text = Html.fromHtml(status.quote_text_html);
|
2015-04-09 19:27:59 +02:00
|
|
|
quoteTextView.setText(idx > 0 ? quote_text.subSequence(0, idx) : quote_text);
|
2015-04-07 18:36:54 +02:00
|
|
|
linkify.applyAllLinks(quoteTextView, status.account_id, getLayoutPosition(),
|
|
|
|
status.is_possibly_sensitive, adapter.getLinkHighlightingStyle());
|
|
|
|
|
|
|
|
loader.displayProfileImage(profileImageView, status.quoted_by_user_profile_image);
|
|
|
|
|
|
|
|
quotedNameContainer.setVisibility(View.VISIBLE);
|
|
|
|
quoteTextView.setVisibility(View.VISIBLE);
|
|
|
|
quoteIndicator.setVisibility(View.VISIBLE);
|
|
|
|
|
2015-04-10 08:55:27 +02:00
|
|
|
quoteIndicator.setColor(UserColorNameUtils.getUserColor(context, status.user_id));
|
|
|
|
|
2015-04-08 11:47:34 +02:00
|
|
|
profileContainer.drawStart(UserColorNameUtils.getUserColor(context, status.quoted_by_user_id));
|
|
|
|
|
2015-04-08 08:33:07 +02:00
|
|
|
typeIconRes = getUserTypeIconRes(status.quoted_by_user_is_verified, status.quoted_by_user_is_protected);
|
|
|
|
typeDescriptionRes = Utils.getUserTypeDescriptionRes(status.quoted_by_user_is_verified, status.quoted_by_user_is_protected);
|
|
|
|
|
|
|
|
timestamp = status.quote_timestamp;
|
|
|
|
source = status.quote_source;
|
2015-04-08 11:47:34 +02:00
|
|
|
|
2015-04-07 18:36:54 +02:00
|
|
|
} else {
|
|
|
|
nameView.setText(getUserNickname(context, status.user_id, status.user_name, true));
|
|
|
|
screenNameView.setText("@" + status.user_screen_name);
|
|
|
|
|
|
|
|
loader.displayProfileImage(profileImageView, status.user_profile_image_url);
|
|
|
|
|
|
|
|
quotedNameContainer.setVisibility(View.GONE);
|
|
|
|
quoteTextView.setVisibility(View.GONE);
|
|
|
|
quoteIndicator.setVisibility(View.GONE);
|
2015-04-08 08:33:07 +02:00
|
|
|
|
2015-04-08 11:47:34 +02:00
|
|
|
profileContainer.drawStart(UserColorNameUtils.getUserColor(context, status.user_id));
|
|
|
|
|
2015-04-08 08:33:07 +02:00
|
|
|
typeIconRes = getUserTypeIconRes(status.user_is_verified, status.user_is_protected);
|
|
|
|
typeDescriptionRes = Utils.getUserTypeDescriptionRes(status.user_is_verified, status.user_is_protected);
|
|
|
|
|
|
|
|
timestamp = status.timestamp;
|
|
|
|
source = status.source;
|
2015-04-07 18:36:54 +02:00
|
|
|
}
|
2014-12-07 16:13:07 +01:00
|
|
|
|
2015-04-08 08:33:07 +02:00
|
|
|
if (typeIconRes != 0 && typeDescriptionRes != 0) {
|
|
|
|
profileTypeView.setImageResource(typeIconRes);
|
|
|
|
profileTypeView.setContentDescription(context.getString(typeDescriptionRes));
|
|
|
|
profileTypeView.setVisibility(View.VISIBLE);
|
|
|
|
} else {
|
|
|
|
profileTypeView.setImageDrawable(null);
|
|
|
|
profileTypeView.setContentDescription(null);
|
|
|
|
profileTypeView.setVisibility(View.GONE);
|
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-08 08:33:07 +02:00
|
|
|
final String timeString = formatToLongTimeString(context, timestamp);
|
|
|
|
if (!isEmpty(timeString) && !isEmpty(source)) {
|
|
|
|
timeSourceView.setText(Html.fromHtml(context.getString(R.string.time_source, timeString, source)));
|
|
|
|
} else if (isEmpty(timeString) && !isEmpty(source)) {
|
|
|
|
timeSourceView.setText(Html.fromHtml(context.getString(R.string.source, source)));
|
|
|
|
} else if (!isEmpty(timeString) && isEmpty(source)) {
|
2015-04-04 16:31:37 +02:00
|
|
|
timeSourceView.setText(timeString);
|
|
|
|
}
|
2015-04-08 11:47:34 +02:00
|
|
|
timeSourceView.setMovementMethod(null);
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-08 08:33:07 +02:00
|
|
|
|
|
|
|
textView.setText(Html.fromHtml(status.text_html));
|
|
|
|
linkify.applyAllLinks(textView, status.account_id, getAdapterPosition(), status.is_possibly_sensitive);
|
|
|
|
ThemeUtils.applyParagraphSpacing(textView, 1.1f);
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
if (!TextUtils.isEmpty(status.place_full_name)) {
|
|
|
|
locationView.setVisibility(View.VISIBLE);
|
|
|
|
locationView.setText(status.place_full_name);
|
|
|
|
locationView.setClickable(ParcelableLocation.isValidLocation(status.location));
|
|
|
|
} else if (ParcelableLocation.isValidLocation(status.location)) {
|
|
|
|
locationView.setVisibility(View.VISIBLE);
|
|
|
|
locationView.setText(R.string.view_map);
|
|
|
|
locationView.setClickable(true);
|
2014-12-06 15:40:22 +01:00
|
|
|
} else {
|
2015-04-04 16:31:37 +02:00
|
|
|
locationView.setVisibility(View.GONE);
|
|
|
|
locationView.setText(null);
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
retweetsContainer.setVisibility(!status.user_is_protected ? View.VISIBLE : View.GONE);
|
|
|
|
repliesContainer.setVisibility(status.reply_count < 0 ? View.GONE : View.VISIBLE);
|
|
|
|
final Locale locale = context.getResources().getConfiguration().locale;
|
|
|
|
repliesCountView.setText(getLocalizedNumber(locale, status.reply_count));
|
|
|
|
retweetsCountView.setText(getLocalizedNumber(locale, status.retweet_count));
|
|
|
|
favoritesCountView.setText(getLocalizedNumber(locale, status.favorite_count));
|
2015-01-10 16:17:02 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
|
|
|
|
if (status.media == null) {
|
|
|
|
mediaPreviewContainer.setVisibility(View.GONE);
|
2015-04-08 08:33:07 +02:00
|
|
|
mediaPreview.setVisibility(View.GONE);
|
|
|
|
mediaPreviewLoad.setVisibility(View.GONE);
|
|
|
|
mediaPreview.displayMedia();
|
2015-04-04 16:31:37 +02:00
|
|
|
} else if (adapter.isDetailMediaExpanded()) {
|
|
|
|
mediaPreviewContainer.setVisibility(View.VISIBLE);
|
2015-04-07 17:43:03 +02:00
|
|
|
mediaPreview.setVisibility(View.VISIBLE);
|
2015-04-08 08:33:07 +02:00
|
|
|
mediaPreviewLoad.setVisibility(View.GONE);
|
2015-04-07 17:43:03 +02:00
|
|
|
mediaPreview.displayMedia(status.media, loader, status.account_id,
|
2015-04-16 14:48:24 +02:00
|
|
|
adapter.getFragment(), adapter.getMediaLoadingHandler());
|
2015-04-04 16:31:37 +02:00
|
|
|
} else {
|
|
|
|
mediaPreviewContainer.setVisibility(View.VISIBLE);
|
2015-04-07 17:43:03 +02:00
|
|
|
mediaPreview.setVisibility(View.GONE);
|
2015-04-08 08:33:07 +02:00
|
|
|
mediaPreviewLoad.setVisibility(View.VISIBLE);
|
|
|
|
mediaPreview.displayMedia();
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (TwitterCardUtils.isCardSupported(status.card)) {
|
|
|
|
final Point size = TwitterCardUtils.getCardSize(status.card);
|
|
|
|
twitterCard.setVisibility(View.VISIBLE);
|
|
|
|
if (size != null) {
|
|
|
|
twitterCard.setCardSize(size.x, size.y);
|
|
|
|
} else {
|
|
|
|
twitterCard.setCardSize(0, 0);
|
|
|
|
}
|
|
|
|
final Fragment cardFragment = TwitterCardUtils.createCardFragment(status.card);
|
2015-04-09 19:39:51 +02:00
|
|
|
if (cardFragment != null) {
|
|
|
|
final FragmentManager fm = fragment.getChildFragmentManager();
|
|
|
|
final FragmentTransaction ft = fm.beginTransaction();
|
|
|
|
ft.replace(R.id.twitter_card, cardFragment);
|
|
|
|
ft.commit();
|
|
|
|
} else {
|
|
|
|
twitterCard.setVisibility(View.GONE);
|
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
} else {
|
|
|
|
twitterCard.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
Utils.setMenuForStatus(context, menuBar.getMenu(), status, adapter.getStatusAccount());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
2015-04-08 15:26:44 +02:00
|
|
|
final ParcelableStatus status = adapter.getStatus(getAdapterPosition());
|
|
|
|
final StatusFragment fragment = adapter.getFragment();
|
2015-04-04 16:31:37 +02:00
|
|
|
switch (v.getId()) {
|
|
|
|
case R.id.media_preview_load: {
|
2015-04-08 15:26:44 +02:00
|
|
|
if (adapter.isSensitiveContentEnabled() || !status.is_possibly_sensitive) {
|
|
|
|
adapter.setDetailMediaExpanded(true);
|
|
|
|
} else {
|
|
|
|
final LoadSensitiveImageConfirmDialogFragment f = new LoadSensitiveImageConfirmDialogFragment();
|
|
|
|
f.show(fragment.getChildFragmentManager(), "load_sensitive_image_confirm");
|
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.profile_container: {
|
|
|
|
final FragmentActivity activity = fragment.getActivity();
|
|
|
|
final Bundle activityOption = Utils.makeSceneTransitionOption(activity,
|
|
|
|
new Pair<View, String>(profileImageView, UserFragment.TRANSITION_NAME_PROFILE_IMAGE),
|
|
|
|
new Pair<View, String>(profileTypeView, UserFragment.TRANSITION_NAME_PROFILE_TYPE));
|
|
|
|
openUserProfile(activity, status.account_id, status.user_id, status.user_screen_name,
|
|
|
|
activityOption);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.retweets_container: {
|
|
|
|
final FragmentActivity activity = fragment.getActivity();
|
|
|
|
Utils.openStatusRetweeters(activity, status.account_id, status.id);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.retweeted_by_container: {
|
|
|
|
if (status.retweet_id > 0) {
|
2015-04-11 23:16:13 +02:00
|
|
|
Utils.openUserProfile(adapter.getContext(), status.account_id, status.retweeted_by_id,
|
|
|
|
status.retweeted_by_screen_name, null);
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case R.id.location_view: {
|
|
|
|
final ParcelableLocation location = status.location;
|
|
|
|
if (!ParcelableLocation.isValidLocation(location)) return;
|
|
|
|
Utils.openMap(adapter.getContext(), location.latitude, location.longitude);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
final StatusFragment fragment = adapter.getFragment();
|
|
|
|
final ParcelableStatus status = adapter.getStatus(getAdapterPosition());
|
|
|
|
if (status == null || fragment == null) return false;
|
|
|
|
final AsyncTwitterWrapper twitter = fragment.getTwitterWrapper();
|
|
|
|
final FragmentActivity activity = fragment.getActivity();
|
|
|
|
final FragmentManager fm = fragment.getFragmentManager();
|
2015-04-10 08:55:27 +02:00
|
|
|
if (item.getItemId() == MENU_RETWEET) {
|
|
|
|
RetweetQuoteDialogFragment.show(fm, status);
|
|
|
|
return true;
|
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
return Utils.handleMenuItemClick(activity, fragment, fm, twitter, status, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initViews() {
|
|
|
|
// menuBar.setOnMenuItemClickListener(this);
|
|
|
|
menuBar.setOnMenuItemClickListener(this);
|
|
|
|
final StatusFragment fragment = adapter.getFragment();
|
|
|
|
final FragmentActivity activity = fragment.getActivity();
|
|
|
|
final MenuInflater inflater = activity.getMenuInflater();
|
|
|
|
inflater.inflate(R.menu.menu_status, menuBar.getMenu());
|
|
|
|
ThemeUtils.wrapMenuIcon(menuBar, MENU_GROUP_STATUS_SHARE);
|
|
|
|
mediaPreviewLoad.setOnClickListener(this);
|
|
|
|
profileContainer.setOnClickListener(this);
|
|
|
|
retweetsContainer.setOnClickListener(this);
|
|
|
|
retweetedByContainer.setOnClickListener(this);
|
|
|
|
locationView.setOnClickListener(this);
|
|
|
|
|
|
|
|
final float defaultTextSize = adapter.getTextSize();
|
|
|
|
nameView.setTextSize(defaultTextSize * 1.25f);
|
2015-04-07 18:36:54 +02:00
|
|
|
quotedNameView.setTextSize(defaultTextSize * 1.25f);
|
2015-04-04 16:31:37 +02:00
|
|
|
textView.setTextSize(defaultTextSize * 1.25f);
|
2015-04-07 18:36:54 +02:00
|
|
|
quoteTextView.setTextSize(defaultTextSize * 1.25f);
|
2015-04-04 16:31:37 +02:00
|
|
|
screenNameView.setTextSize(defaultTextSize * 0.85f);
|
2015-04-07 18:36:54 +02:00
|
|
|
quotedScreenNameView.setTextSize(defaultTextSize * 0.85f);
|
2015-04-04 16:31:37 +02:00
|
|
|
locationView.setTextSize(defaultTextSize * 0.85f);
|
|
|
|
timeSourceView.setTextSize(defaultTextSize * 0.85f);
|
|
|
|
|
2015-04-08 08:33:07 +02:00
|
|
|
mediaPreview.setStyle(adapter.getMediaPreviewStyle());
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
textView.setMovementMethod(StatusContentMovementMethod.getInstance());
|
2015-04-15 09:32:20 +02:00
|
|
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
2015-04-16 21:38:02 +02:00
|
|
|
quoteTextView.setCustomSelectionActionModeCallback(new StatusActionModeCallback(quoteTextView, fragment, activity));
|
|
|
|
textView.setCustomSelectionActionModeCallback(new StatusActionModeCallback(textView, fragment, activity));
|
2015-04-15 09:32:20 +02:00
|
|
|
// }
|
2015-04-07 18:36:54 +02:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
|
2015-04-07 18:36:54 +02:00
|
|
|
private static class StatusActionModeCallback implements Callback {
|
|
|
|
private final TextView textView;
|
|
|
|
private final StatusFragment fragment;
|
|
|
|
private final FragmentActivity activity;
|
|
|
|
|
|
|
|
public StatusActionModeCallback(TextView textView, StatusFragment fragment, FragmentActivity activity) {
|
|
|
|
this.textView = textView;
|
|
|
|
this.fragment = fragment;
|
|
|
|
this.activity = activity;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
|
|
|
mode.getMenuInflater().inflate(R.menu.action_status_text_selection, menu);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
|
|
|
final int start = textView.getSelectionStart(), end = textView.getSelectionEnd();
|
|
|
|
final SpannableString string = SpannableString.valueOf(textView.getText());
|
|
|
|
final URLSpan[] spans = string.getSpans(start, end, URLSpan.class);
|
|
|
|
final boolean avail = spans.length == 1 && URLUtil.isValidUrl(spans[0].getURL());
|
2015-04-11 23:16:13 +02:00
|
|
|
MenuUtils.setMenuItemAvailability(menu, android.R.id.copyUrl, avail);
|
2015-04-07 18:36:54 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case android.R.id.copyUrl: {
|
2015-04-04 16:31:37 +02:00
|
|
|
final int start = textView.getSelectionStart(), end = textView.getSelectionEnd();
|
|
|
|
final SpannableString string = SpannableString.valueOf(textView.getText());
|
|
|
|
final URLSpan[] spans = string.getSpans(start, end, URLSpan.class);
|
2015-04-07 18:36:54 +02:00
|
|
|
if (spans.length != 1) return true;
|
|
|
|
ClipboardUtils.setText(activity, spans[0].getURL());
|
|
|
|
mode.finish();
|
2015-04-04 16:31:37 +02:00
|
|
|
return true;
|
|
|
|
}
|
2015-04-07 18:36:54 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
|
2015-04-07 18:36:54 +02:00
|
|
|
@Override
|
|
|
|
public void onDestroyActionMode(ActionMode mode) {
|
2015-04-04 16:31:37 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2015-04-09 21:22:25 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
|
|
|
|
2015-04-08 15:26:44 +02:00
|
|
|
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) {
|
|
|
|
final StatusAdapter adapter = ((StatusFragment) f).getAdapter();
|
|
|
|
adapter.setDetailMediaExpanded(true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@NonNull
|
|
|
|
@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 StatusAdapter getAdapter() {
|
|
|
|
return mStatusAdapter;
|
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
static class LoadConversationTask extends AsyncTask<ParcelableStatus, ParcelableStatus,
|
|
|
|
ListResponse<ParcelableStatus>> {
|
|
|
|
|
|
|
|
final Context context;
|
|
|
|
final StatusFragment fragment;
|
|
|
|
|
|
|
|
LoadConversationTask(final StatusFragment fragment) {
|
|
|
|
context = fragment.getActivity();
|
|
|
|
this.fragment = fragment;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected ListResponse<ParcelableStatus> doInBackground(final ParcelableStatus... params) {
|
|
|
|
final ArrayList<ParcelableStatus> list = new ArrayList<>();
|
|
|
|
try {
|
|
|
|
ParcelableStatus status = params[0];
|
|
|
|
final long account_id = status.account_id;
|
|
|
|
while (status.in_reply_to_status_id > 0 && !isCancelled()) {
|
|
|
|
status = findStatus(context, account_id, status.in_reply_to_status_id);
|
|
|
|
publishProgress(status);
|
|
|
|
list.add(0, status);
|
|
|
|
}
|
|
|
|
} catch (final TwitterException e) {
|
|
|
|
return ListResponse.getListInstance(e);
|
|
|
|
}
|
|
|
|
return ListResponse.getListInstance(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostExecute(final ListResponse<ParcelableStatus> data) {
|
|
|
|
if (data.hasData()) {
|
|
|
|
fragment.setConversation(data.getData());
|
|
|
|
} else {
|
|
|
|
showErrorMessage(context, context.getString(R.string.action_getting_status), data.getException(), true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onProgressUpdate(ParcelableStatus... values) {
|
|
|
|
for (ParcelableStatus status : values) {
|
|
|
|
// fragment.addConversation(status, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onCancelled() {
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class SpaceViewHolder extends ViewHolder {
|
|
|
|
|
|
|
|
public SpaceViewHolder(View itemView) {
|
|
|
|
super(itemView);
|
|
|
|
}
|
2015-04-05 19:58:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public void onLoaderReset(final Loader<SingleResponse<ParcelableStatus>> loader) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-06 18:42:09 +02:00
|
|
|
private static class StatusAdapter extends Adapter<ViewHolder> implements IStatusesAdapter<List<ParcelableStatus>> {
|
2015-04-04 16:31:37 +02:00
|
|
|
|
|
|
|
private static final int VIEW_TYPE_DETAIL_STATUS = 0;
|
|
|
|
private static final int VIEW_TYPE_LIST_STATUS = 1;
|
|
|
|
private static final int VIEW_TYPE_CONVERSATION_LOAD_INDICATOR = 2;
|
|
|
|
private static final int VIEW_TYPE_REPLIES_LOAD_INDICATOR = 3;
|
|
|
|
private static final int VIEW_TYPE_SPACE = 4;
|
|
|
|
|
|
|
|
private final Context mContext;
|
|
|
|
private final StatusFragment mFragment;
|
|
|
|
private final LayoutInflater mInflater;
|
|
|
|
private final MediaLoaderWrapper mImageLoader;
|
2015-04-16 14:48:24 +02:00
|
|
|
private final MediaLoadingHandler mMediaLoadingHandler;
|
2015-04-06 18:42:09 +02:00
|
|
|
private final TwidereLinkify mTwidereLinkify;
|
2015-04-04 16:31:37 +02:00
|
|
|
|
|
|
|
private final boolean mNameFirst;
|
|
|
|
private final int mCardLayoutResource;
|
|
|
|
private final int mTextSize;
|
|
|
|
private final int mCardBackgroundColor;
|
|
|
|
private final boolean mIsCompact;
|
|
|
|
private final int mProfileImageStyle;
|
2015-04-05 19:58:10 +02:00
|
|
|
private final int mMediaPreviewStyle;
|
2015-04-06 18:42:09 +02:00
|
|
|
private final int mLinkHighligingStyle;
|
2015-04-04 16:31:37 +02:00
|
|
|
private final boolean mDisplayMediaPreview;
|
|
|
|
private final boolean mDisplayProfileImage;
|
2015-04-08 15:26:44 +02:00
|
|
|
private final boolean mSensitiveContentEnabled;
|
2015-04-08 18:33:10 +02:00
|
|
|
private final boolean mHideCardActions;
|
2015-04-04 16:31:37 +02:00
|
|
|
|
|
|
|
private boolean mLoadMoreSupported;
|
|
|
|
private boolean mLoadMoreIndicatorVisible;
|
|
|
|
|
|
|
|
private ParcelableStatus mStatus;
|
|
|
|
private ParcelableCredentials mStatusAccount;
|
|
|
|
private List<ParcelableStatus> mConversation, mReplies;
|
|
|
|
private boolean mDetailMediaExpanded;
|
|
|
|
private StatusAdapterListener mStatusAdapterListener;
|
|
|
|
private DetailStatusViewHolder mCachedHolder;
|
|
|
|
|
|
|
|
public StatusAdapter(StatusFragment fragment, boolean compact) {
|
|
|
|
final Context context = fragment.getActivity();
|
|
|
|
final Resources res = context.getResources();
|
|
|
|
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
|
|
|
|
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
|
|
|
mFragment = fragment;
|
|
|
|
mContext = context;
|
|
|
|
mInflater = LayoutInflater.from(context);
|
|
|
|
mImageLoader = TwidereApplication.getInstance(context).getMediaLoaderWrapper();
|
2015-04-16 14:48:24 +02:00
|
|
|
mMediaLoadingHandler = new MediaLoadingHandler(R.id.media_preview_progress);
|
2015-04-04 16:31:37 +02:00
|
|
|
mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context);
|
|
|
|
mNameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
|
|
|
|
mTextSize = preferences.getInt(KEY_TEXT_SIZE, res.getInteger(R.integer.default_text_size));
|
|
|
|
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
|
2015-04-05 19:58:10 +02:00
|
|
|
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
|
2015-04-06 18:42:09 +02:00
|
|
|
mLinkHighligingStyle = Utils.getLinkHighlightingStyleInt(preferences.getString(KEY_LINK_HIGHLIGHT_OPTION, null));
|
2015-04-04 16:31:37 +02:00
|
|
|
mIsCompact = compact;
|
|
|
|
mDisplayProfileImage = preferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
|
|
|
|
mDisplayMediaPreview = preferences.getBoolean(KEY_MEDIA_PREVIEW, false);
|
2015-04-08 15:26:44 +02:00
|
|
|
mSensitiveContentEnabled = preferences.getBoolean(KEY_DISPLAY_SENSITIVE_CONTENTS, false);
|
2015-04-08 18:33:10 +02:00
|
|
|
mHideCardActions = preferences.getBoolean(KEY_HIDE_CARD_ACTIONS, false);
|
2015-04-04 16:31:37 +02:00
|
|
|
if (compact) {
|
|
|
|
mCardLayoutResource = R.layout.card_item_status_compact;
|
|
|
|
} else {
|
|
|
|
mCardLayoutResource = R.layout.card_item_status;
|
|
|
|
}
|
2015-04-06 18:42:09 +02:00
|
|
|
mTwidereLinkify = new TwidereLinkify(new StatusAdapterLinkClickHandler<>(this));
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addConversation(ParcelableStatus status, int position) {
|
|
|
|
if (mConversation == null) {
|
|
|
|
mConversation = new ArrayList<>();
|
|
|
|
}
|
|
|
|
mConversation.add(position, status);
|
|
|
|
notifyDataSetChanged();
|
|
|
|
updateItemDecoration();
|
2014-12-10 13:15:09 +01:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public int findPositionById(long itemId) {
|
|
|
|
for (int i = 0, j = getItemCount(); i < j; i++) {
|
|
|
|
if (getItemId(i) == itemId) return i;
|
|
|
|
}
|
2015-04-08 20:37:05 +02:00
|
|
|
return RecyclerView.NO_POSITION;
|
2015-01-01 11:38:34 +01:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public StatusFragment getFragment() {
|
|
|
|
return mFragment;
|
2015-03-30 14:24:51 +02:00
|
|
|
}
|
|
|
|
|
2015-04-16 14:48:24 +02:00
|
|
|
public MediaLoaderWrapper getMediaLoader() {
|
2015-04-04 16:31:37 +02:00
|
|
|
return mImageLoader;
|
2014-12-06 15:40:22 +01:00
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public Context getContext() {
|
|
|
|
return mContext;
|
2015-03-29 09:17:42 +02:00
|
|
|
}
|
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
@Override
|
2015-04-16 14:48:24 +02:00
|
|
|
public MediaLoadingHandler getMediaLoadingHandler() {
|
|
|
|
return mMediaLoadingHandler;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public int getProfileImageStyle() {
|
|
|
|
return mProfileImageStyle;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-01-17 19:58:29 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public int getMediaPreviewStyle() {
|
2015-04-05 19:58:10 +02:00
|
|
|
return mMediaPreviewStyle;
|
2015-01-17 19:58:29 +01:00
|
|
|
}
|
|
|
|
|
2015-04-16 14:48:24 +02:00
|
|
|
@NonNull
|
2014-12-12 14:53:18 +01:00
|
|
|
@Override
|
|
|
|
public AsyncTwitterWrapper getTwitterWrapper() {
|
|
|
|
return mFragment.getTwitterWrapper();
|
|
|
|
}
|
|
|
|
|
2015-01-01 11:38:34 +01:00
|
|
|
public float getTextSize() {
|
|
|
|
return mTextSize;
|
|
|
|
}
|
|
|
|
|
2015-03-15 15:40:45 +01:00
|
|
|
@Override
|
2015-04-01 15:42:07 +02:00
|
|
|
public boolean isLoadMoreIndicatorVisible() {
|
|
|
|
return mLoadMoreIndicatorVisible;
|
2015-03-15 15:40:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-01 15:42:07 +02:00
|
|
|
public boolean isLoadMoreSupported() {
|
|
|
|
return mLoadMoreSupported;
|
|
|
|
}
|
2015-03-15 15:40:45 +01:00
|
|
|
|
2015-04-01 15:42:07 +02:00
|
|
|
@Override
|
|
|
|
public void setLoadMoreSupported(boolean supported) {
|
|
|
|
mLoadMoreSupported = supported;
|
|
|
|
if (!supported) {
|
|
|
|
mLoadMoreIndicatorVisible = false;
|
|
|
|
}
|
|
|
|
notifyDataSetChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setLoadMoreIndicatorVisible(boolean enabled) {
|
|
|
|
if (mLoadMoreIndicatorVisible == enabled) return;
|
|
|
|
mLoadMoreIndicatorVisible = enabled && mLoadMoreSupported;
|
2015-04-09 13:50:32 +02:00
|
|
|
updateItemDecoration();
|
2015-04-01 15:42:07 +02:00
|
|
|
notifyDataSetChanged();
|
2015-03-15 15:40:45 +01:00
|
|
|
}
|
|
|
|
|
2014-12-06 15:40:22 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public ParcelableStatus getStatus(int position) {
|
2014-12-07 16:13:07 +01:00
|
|
|
final int conversationCount = getConversationCount();
|
|
|
|
if (position == getItemCount() - 1) {
|
2015-04-04 16:31:37 +02:00
|
|
|
return null;
|
2014-12-07 16:13:07 +01:00
|
|
|
} else if (position < conversationCount) {
|
2015-04-04 16:31:37 +02:00
|
|
|
return mConversation != null ? mConversation.get(position) : null;
|
2014-12-07 16:13:07 +01:00
|
|
|
} else if (position > conversationCount) {
|
2015-04-04 16:31:37 +02:00
|
|
|
return mReplies != null ? mReplies.get(position - conversationCount - 1) : null;
|
2014-12-07 16:13:07 +01:00
|
|
|
} else {
|
2015-04-04 16:31:37 +02:00
|
|
|
return mStatus;
|
2014-12-06 15:40:22 +01:00
|
|
|
}
|
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public int getStatusesCount() {
|
|
|
|
return getConversationCount() + 1 + getRepliesCount() + 1;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public long getStatusId(int position) {
|
|
|
|
final ParcelableStatus status = getStatus(position);
|
|
|
|
return status != null ? status.hashCode() : position;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-04-05 19:58:10 +02:00
|
|
|
@Override
|
|
|
|
public TwidereLinkify getTwidereLinkify() {
|
2015-04-06 18:42:09 +02:00
|
|
|
return mTwidereLinkify;
|
2015-04-05 19:58:10 +02:00
|
|
|
}
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public boolean isMediaPreviewEnabled() {
|
|
|
|
return mDisplayMediaPreview;
|
2015-01-01 11:38:34 +01:00
|
|
|
}
|
|
|
|
|
2015-04-05 19:58:10 +02:00
|
|
|
@Override
|
|
|
|
public int getLinkHighlightingStyle() {
|
2015-04-06 18:42:09 +02:00
|
|
|
return mLinkHighligingStyle;
|
2015-04-05 19:58:10 +02:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public boolean isNameFirst() {
|
|
|
|
return mNameFirst;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-04-08 15:26:44 +02:00
|
|
|
@Override
|
|
|
|
public boolean isSensitiveContentEnabled() {
|
|
|
|
return mSensitiveContentEnabled;
|
|
|
|
}
|
|
|
|
|
2015-04-08 18:33:10 +02:00
|
|
|
@Override
|
|
|
|
public boolean isCardActionsHidden() {
|
|
|
|
return mHideCardActions;
|
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void setData(List<ParcelableStatus> data) {
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public boolean shouldShowAccountsColor() {
|
|
|
|
return false;
|
|
|
|
}
|
2015-01-06 16:46:07 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public ParcelableStatus getStatus() {
|
|
|
|
return mStatus;
|
|
|
|
}
|
2015-01-01 11:38:34 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public ParcelableCredentials getStatusAccount() {
|
|
|
|
return mStatusAccount;
|
|
|
|
}
|
2014-12-08 16:16:33 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public boolean isDetailMediaExpanded() {
|
2015-04-14 07:11:50 +02:00
|
|
|
if (mDetailMediaExpanded) return true;
|
2015-04-09 19:27:59 +02:00
|
|
|
if (mDisplayMediaPreview) {
|
|
|
|
final ParcelableStatus status = mStatus;
|
|
|
|
return status != null && (mSensitiveContentEnabled || !status.is_possibly_sensitive);
|
|
|
|
}
|
2015-04-14 07:11:50 +02:00
|
|
|
return false;
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
2014-12-06 15:40:22 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public void setDetailMediaExpanded(boolean expanded) {
|
|
|
|
mDetailMediaExpanded = expanded;
|
|
|
|
notifyDataSetChanged();
|
|
|
|
updateItemDecoration();
|
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public boolean isGapItem(int position) {
|
|
|
|
return false;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public final void onGapClick(ViewHolder holder, int position) {
|
|
|
|
if (mStatusAdapterListener != null) {
|
|
|
|
mStatusAdapterListener.onGapClick((GapViewHolder) holder, position);
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public boolean isProfileImageEnabled() {
|
|
|
|
return mDisplayProfileImage;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public final void onStatusClick(StatusViewHolder holder, int position) {
|
|
|
|
if (mStatusAdapterListener != null) {
|
|
|
|
mStatusAdapterListener.onStatusClick(holder, position);
|
2014-12-06 15:40:22 +01:00
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-04-16 14:48:24 +02:00
|
|
|
@Override
|
|
|
|
public boolean onStatusLongClick(StatusViewHolder holder, int position) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public void onMediaClick(StatusViewHolder holder, ParcelableMedia media, int position) {
|
|
|
|
if (mStatusAdapterListener != null) {
|
|
|
|
mStatusAdapterListener.onMediaClick(holder, media, position);
|
2015-03-29 08:44:43 +02:00
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void onUserProfileClick(StatusViewHolder holder, int position) {
|
|
|
|
final Context context = getContext();
|
|
|
|
final ParcelableStatus status = getStatus(position);
|
|
|
|
final View profileImageView = holder.getProfileImageView();
|
|
|
|
final View profileTypeView = holder.getProfileTypeView();
|
|
|
|
if (context instanceof FragmentActivity) {
|
|
|
|
final Bundle options = Utils.makeSceneTransitionOption((FragmentActivity) context,
|
|
|
|
new Pair<>(profileImageView, UserFragment.TRANSITION_NAME_PROFILE_IMAGE),
|
|
|
|
new Pair<>(profileTypeView, UserFragment.TRANSITION_NAME_PROFILE_TYPE));
|
|
|
|
Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, options);
|
|
|
|
} else {
|
|
|
|
Utils.openUserProfile(context, status.account_id, status.user_id, status.user_screen_name, null);
|
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
|
|
|
switch (viewType) {
|
|
|
|
case VIEW_TYPE_DETAIL_STATUS: {
|
|
|
|
if (mCachedHolder != null) return mCachedHolder;
|
|
|
|
final View view;
|
|
|
|
if (mIsCompact) {
|
|
|
|
view = mInflater.inflate(R.layout.header_status_compact, parent, false);
|
|
|
|
final View cardView = view.findViewById(R.id.compact_card);
|
|
|
|
cardView.setBackgroundColor(mCardBackgroundColor);
|
|
|
|
} else {
|
|
|
|
view = mInflater.inflate(R.layout.header_status, parent, false);
|
|
|
|
final CardView cardView = (CardView) view.findViewById(R.id.card);
|
|
|
|
cardView.setCardBackgroundColor(mCardBackgroundColor);
|
|
|
|
}
|
|
|
|
return new DetailStatusViewHolder(this, view);
|
2015-01-08 10:13:20 +01:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
case VIEW_TYPE_LIST_STATUS: {
|
|
|
|
final View view = mInflater.inflate(mCardLayoutResource, parent, false);
|
|
|
|
final CardView cardView = (CardView) view.findViewById(R.id.card);
|
|
|
|
if (cardView != null) {
|
|
|
|
cardView.setCardBackgroundColor(mCardBackgroundColor);
|
2015-01-19 18:46:14 +01:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
final StatusViewHolder holder = new StatusViewHolder(this, view);
|
|
|
|
holder.setupViewOptions();
|
|
|
|
holder.setOnClickListeners();
|
|
|
|
return holder;
|
2015-01-19 18:46:14 +01:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
case VIEW_TYPE_CONVERSATION_LOAD_INDICATOR:
|
|
|
|
case VIEW_TYPE_REPLIES_LOAD_INDICATOR: {
|
|
|
|
final View view = mInflater.inflate(R.layout.card_item_load_indicator, parent,
|
|
|
|
false);
|
|
|
|
return new LoadIndicatorViewHolder(view);
|
|
|
|
}
|
|
|
|
case VIEW_TYPE_SPACE: {
|
|
|
|
return new SpaceViewHolder(new Space(mContext));
|
2015-03-30 08:46:08 +02:00
|
|
|
}
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
return null;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-04-04 16:31:37 +02:00
|
|
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
|
|
|
switch (getItemViewType(position)) {
|
|
|
|
case VIEW_TYPE_DETAIL_STATUS: {
|
|
|
|
final ParcelableStatus status = getStatus(position);
|
|
|
|
final DetailStatusViewHolder detailHolder = (DetailStatusViewHolder) holder;
|
|
|
|
detailHolder.displayStatus(status);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case VIEW_TYPE_LIST_STATUS: {
|
|
|
|
final ParcelableStatus status = getStatus(position);
|
|
|
|
final StatusViewHolder statusHolder = (StatusViewHolder) holder;
|
|
|
|
// Display 'in reply to' for first item
|
|
|
|
// useful to indicate whether first tweet has reply or not
|
|
|
|
statusHolder.displayStatus(status, position == 0);
|
|
|
|
break;
|
|
|
|
}
|
2015-01-19 18:46:14 +01:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
2015-01-19 18:46:14 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public int getItemViewType(int position) {
|
|
|
|
final int conversationCount = getConversationCount();
|
|
|
|
if (position == getItemCount() - 1) {
|
|
|
|
return VIEW_TYPE_SPACE;
|
|
|
|
} else if (position < conversationCount) {
|
|
|
|
return mConversation != null ? VIEW_TYPE_LIST_STATUS : VIEW_TYPE_CONVERSATION_LOAD_INDICATOR;
|
|
|
|
} else if (position > conversationCount) {
|
|
|
|
return mReplies != null ? VIEW_TYPE_LIST_STATUS : VIEW_TYPE_REPLIES_LOAD_INDICATOR;
|
|
|
|
} else {
|
|
|
|
return VIEW_TYPE_DETAIL_STATUS;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
2014-12-06 15:40:22 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public long getItemId(int position) {
|
|
|
|
final int conversationCount = getConversationCount();
|
|
|
|
if (position == getItemCount() - 1) {
|
2015-04-08 20:37:05 +02:00
|
|
|
return VIEW_TYPE_SPACE;
|
2015-04-04 16:31:37 +02:00
|
|
|
} else if (position < conversationCount) {
|
2015-04-08 20:37:05 +02:00
|
|
|
return mConversation != null ? mConversation.get(position).id : VIEW_TYPE_CONVERSATION_LOAD_INDICATOR;
|
2015-04-04 16:31:37 +02:00
|
|
|
} else if (position > conversationCount) {
|
2015-04-08 20:37:05 +02:00
|
|
|
return mReplies != null ? mReplies.get(position - conversationCount - 1).id : VIEW_TYPE_REPLIES_LOAD_INDICATOR;
|
2015-04-03 19:22:00 +02:00
|
|
|
} else {
|
2015-04-08 20:37:05 +02:00
|
|
|
return mStatus != null ? mStatus.id : VIEW_TYPE_DETAIL_STATUS;
|
2015-04-03 19:22:00 +02:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
2014-12-06 15:40:22 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public int getItemCount() {
|
|
|
|
return getStatusesCount();
|
|
|
|
}
|
2014-12-06 15:40:22 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void onViewAttachedToWindow(ViewHolder holder) {
|
|
|
|
super.onViewAttachedToWindow(holder);
|
|
|
|
if (mCachedHolder == holder) {
|
|
|
|
mCachedHolder = null;
|
|
|
|
}
|
|
|
|
}
|
2014-12-06 15:40:22 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void onViewDetachedFromWindow(ViewHolder holder) {
|
|
|
|
super.onViewDetachedFromWindow(holder);
|
|
|
|
if (holder instanceof DetailStatusViewHolder) {
|
|
|
|
mCachedHolder = (DetailStatusViewHolder) holder;
|
2014-12-06 15:40:22 +01:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
2014-12-06 15:40:22 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void onItemActionClick(ViewHolder holder, int id, int position) {
|
|
|
|
if (mStatusAdapterListener != null) {
|
|
|
|
mStatusAdapterListener.onStatusActionClick((StatusViewHolder) holder, id, position);
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
2015-01-01 11:38:34 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void onItemMenuClick(ViewHolder holder, View itemView, int position) {
|
|
|
|
if (mStatusAdapterListener != null) {
|
|
|
|
mStatusAdapterListener.onStatusMenuClick((StatusViewHolder) holder, itemView, position);
|
2015-01-01 11:38:34 +01:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
}
|
2015-01-01 11:38:34 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public void setConversation(List<ParcelableStatus> conversation) {
|
|
|
|
mConversation = conversation;
|
|
|
|
notifyDataSetChanged();
|
|
|
|
updateItemDecoration();
|
2014-12-06 15:40:22 +01:00
|
|
|
}
|
2014-12-07 16:13:07 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public void setEventListener(StatusAdapterListener listener) {
|
|
|
|
mStatusAdapterListener = listener;
|
|
|
|
}
|
2015-01-08 10:13:20 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public void setReplies(List<ParcelableStatus> replies) {
|
|
|
|
mReplies = replies;
|
|
|
|
notifyDataSetChanged();
|
|
|
|
updateItemDecoration();
|
|
|
|
}
|
2015-04-03 23:12:33 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
public boolean setStatus(ParcelableStatus status) {
|
|
|
|
final ParcelableStatus old = mStatus;
|
|
|
|
mStatus = status;
|
|
|
|
if (status != null) {
|
|
|
|
mStatusAccount = ParcelableAccount.getCredentials(mContext, status.account_id);
|
|
|
|
} else {
|
|
|
|
mStatusAccount = null;
|
|
|
|
}
|
|
|
|
notifyDataSetChanged();
|
|
|
|
updateItemDecoration();
|
|
|
|
return !CompareUtils.objectEquals(old, status);
|
|
|
|
}
|
2015-04-03 23:12:33 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private int getConversationCount() {
|
|
|
|
return mConversation != null ? mConversation.size() : 1;
|
|
|
|
}
|
2015-04-03 23:12:33 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private int getRepliesCount() {
|
|
|
|
return mReplies != null ? mReplies.size() : 1;
|
|
|
|
}
|
2015-04-03 23:12:33 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private int getStatusPosition() {
|
|
|
|
return getConversationCount();
|
|
|
|
}
|
2015-04-03 23:12:33 +02:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
private void updateItemDecoration() {
|
|
|
|
final DividerItemDecoration decoration = mFragment.getItemDecoration();
|
|
|
|
decoration.setDecorationStart(0);
|
2015-04-09 13:50:32 +02:00
|
|
|
if (isLoadMoreIndicatorVisible()) {
|
2015-04-04 16:31:37 +02:00
|
|
|
decoration.setDecorationEndOffset(3);
|
2015-04-09 13:50:32 +02:00
|
|
|
} else {
|
|
|
|
decoration.setDecorationEndOffset(mReplies != null && mReplies.size() > 0 ? 1 : 2);
|
2015-04-04 00:06:08 +02:00
|
|
|
}
|
2015-04-04 16:31:37 +02:00
|
|
|
mFragment.mRecyclerView.invalidateItemDecorations();
|
2014-12-07 16:13:07 +01:00
|
|
|
}
|
2014-12-06 15:40:22 +01:00
|
|
|
}
|
|
|
|
|
2015-03-24 16:40:47 +01:00
|
|
|
private static class StatusListLinearLayoutManager extends FixedLinearLayoutManager {
|
2014-12-06 15:40:22 +01:00
|
|
|
|
2014-12-07 16:13:07 +01:00
|
|
|
private final RecyclerView recyclerView;
|
|
|
|
|
2014-12-08 16:16:33 +01:00
|
|
|
public StatusListLinearLayoutManager(Context context, RecyclerView recyclerView) {
|
2014-12-06 15:40:22 +01:00
|
|
|
super(context);
|
2014-12-08 16:16:33 +01:00
|
|
|
setOrientation(LinearLayoutManager.VERTICAL);
|
2014-12-07 16:13:07 +01:00
|
|
|
this.recyclerView = recyclerView;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2014-12-06 15:40:22 +01:00
|
|
|
public int getDecoratedMeasuredHeight(View child) {
|
|
|
|
final int height = super.getDecoratedMeasuredHeight(child);
|
|
|
|
int heightBeforeSpace = 0;
|
|
|
|
if (getItemViewType(child) == StatusAdapter.VIEW_TYPE_SPACE) {
|
|
|
|
for (int i = 0, j = getChildCount(); i < j; i++) {
|
|
|
|
final View childToMeasure = getChildAt(i);
|
|
|
|
final LayoutParams paramsToMeasure = (LayoutParams) childToMeasure.getLayoutParams();
|
|
|
|
final int typeToMeasure = getItemViewType(childToMeasure);
|
|
|
|
if (typeToMeasure == StatusAdapter.VIEW_TYPE_DETAIL_STATUS || heightBeforeSpace != 0) {
|
|
|
|
heightBeforeSpace += super.getDecoratedMeasuredHeight(childToMeasure)
|
|
|
|
+ paramsToMeasure.topMargin + paramsToMeasure.bottomMargin;
|
|
|
|
}
|
|
|
|
if (typeToMeasure == StatusAdapter.VIEW_TYPE_REPLIES_LOAD_INDICATOR) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (heightBeforeSpace != 0) {
|
2014-12-07 16:13:07 +01:00
|
|
|
final int spaceHeight = recyclerView.getMeasuredHeight() - heightBeforeSpace;
|
2014-12-06 15:40:22 +01:00
|
|
|
return Math.max(0, spaceHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return height;
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-01-01 11:38:34 +01:00
|
|
|
@Override
|
|
|
|
public void setOrientation(int orientation) {
|
|
|
|
if (orientation != VERTICAL)
|
|
|
|
throw new IllegalArgumentException("Only VERTICAL orientation supported");
|
|
|
|
super.setOrientation(orientation);
|
|
|
|
}
|
|
|
|
|
2014-07-28 12:42:48 +02:00
|
|
|
}
|
2014-12-07 16:13:07 +01:00
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
|
2014-07-03 07:48:39 +02:00
|
|
|
}
|