close #567
This commit is contained in:
parent
53662fb5b2
commit
918b2d27ed
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 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 org.mariotaku.twidere.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.commonsware.cwac.layouts.AspectLockedFrameLayout;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter;
|
||||
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.model.util.ParcelableMediaUtils;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.view.MediaPreviewImageView;
|
||||
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/11/19.
|
||||
*/
|
||||
public class StaggeredGridParcelableStatusesAdapter extends ParcelableStatusesAdapter {
|
||||
|
||||
public StaggeredGridParcelableStatusesAdapter(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getProgressViewIds() {
|
||||
return new int[]{R.id.media_image_progress};
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected IStatusViewHolder onCreateStatusViewHolder(ViewGroup parent) {
|
||||
final View view = getInflater().inflate(R.layout.adapter_item_media_status, parent, false);
|
||||
final MediaStatusViewHolder holder = new MediaStatusViewHolder(this, view);
|
||||
holder.setOnClickListeners();
|
||||
holder.setupViewOptions();
|
||||
return holder;
|
||||
}
|
||||
|
||||
public static class MediaStatusViewHolder extends RecyclerView.ViewHolder
|
||||
implements IStatusViewHolder, View.OnClickListener, View.OnLongClickListener {
|
||||
private final SimpleAspectRatioSource aspectRatioSource = new SimpleAspectRatioSource();
|
||||
|
||||
private final AspectLockedFrameLayout mediaImageContainer;
|
||||
private final MediaPreviewImageView mediaImageView;
|
||||
private final ImageView mediaProfileImageView;
|
||||
private final TextView mediaTextView;
|
||||
private final IStatusesAdapter<?> adapter;
|
||||
private StatusClickListener listener;
|
||||
|
||||
public MediaStatusViewHolder(IStatusesAdapter<?> adapter, View itemView) {
|
||||
super(itemView);
|
||||
this.adapter = adapter;
|
||||
mediaImageContainer = (AspectLockedFrameLayout) itemView.findViewById(R.id.media_image_container);
|
||||
mediaImageContainer.setAspectRatioSource(aspectRatioSource);
|
||||
mediaImageView = (MediaPreviewImageView) itemView.findViewById(R.id.media_image);
|
||||
mediaProfileImageView = (ImageView) itemView.findViewById(R.id.media_profile_image);
|
||||
mediaTextView = (TextView) itemView.findViewById(R.id.media_text);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void displayStatus(@NonNull ParcelableStatus status, boolean displayInReplyTo, boolean shouldDisplayExtraType) {
|
||||
final MediaLoaderWrapper loader = adapter.getMediaLoader();
|
||||
final ParcelableMedia[] media = status.media;
|
||||
if (media == null || media.length < 1) return;
|
||||
final ParcelableMedia firstMedia = media[0];
|
||||
mediaTextView.setText(status.text_unescaped);
|
||||
if (firstMedia.width > 0 && firstMedia.height > 0) {
|
||||
aspectRatioSource.setSize(firstMedia.width, firstMedia.height);
|
||||
} else {
|
||||
aspectRatioSource.setSize(100, 100);
|
||||
}
|
||||
mediaImageContainer.setTag(firstMedia);
|
||||
mediaImageContainer.requestLayout();
|
||||
|
||||
mediaImageView.setHasPlayIcon(ParcelableMediaUtils.hasPlayIcon(firstMedia.type));
|
||||
loader.displayProfileImage(mediaProfileImageView, status);
|
||||
loader.displayPreviewImageWithCredentials(mediaImageView, firstMedia.preview_url,
|
||||
status.account_key, adapter.getMediaLoadingHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ImageView getProfileImageView() {
|
||||
return mediaProfileImageView;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ImageView getProfileTypeView() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener == null) return;
|
||||
switch (v.getId()) {
|
||||
case R.id.itemContent: {
|
||||
listener.onStatusClick(this, getLayoutPosition());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onLongClick(View v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaClick(View view, ParcelableMedia media, UserKey accountKey, long extraId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatusClickListener(StatusClickListener listener) {
|
||||
this.listener = listener;
|
||||
itemView.findViewById(R.id.itemContent).setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextSize(float textSize) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playLikeAnimation(LikeAnimationDrawable.OnLikedListener listener) {
|
||||
|
||||
}
|
||||
|
||||
public void setOnClickListeners() {
|
||||
setStatusClickListener(adapter.getStatusClickListener());
|
||||
}
|
||||
|
||||
public void setupViewOptions() {
|
||||
setTextSize(adapter.getTextSize());
|
||||
}
|
||||
|
||||
|
||||
private static class SimpleAspectRatioSource implements AspectLockedFrameLayout.AspectRatioSource {
|
||||
private int width, height;
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setSize(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -148,23 +148,23 @@ public abstract class DrawableHolder {
|
|||
}
|
||||
|
||||
public static class Builtin extends DrawableHolder {
|
||||
public static final Builtin HOME = new Builtin("home", R.drawable.ic_action_home);
|
||||
public static final Builtin HEART = new Builtin("heart", R.drawable.ic_action_heart);
|
||||
public static final Builtin HASHTAG = new Builtin("hashtag", R.drawable.ic_action_hashtag);
|
||||
public static final Builtin ACCOUNTS = new Builtin("accounts", R.drawable.ic_action_accounts);
|
||||
public static final Builtin LIST = new Builtin("list", R.drawable.ic_action_list);
|
||||
public static final Builtin MENTION = new Builtin("mention", R.drawable.ic_action_at);
|
||||
public static final Builtin NOTIFICATIONS = new Builtin("notifications", R.drawable.ic_action_notification);
|
||||
public static final Builtin GALLERY = new Builtin("gallery", R.drawable.ic_action_gallery);
|
||||
public static final Builtin MESSAGE = new Builtin("message", R.drawable.ic_action_message);
|
||||
public static final Builtin QUOTE = new Builtin("quote", R.drawable.ic_action_quote);
|
||||
public static final Builtin SEARCH = new Builtin("search", R.drawable.ic_action_search);
|
||||
public static final Builtin STAGGERED = new Builtin("staggered", R.drawable.ic_action_view_quilt);
|
||||
public static final Builtin STAR = new Builtin("star", R.drawable.ic_action_star);
|
||||
public static final Builtin TRENDS = new Builtin("trends", R.drawable.ic_action_trends);
|
||||
public static final Builtin TWIDERE = new Builtin("twidere", R.drawable.ic_action_twidere);
|
||||
public static final Builtin TWITTER = new Builtin("twitter", R.drawable.ic_action_twitter);
|
||||
public static final Builtin USER = new Builtin("user", R.drawable.ic_action_user);
|
||||
public static final DrawableHolder HOME = new Builtin("home", R.drawable.ic_action_home);
|
||||
public static final DrawableHolder HEART = new Builtin("heart", R.drawable.ic_action_heart);
|
||||
public static final DrawableHolder HASHTAG = new Builtin("hashtag", R.drawable.ic_action_hashtag);
|
||||
public static final DrawableHolder ACCOUNTS = new Builtin("accounts", R.drawable.ic_action_accounts);
|
||||
public static final DrawableHolder LIST = new Builtin("list", R.drawable.ic_action_list);
|
||||
public static final DrawableHolder MENTION = new Builtin("mention", R.drawable.ic_action_at);
|
||||
public static final DrawableHolder NOTIFICATIONS = new Builtin("notifications", R.drawable.ic_action_notification);
|
||||
public static final DrawableHolder GALLERY = new Builtin("gallery", R.drawable.ic_action_gallery);
|
||||
public static final DrawableHolder MESSAGE = new Builtin("message", R.drawable.ic_action_message);
|
||||
public static final DrawableHolder QUOTE = new Builtin("quote", R.drawable.ic_action_quote);
|
||||
public static final DrawableHolder SEARCH = new Builtin("search", R.drawable.ic_action_search);
|
||||
public static final DrawableHolder STAGGERED = new Builtin("staggered", R.drawable.ic_action_view_quilt);
|
||||
public static final DrawableHolder STAR = new Builtin("star", R.drawable.ic_action_star);
|
||||
public static final DrawableHolder TRENDS = new Builtin("trends", R.drawable.ic_action_trends);
|
||||
public static final DrawableHolder TWIDERE = new Builtin("twidere", R.drawable.ic_action_twidere);
|
||||
public static final DrawableHolder TWITTER = new Builtin("twitter", R.drawable.ic_action_twitter);
|
||||
public static final DrawableHolder USER = new Builtin("user", R.drawable.ic_action_user);
|
||||
public static final DrawableHolder FAVORITE = new DrawableHolder() {
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -185,7 +185,7 @@ public abstract class DrawableHolder {
|
|||
private final String key;
|
||||
private final int resId;
|
||||
|
||||
public Builtin(String key, int resId) {
|
||||
private Builtin(String key, int resId) {
|
||||
this.key = key;
|
||||
this.resId = resId;
|
||||
setName(WordUtils.capitalize(key));
|
||||
|
|
|
@ -5,9 +5,9 @@ import android.support.v4.app.Fragment;
|
|||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.fragment.TrendsSuggestionsFragment;
|
||||
import org.mariotaku.twidere.model.tab.TabConfiguration;
|
||||
import org.mariotaku.twidere.model.tab.DrawableHolder;
|
||||
import org.mariotaku.twidere.model.tab.StringHolder;
|
||||
import org.mariotaku.twidere.model.tab.TabConfiguration;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2016/11/27.
|
||||
|
@ -23,7 +23,7 @@ public class TrendsTabConfiguration extends TabConfiguration {
|
|||
@NonNull
|
||||
@Override
|
||||
public DrawableHolder getIcon() {
|
||||
return DrawableHolder.Builtin.TRENDS;
|
||||
return DrawableHolder.Builtin.HASHTAG;
|
||||
}
|
||||
|
||||
@AccountFlags
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* 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 org.mariotaku.twidere.view.holder;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
import org.mariotaku.twidere.adapter.iface.IGapSupportedAdapter;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/12/3.
|
||||
*/
|
||||
public class GapViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
|
||||
|
||||
private final IGapSupportedAdapter adapter;
|
||||
|
||||
public GapViewHolder(IGapSupportedAdapter adapter, View itemView) {
|
||||
super(itemView);
|
||||
this.adapter = adapter;
|
||||
itemView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final IGapSupportedAdapter.GapClickListener listener = adapter.getGapClickListener();
|
||||
if (listener == null) return;
|
||||
listener.onGapClick(this, getLayoutPosition());
|
||||
}
|
||||
}
|
|
@ -8,10 +8,7 @@ import org.mariotaku.twidere.TwidereConstants
|
|||
import org.mariotaku.twidere.adapter.iface.*
|
||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants
|
||||
import org.mariotaku.twidere.model.ParcelableStatus
|
||||
import org.mariotaku.twidere.model.ParcelableUser
|
||||
import org.mariotaku.twidere.model.ParcelableUserList
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.util.getActivityStatus
|
||||
import org.mariotaku.twidere.util.*
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||
|
@ -179,6 +176,14 @@ class DummyItemAdapter @JvmOverloads constructor(
|
|||
return false
|
||||
}
|
||||
|
||||
override fun addGapLoadingId(id: ObjectId) {
|
||||
|
||||
}
|
||||
|
||||
override fun removeGapLoadingId(id: ObjectId) {
|
||||
|
||||
}
|
||||
|
||||
fun updateOptions() {
|
||||
profileImageStyle = Utils.getProfileImageStyle(preferences.getString(SharedPreferenceConstants.KEY_PROFILE_IMAGE_STYLE, null))
|
||||
mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(SharedPreferenceConstants.KEY_MEDIA_PREVIEW_STYLE, null))
|
||||
|
|
|
@ -36,11 +36,9 @@ import org.mariotaku.twidere.adapter.iface.IGapSupportedAdapter
|
|||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
||||
import org.mariotaku.twidere.annotation.Referral
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_NEW_DOCUMENT_API
|
||||
import org.mariotaku.twidere.extension.model.id
|
||||
import org.mariotaku.twidere.fragment.CursorActivitiesFragment
|
||||
import org.mariotaku.twidere.model.ParcelableActivity
|
||||
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices
|
||||
import org.mariotaku.twidere.model.ParcelableMedia
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.util.ParcelableActivityUtils
|
||||
import org.mariotaku.twidere.model.util.getActivityStatus
|
||||
import org.mariotaku.twidere.util.IntentUtils
|
||||
|
@ -50,6 +48,7 @@ import org.mariotaku.twidere.util.TwidereLinkify
|
|||
import org.mariotaku.twidere.view.holder.*
|
||||
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/3.
|
||||
|
@ -66,6 +65,8 @@ class ParcelableActivitiesAdapter(
|
|||
private var data: List<ParcelableActivity>? = null
|
||||
private var activityAdapterListener: ActivityAdapterListener? = null
|
||||
private var filteredUserIds: Array<UserKey>? = null
|
||||
private val gapLoadingIds: MutableSet<ObjectId> = HashSet()
|
||||
|
||||
var followingOnly: Boolean = false
|
||||
set(value) {
|
||||
field = value
|
||||
|
@ -169,6 +170,7 @@ class ParcelableActivitiesAdapter(
|
|||
filteredUserIds = data.filteredUserIds
|
||||
}
|
||||
this.data = data
|
||||
gapLoadingIds.clear()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
|
@ -217,7 +219,7 @@ class ParcelableActivitiesAdapter(
|
|||
return holder
|
||||
}
|
||||
ITEM_VIEW_TYPE_GAP -> {
|
||||
val view = inflater.inflate(R.layout.card_item_gap, parent, false)
|
||||
val view = inflater.inflate(GapViewHolder.layoutResource, parent, false)
|
||||
return GapViewHolder(this, view)
|
||||
}
|
||||
ITEM_VIEW_TYPE_LOAD_INDICATOR -> {
|
||||
|
@ -248,6 +250,11 @@ class ParcelableActivitiesAdapter(
|
|||
ITEM_VIEW_TYPE_STUB -> {
|
||||
(holder as StubViewHolder).displayActivity(getActivity(position)!!)
|
||||
}
|
||||
ITEM_VIEW_TYPE_GAP -> {
|
||||
val activity = getActivity(position)!!
|
||||
val loading = gapLoadingIds.find { it.accountKey == activity.account_key && it.id == activity.id } != null
|
||||
(holder as GapViewHolder).display(loading)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,6 +306,13 @@ class ParcelableActivitiesAdapter(
|
|||
return ITEM_VIEW_TYPE_STUB
|
||||
}
|
||||
|
||||
override fun addGapLoadingId(id: ObjectId) {
|
||||
gapLoadingIds.add(id)
|
||||
}
|
||||
|
||||
override fun removeGapLoadingId(id: ObjectId) {
|
||||
gapLoadingIds.remove(id)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
val position = loadMoreIndicatorPosition
|
||||
|
@ -388,16 +402,14 @@ class ParcelableActivitiesAdapter(
|
|||
|
||||
override fun onGapClick(holder: GapViewHolder, position: Int) {
|
||||
val adapter = adapterRef.get() ?: return
|
||||
if (adapter.activityAdapterListener != null) {
|
||||
adapter.activityAdapterListener!!.onGapClick(holder, position)
|
||||
}
|
||||
val activity = adapter.getActivity(position) ?: return
|
||||
adapter.addGapLoadingId(ObjectId(activity.account_key, activity.id))
|
||||
adapter.activityAdapterListener?.onGapClick(holder, position)
|
||||
}
|
||||
|
||||
override fun onItemActionClick(holder: RecyclerView.ViewHolder, id: Int, position: Int) {
|
||||
val adapter = adapterRef.get() ?: return
|
||||
if (adapter.activityAdapterListener != null) {
|
||||
adapter.activityAdapterListener!!.onStatusActionClick(holder as IStatusViewHolder, id, position)
|
||||
}
|
||||
adapter.activityAdapterListener?.onStatusActionClick(holder as IStatusViewHolder, id, position)
|
||||
}
|
||||
|
||||
override fun onStatusLongClick(holder: IStatusViewHolder, position: Int): Boolean {
|
||||
|
|
|
@ -29,10 +29,13 @@ import org.mariotaku.ktextension.safeMoveToPosition
|
|||
import org.mariotaku.library.objectcursor.ObjectCursor
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.adapter.iface.IGapSupportedAdapter
|
||||
import org.mariotaku.twidere.adapter.iface.IGapSupportedAdapter.Companion.ITEM_VIEW_TYPE_GAP
|
||||
import org.mariotaku.twidere.adapter.iface.IItemCountsAdapter
|
||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.Companion.ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants.*
|
||||
import org.mariotaku.twidere.model.ObjectId
|
||||
import org.mariotaku.twidere.model.ParcelableStatus
|
||||
import org.mariotaku.twidere.model.ParcelableStatusCursorIndices
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
|
@ -46,6 +49,7 @@ import org.mariotaku.twidere.view.holder.EmptyViewHolder
|
|||
import org.mariotaku.twidere.view.holder.GapViewHolder
|
||||
import org.mariotaku.twidere.view.holder.LoadIndicatorViewHolder
|
||||
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/10/26.
|
||||
|
@ -72,10 +76,12 @@ abstract class ParcelableStatusesAdapter(
|
|||
final override val sensitiveContentEnabled: Boolean
|
||||
final override val useStarsForLikes: Boolean
|
||||
final override val isShowAbsoluteTime: Boolean
|
||||
override var statusClickListener: IStatusViewHolder.StatusClickListener? = null
|
||||
|
||||
private val showCardActions: Boolean
|
||||
|
||||
private val gapLoadingIds: MutableSet<ObjectId> = HashSet()
|
||||
|
||||
override var statusClickListener: IStatusViewHolder.StatusClickListener? = null
|
||||
|
||||
override val gapClickListener: IGapSupportedAdapter.GapClickListener?
|
||||
get() = statusClickListener
|
||||
|
||||
|
@ -245,14 +251,11 @@ abstract class ParcelableStatusesAdapter(
|
|||
changed = data != data
|
||||
}
|
||||
this.data = data
|
||||
gapLoadingIds.clear()
|
||||
notifyDataSetChanged()
|
||||
return changed
|
||||
}
|
||||
|
||||
fun getData(): List<ParcelableStatus>? {
|
||||
return data
|
||||
}
|
||||
|
||||
override fun isCardActionsShown(position: Int): Boolean {
|
||||
if (position == RecyclerView.NO_POSITION) return showCardActions
|
||||
return showCardActions || showingActionCardId == getItemId(position)
|
||||
|
@ -272,21 +275,16 @@ abstract class ParcelableStatusesAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fun isStatus(position: Int): Boolean {
|
||||
return position < statusCount
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
when (viewType) {
|
||||
ITEM_VIEW_TYPE_STATUS -> {
|
||||
return onCreateStatusViewHolder(parent) as RecyclerView.ViewHolder
|
||||
}
|
||||
IGapSupportedAdapter.ITEM_VIEW_TYPE_GAP -> {
|
||||
val view = inflater.inflate(R.layout.card_item_gap, parent, false)
|
||||
ITEM_VIEW_TYPE_GAP -> {
|
||||
val view = inflater.inflate(GapViewHolder.layoutResource, parent, false)
|
||||
return GapViewHolder(this, view)
|
||||
}
|
||||
ILoadMoreSupportAdapter.ITEM_VIEW_TYPE_LOAD_INDICATOR -> {
|
||||
ITEM_VIEW_TYPE_LOAD_INDICATOR -> {
|
||||
val view = inflater.inflate(R.layout.card_item_load_indicator, parent, false)
|
||||
return LoadIndicatorViewHolder(view)
|
||||
}
|
||||
|
@ -297,7 +295,6 @@ abstract class ParcelableStatusesAdapter(
|
|||
throw IllegalStateException("Unknown view type " + viewType)
|
||||
}
|
||||
|
||||
protected abstract fun onCreateStatusViewHolder(parent: ViewGroup): IStatusViewHolder
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
when (getItemCountIndex(position)) {
|
||||
|
@ -306,31 +303,53 @@ abstract class ParcelableStatusesAdapter(
|
|||
(holder as IStatusViewHolder).displayStatus(status, isShowInReplyTo)
|
||||
}
|
||||
2 -> {
|
||||
val status = data!![position - getItemStartPosition(2)]
|
||||
when (holder.itemViewType) {
|
||||
ITEM_VIEW_TYPE_STATUS -> {
|
||||
val status = data!![position - getItemStartPosition(2)]
|
||||
(holder as IStatusViewHolder).displayStatus(status, isShowInReplyTo)
|
||||
}
|
||||
ITEM_VIEW_TYPE_GAP -> {
|
||||
val loading = gapLoadingIds.find { it.accountKey == status.account_key && it.id == status.id } != null
|
||||
(holder as GapViewHolder).display(loading)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected abstract fun onCreateStatusViewHolder(parent: ViewGroup): IStatusViewHolder
|
||||
|
||||
override fun addGapLoadingId(id: ObjectId) {
|
||||
gapLoadingIds.add(id)
|
||||
}
|
||||
|
||||
override fun removeGapLoadingId(id: ObjectId) {
|
||||
gapLoadingIds.remove(id)
|
||||
}
|
||||
|
||||
fun getData(): List<ParcelableStatus>? {
|
||||
return data
|
||||
}
|
||||
|
||||
fun isStatus(position: Int): Boolean {
|
||||
return position < statusCount
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if (loadMoreIndicatorPosition and ILoadMoreSupportAdapter.START != 0L && position == 0) {
|
||||
return ILoadMoreSupportAdapter.ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
return ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
}
|
||||
when (getItemCountIndex(position)) {
|
||||
0, 3 -> {
|
||||
return ILoadMoreSupportAdapter.ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
return ITEM_VIEW_TYPE_LOAD_INDICATOR
|
||||
}
|
||||
1 -> {
|
||||
return ITEM_VIEW_TYPE_STATUS
|
||||
}
|
||||
2 -> {
|
||||
if (isGapItem(position)) {
|
||||
return IGapSupportedAdapter.ITEM_VIEW_TYPE_GAP
|
||||
return ITEM_VIEW_TYPE_GAP
|
||||
} else if (isFiltered(position)) {
|
||||
return ITEM_VIEW_TYPE_EMPTY
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 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 org.mariotaku.twidere.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.commonsware.cwac.layouts.AspectLockedFrameLayout
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
|
||||
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
|
||||
import org.mariotaku.twidere.model.ParcelableMedia
|
||||
import org.mariotaku.twidere.model.ParcelableStatus
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
|
||||
import org.mariotaku.twidere.view.MediaPreviewImageView
|
||||
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/11/19.
|
||||
*/
|
||||
class StaggeredGridParcelableStatusesAdapter(context: Context) : ParcelableStatusesAdapter(context) {
|
||||
|
||||
override val progressViewIds: IntArray
|
||||
get() = intArrayOf(R.id.media_image_progress)
|
||||
|
||||
override fun onCreateStatusViewHolder(parent: ViewGroup): IStatusViewHolder {
|
||||
val view = inflater.inflate(R.layout.adapter_item_media_status, parent, false)
|
||||
val holder = MediaStatusViewHolder(this, view)
|
||||
holder.setOnClickListeners()
|
||||
holder.setupViewOptions()
|
||||
return holder
|
||||
}
|
||||
|
||||
class MediaStatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : RecyclerView.ViewHolder(itemView), IStatusViewHolder, View.OnClickListener, View.OnLongClickListener {
|
||||
private val aspectRatioSource = SimpleAspectRatioSource()
|
||||
|
||||
private val mediaImageContainer: AspectLockedFrameLayout
|
||||
private val mediaImageView: MediaPreviewImageView
|
||||
override val profileImageView: ImageView?
|
||||
private val mediaTextView: TextView
|
||||
private var listener: IStatusViewHolder.StatusClickListener? = null
|
||||
|
||||
init {
|
||||
mediaImageContainer = itemView.findViewById(R.id.media_image_container) as AspectLockedFrameLayout
|
||||
mediaImageContainer.setAspectRatioSource(aspectRatioSource)
|
||||
mediaImageView = itemView.findViewById(R.id.media_image) as MediaPreviewImageView
|
||||
profileImageView = itemView.findViewById(R.id.media_profile_image) as ImageView
|
||||
mediaTextView = itemView.findViewById(R.id.media_text) as TextView
|
||||
}
|
||||
|
||||
|
||||
override fun displayStatus(status: ParcelableStatus, displayInReplyTo: Boolean, shouldDisplayExtraType: Boolean) {
|
||||
val loader = adapter.mediaLoader
|
||||
val media = status.media ?: return
|
||||
if (media.isEmpty()) return
|
||||
val firstMedia = media[0]
|
||||
mediaTextView.text = status.text_unescaped
|
||||
if (firstMedia.width > 0 && firstMedia.height > 0) {
|
||||
aspectRatioSource.setSize(firstMedia.width, firstMedia.height)
|
||||
} else {
|
||||
aspectRatioSource.setSize(100, 100)
|
||||
}
|
||||
mediaImageContainer.tag = firstMedia
|
||||
mediaImageContainer.requestLayout()
|
||||
|
||||
mediaImageView.setHasPlayIcon(ParcelableMediaUtils.hasPlayIcon(firstMedia.type))
|
||||
loader.displayProfileImage(profileImageView, status)
|
||||
loader.displayPreviewImageWithCredentials(mediaImageView, firstMedia.preview_url,
|
||||
status.account_key, adapter.mediaLoadingHandler)
|
||||
}
|
||||
|
||||
override val profileTypeView: ImageView?
|
||||
get() = null
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (listener == null) return
|
||||
when (v.id) {
|
||||
R.id.itemContent -> {
|
||||
listener!!.onStatusClick(this, layoutPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLongClick(v: View): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMediaClick(view: View, media: ParcelableMedia, accountKey: UserKey, extraId: Long) {
|
||||
}
|
||||
|
||||
override fun setStatusClickListener(listener: IStatusViewHolder.StatusClickListener?) {
|
||||
this.listener = listener
|
||||
itemView.findViewById(R.id.itemContent).setOnClickListener(this)
|
||||
}
|
||||
|
||||
override fun setTextSize(textSize: Float) {
|
||||
|
||||
}
|
||||
|
||||
override fun playLikeAnimation(listener: LikeAnimationDrawable.OnLikedListener) {
|
||||
|
||||
}
|
||||
|
||||
fun setOnClickListeners() {
|
||||
setStatusClickListener(adapter.statusClickListener)
|
||||
}
|
||||
|
||||
fun setupViewOptions() {
|
||||
setTextSize(adapter.textSize)
|
||||
}
|
||||
|
||||
|
||||
private class SimpleAspectRatioSource : AspectLockedFrameLayout.AspectRatioSource {
|
||||
private var width: Int = 0
|
||||
private var height: Int = 0
|
||||
|
||||
override fun getWidth(): Int {
|
||||
return width
|
||||
}
|
||||
|
||||
override fun getHeight(): Int {
|
||||
return height
|
||||
}
|
||||
|
||||
fun setSize(width: Int, height: Int) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.adapter.iface
|
||||
|
||||
import org.mariotaku.twidere.model.ObjectId
|
||||
import org.mariotaku.twidere.view.holder.GapViewHolder
|
||||
|
||||
/**
|
||||
|
@ -28,6 +29,10 @@ interface IGapSupportedAdapter {
|
|||
|
||||
fun isGapItem(position: Int): Boolean
|
||||
|
||||
fun addGapLoadingId(id: ObjectId)
|
||||
|
||||
fun removeGapLoadingId(id: ObjectId)
|
||||
|
||||
val gapClickListener: GapClickListener?
|
||||
|
||||
interface GapClickListener {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package org.mariotaku.twidere.extension.model
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableActivity
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2016/12/6.
|
||||
*/
|
||||
val ParcelableActivity.id: String
|
||||
get() = "$min_position-$max_position"
|
|
@ -397,12 +397,12 @@ abstract class AbsStatusesFragment protected constructor() :
|
|||
|
||||
|
||||
override fun onGapClick(holder: GapViewHolder, position: Int) {
|
||||
val adapter = adapter
|
||||
val status = adapter!!.getStatus(position)
|
||||
val adapter = this.adapter ?: return
|
||||
val status = adapter.getStatus(position) ?: return
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.v(TwidereConstants.LOGTAG, "Load activity gap " + status!!)
|
||||
Log.v(TwidereConstants.LOGTAG, "Load activity gap " + status)
|
||||
}
|
||||
if (status == null) return
|
||||
adapter.addGapLoadingId(ObjectId(status.account_key, status.id))
|
||||
val accountIds = arrayOf(status.account_key)
|
||||
val maxIds = arrayOf<String?>(status.id)
|
||||
val maxSortIds = longArrayOf(status.sort_id)
|
||||
|
|
|
@ -1746,6 +1746,14 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
|
|||
return getItemViewTypeByItemType(getItemType(position))
|
||||
}
|
||||
|
||||
override fun addGapLoadingId(id: ObjectId) {
|
||||
|
||||
}
|
||||
|
||||
override fun removeGapLoadingId(id: ObjectId) {
|
||||
|
||||
}
|
||||
|
||||
private fun getItemViewTypeByItemType(type: Int): Int {
|
||||
when (type) {
|
||||
ITEM_IDX_CONVERSATION, ITEM_IDX_REPLY -> return VIEW_TYPE_LIST_STATUS
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package org.mariotaku.twidere.model
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2016/12/6.
|
||||
*/
|
||||
data class ObjectId(val accountKey: UserKey, val id: String)
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* 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 org.mariotaku.twidere.view.holder
|
||||
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
import android.view.View.OnClickListener
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import kotlinx.android.synthetic.main.card_item_gap.view.*
|
||||
import org.mariotaku.twidere.R
|
||||
|
||||
import org.mariotaku.twidere.adapter.iface.IGapSupportedAdapter
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 14/12/3.
|
||||
*/
|
||||
class GapViewHolder(
|
||||
private val adapter: IGapSupportedAdapter,
|
||||
itemView: View
|
||||
) : RecyclerView.ViewHolder(itemView), OnClickListener {
|
||||
|
||||
private val gapText: TextView
|
||||
private val gapProgress: ProgressBar
|
||||
|
||||
init {
|
||||
itemView.setOnClickListener(this)
|
||||
gapText = itemView.gapText
|
||||
gapProgress = itemView.gapProgress
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
adapter.gapClickListener?.onGapClick(this, layoutPosition)
|
||||
display(true)
|
||||
}
|
||||
|
||||
fun display(showProgress: Boolean) {
|
||||
gapText.visibility = if (showProgress) View.GONE else View.VISIBLE
|
||||
gapProgress.visibility = if (showProgress) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val layoutResource = R.layout.card_item_gap
|
||||
}
|
||||
}
|
|
@ -18,15 +18,30 @@
|
|||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gap_indicator"
|
||||
<FrameLayout
|
||||
android:id="@+id/gapIndicator"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
android:focusable="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/gapText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:text="@string/load_more"
|
||||
android:focusable="true"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/gapProgress"
|
||||
style="?android:progressBarStyleSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
</FrameLayout>
|
Loading…
Reference in New Issue