implemented notification fragment, restructured adapter and holder, added notification to user and status item layout
This commit is contained in:
parent
2da277da8a
commit
0aa0a51912
|
@ -5,7 +5,6 @@ import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_STATUS_FRAGM
|
|||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_STATUS_FRAGMENT_SEARCH;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.STATUS_FRAGMENT_FAVORIT;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.STATUS_FRAGMENT_HOME;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.STATUS_FRAGMENT_MENTION;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.STATUS_FRAGMENT_SEARCH;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.STATUS_FRAGMENT_USER;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.STATUS_FRAGMENT_USERLIST;
|
||||
|
@ -38,6 +37,7 @@ import androidx.fragment.app.FragmentManager;
|
|||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
import org.nuclearfog.twidda.ui.fragments.ListFragment;
|
||||
import org.nuclearfog.twidda.ui.fragments.NotificationFragment;
|
||||
import org.nuclearfog.twidda.ui.fragments.StatusFragment;
|
||||
import org.nuclearfog.twidda.ui.fragments.TrendFragment;
|
||||
import org.nuclearfog.twidda.ui.fragments.UserFragment;
|
||||
|
@ -95,15 +95,12 @@ public class FragmentAdapter extends FragmentStatePagerAdapter {
|
|||
*/
|
||||
public void setupForHomePage() {
|
||||
Bundle paramHomeTl = new Bundle();
|
||||
Bundle paramMention = new Bundle();
|
||||
paramHomeTl.putInt(KEY_STATUS_FRAGMENT_MODE, STATUS_FRAGMENT_HOME);
|
||||
paramMention.putInt(KEY_STATUS_FRAGMENT_MODE, STATUS_FRAGMENT_MENTION);
|
||||
fragments = new ListFragment[3];
|
||||
fragments[0] = new StatusFragment();
|
||||
fragments[1] = new TrendFragment();
|
||||
fragments[2] = new StatusFragment();
|
||||
fragments[2] = new NotificationFragment();
|
||||
fragments[0].setArguments(paramHomeTl);
|
||||
fragments[2].setArguments(paramMention);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
package org.nuclearfog.twidda.adapter;
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder.OnHolderClickListener;
|
||||
import org.nuclearfog.twidda.adapter.holder.StatusHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.StatusHolder.OnStatusClickListener;
|
||||
import org.nuclearfog.twidda.adapter.holder.UserHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.UserHolder.OnUserClickListener;
|
||||
import org.nuclearfog.twidda.backend.utils.PicassoBuilder;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.Notification;
|
||||
import org.nuclearfog.twidda.model.Status;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Rycyclerview adapter for notifications
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class NotificationAdapter extends Adapter<ViewHolder> implements OnStatusClickListener, OnUserClickListener, OnHolderClickListener {
|
||||
|
||||
/**
|
||||
* Minimum count of new statuses to insert a placeholder.
|
||||
*/
|
||||
private static final int MIN_COUNT = 2;
|
||||
|
||||
private static final int NO_LOADING = -1;
|
||||
|
||||
/**
|
||||
* notification placeholder
|
||||
*/
|
||||
private static final int TYPE_PLACEHOLER = 0;
|
||||
|
||||
/**
|
||||
* notifcation type for statuses
|
||||
*/
|
||||
private static final int TYPE_STATUS = 1;
|
||||
|
||||
/**
|
||||
* notification type for users
|
||||
*/
|
||||
private static final int TYPE_USER = 2;
|
||||
|
||||
private Picasso picasso;
|
||||
private GlobalSettings settings;
|
||||
private OnNotificationClickListener listener;
|
||||
|
||||
private List<Notification> items = new LinkedList<>();
|
||||
private int loadingIndex = NO_LOADING;
|
||||
|
||||
|
||||
public NotificationAdapter(Context context, OnNotificationClickListener listener) {
|
||||
settings = GlobalSettings.getInstance(context);
|
||||
picasso = PicassoBuilder.get(context);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == TYPE_STATUS) {
|
||||
StatusHolder holder = new StatusHolder(parent, settings, picasso);
|
||||
holder.setOnStatusClickListener(this);
|
||||
return holder;
|
||||
} else if (viewType == TYPE_USER) {
|
||||
final UserHolder holder = new UserHolder(parent, settings, picasso);
|
||||
holder.setOnUserClickListener(this);
|
||||
return holder;
|
||||
} else {
|
||||
final PlaceHolder placeHolder = new PlaceHolder(parent, settings, false);
|
||||
placeHolder.loadBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = placeHolder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
long sinceId = 0;
|
||||
long maxId = 0;
|
||||
if (position == 0) {
|
||||
Notification item = items.get(position + 1);
|
||||
if (item != null) {
|
||||
sinceId = item.getId();
|
||||
}
|
||||
} else if (position == items.size() - 1) {
|
||||
Notification item = items.get(position - 1);
|
||||
if (item != null) {
|
||||
maxId = item.getId() - 1;
|
||||
}
|
||||
} else {
|
||||
Notification item = items.get(position + 1);
|
||||
if (item != null) {
|
||||
sinceId = item.getId();
|
||||
}
|
||||
item = items.get(position - 1);
|
||||
if (item != null) {
|
||||
maxId = item.getId() - 1;
|
||||
}
|
||||
}
|
||||
boolean success = listener.onPlaceholderClick(sinceId, maxId, position);
|
||||
if (success) {
|
||||
placeHolder.setLoading(true);
|
||||
loadingIndex = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return placeHolder;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Notification item = items.get(position);
|
||||
if (item != null) {
|
||||
if (holder instanceof StatusHolder && item.getStatus() != null) {
|
||||
StatusHolder statusHolder = (StatusHolder) holder;
|
||||
statusHolder.setContent(item.getStatus());
|
||||
statusHolder.setLabel(item);
|
||||
} else if (holder instanceof UserHolder && item.getUser() != null) {
|
||||
UserHolder userHolder = (UserHolder) holder;
|
||||
userHolder.setContent(item.getUser());
|
||||
userHolder.setLabel(item);
|
||||
}
|
||||
} else if (holder instanceof PlaceHolder) {
|
||||
PlaceHolder placeHolder = (PlaceHolder) holder;
|
||||
placeHolder.setLoading(loadingIndex == position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
Notification item = items.get(position);
|
||||
if (item == null)
|
||||
return TYPE_PLACEHOLER;
|
||||
switch (item.getType()) {
|
||||
default:
|
||||
return TYPE_PLACEHOLER;
|
||||
|
||||
case Notification.TYPE_FAVORITE:
|
||||
case Notification.TYPE_MENTION:
|
||||
case Notification.TYPE_REPOST:
|
||||
case Notification.TYPE_POLL:
|
||||
case Notification.TYPE_STATUS:
|
||||
case Notification.TYPE_UPDATE:
|
||||
return TYPE_STATUS;
|
||||
|
||||
case Notification.TYPE_FOLLOW:
|
||||
case Notification.TYPE_REQUEST:
|
||||
return TYPE_USER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onHolderClick(int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStatusClick(int position, int type) {
|
||||
Notification item = items.get(position);
|
||||
switch (type) {
|
||||
case OnStatusClickListener.TYPE_LABEL:
|
||||
if (item != null && item.getUser() != null) {
|
||||
listener.onUserClick(item.getUser());
|
||||
}
|
||||
break;
|
||||
|
||||
case OnStatusClickListener.TYPE_STATUS:
|
||||
if (item != null && item.getStatus() != null) {
|
||||
listener.onStatusClick(item.getStatus());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onUserClick(int position, int type) {
|
||||
Notification item = items.get(position);
|
||||
if (type == OnUserClickListener.ITEM_CLICK) {
|
||||
if (item != null && item.getUser() != null) {
|
||||
listener.onUserClick(item.getUser());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add new items at specific position
|
||||
*
|
||||
* @param newItems items to add
|
||||
* @param index position where to add the items
|
||||
*/
|
||||
public void addItems(List<Notification> newItems, int index) {
|
||||
disableLoading();
|
||||
if (newItems.size() > MIN_COUNT) {
|
||||
if (items.isEmpty() || items.get(index) != null) {
|
||||
// Add placeholder
|
||||
items.add(index, null);
|
||||
notifyItemInserted(index);
|
||||
}
|
||||
} else {
|
||||
if (!items.isEmpty() && items.get(index) == null) {
|
||||
// remove placeholder
|
||||
items.remove(index);
|
||||
notifyItemRemoved(index);
|
||||
}
|
||||
}
|
||||
if (!newItems.isEmpty()) {
|
||||
items.addAll(index, newItems);
|
||||
notifyItemRangeInserted(index, newItems.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* disable placeholder load animation
|
||||
*/
|
||||
public void disableLoading() {
|
||||
if (loadingIndex != NO_LOADING) {
|
||||
int oldIndex = loadingIndex;
|
||||
loadingIndex = NO_LOADING;
|
||||
notifyItemChanged(oldIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if adapter is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return items.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* notification item listener
|
||||
*/
|
||||
public interface OnNotificationClickListener {
|
||||
|
||||
/**
|
||||
* called on status item click
|
||||
*
|
||||
* @param status clicked status
|
||||
*/
|
||||
void onStatusClick(Status status);
|
||||
|
||||
/**
|
||||
* called on user item click
|
||||
*
|
||||
* @param user clicked user
|
||||
*/
|
||||
void onUserClick(User user);
|
||||
|
||||
/**
|
||||
* called on placeholder click
|
||||
*
|
||||
* @param sinceId notification ID below the placeholder
|
||||
* @param maxId notification ID over the placeholder
|
||||
* @param position position of the placeholder
|
||||
* @return true to enable loading animation
|
||||
*/
|
||||
boolean onPlaceholderClick(long sinceId, long maxId, long position);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,8 @@
|
|||
package org.nuclearfog.twidda.adapter;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_ID;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.Spanned;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -18,30 +11,25 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
|||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.tag.Tagger;
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder.OnHolderClickListener;
|
||||
import org.nuclearfog.twidda.adapter.holder.StatusHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.StatusHolder.OnStatusClickListener;
|
||||
import org.nuclearfog.twidda.backend.utils.PicassoBuilder;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.Status;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
import org.nuclearfog.twidda.ui.fragments.StatusFragment;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||
|
||||
/**
|
||||
* custom {@link androidx.recyclerview.widget.RecyclerView} adapter to show statuses
|
||||
*
|
||||
* @author nuclearfog
|
||||
* @see StatusFragment
|
||||
*/
|
||||
public class StatusAdapter extends Adapter<ViewHolder> {
|
||||
public class StatusAdapter extends Adapter<ViewHolder> implements OnStatusClickListener, OnHolderClickListener {
|
||||
|
||||
/**
|
||||
* index of {@link #loadingIndex} if no index is defined
|
||||
|
@ -63,18 +51,12 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
*/
|
||||
private static final int MIN_COUNT = 2;
|
||||
|
||||
/**
|
||||
* Locale specific number format
|
||||
*/
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
|
||||
private StatusSelectListener itemClickListener;
|
||||
private GlobalSettings settings;
|
||||
private Resources resources;
|
||||
private Picasso picasso;
|
||||
|
||||
private final List<Status> statuses = new LinkedList<>();
|
||||
private final List<Status> items = new LinkedList<>();
|
||||
private int loadingIndex = NO_LOADING;
|
||||
|
||||
/**
|
||||
|
@ -84,13 +66,12 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
this.itemClickListener = itemClickListener;
|
||||
settings = GlobalSettings.getInstance(context);
|
||||
picasso = PicassoBuilder.get(context);
|
||||
resources = context.getResources();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getItemId(int index) {
|
||||
Status status = statuses.get(index);
|
||||
Status status = items.get(index);
|
||||
if (status != null)
|
||||
return status.getId();
|
||||
return NO_ID;
|
||||
|
@ -99,13 +80,13 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return statuses.size();
|
||||
return items.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int index) {
|
||||
if (statuses.get(index) == null)
|
||||
if (items.get(index) == null)
|
||||
return VIEW_PLACEHOLDER;
|
||||
return VIEW_STATUS;
|
||||
}
|
||||
|
@ -115,57 +96,12 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == VIEW_STATUS) {
|
||||
final StatusHolder vh = new StatusHolder(parent, settings);
|
||||
vh.itemView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = vh.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
Status status = statuses.get(position);
|
||||
if (status != null) {
|
||||
itemClickListener.onStatusSelected(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
StatusHolder vh = new StatusHolder(parent, settings, picasso);
|
||||
vh.setOnStatusClickListener(this);
|
||||
return vh;
|
||||
} else {
|
||||
final PlaceHolder placeHolder = new PlaceHolder(parent, settings, false);
|
||||
placeHolder.loadBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = placeHolder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
long sinceId = 0;
|
||||
long maxId = 0;
|
||||
if (position == 0) {
|
||||
Status status = statuses.get(position + 1);
|
||||
if (status != null) {
|
||||
sinceId = status.getId();
|
||||
}
|
||||
} else if (position == statuses.size() - 1) {
|
||||
Status status = statuses.get(position - 1);
|
||||
if (status != null) {
|
||||
maxId = status.getId() - 1;
|
||||
}
|
||||
} else {
|
||||
Status status = statuses.get(position + 1);
|
||||
if (status != null) {
|
||||
sinceId = status.getId();
|
||||
}
|
||||
status = statuses.get(position - 1);
|
||||
if (status != null) {
|
||||
maxId = status.getId() - 1;
|
||||
}
|
||||
}
|
||||
boolean success = itemClickListener.onPlaceholderClick(sinceId, maxId, position);
|
||||
if (success) {
|
||||
placeHolder.setLoading(true);
|
||||
loadingIndex = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
PlaceHolder placeHolder = new PlaceHolder(parent, settings, false);
|
||||
placeHolder.setOnHolderClickListener(this);
|
||||
return placeHolder;
|
||||
}
|
||||
}
|
||||
|
@ -174,94 +110,9 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int index) {
|
||||
if (holder instanceof StatusHolder) {
|
||||
Status status = statuses.get(index);
|
||||
Status status = items.get(index);
|
||||
if (status != null) {
|
||||
StatusHolder statusHolder = (StatusHolder) holder;
|
||||
User user = status.getAuthor();
|
||||
if (status.getEmbeddedStatus() != null) {
|
||||
statusHolder.reposter.setText(user.getScreenname());
|
||||
statusHolder.reposter.setVisibility(VISIBLE);
|
||||
statusHolder.rpUser.setVisibility(VISIBLE);
|
||||
status = status.getEmbeddedStatus();
|
||||
user = status.getAuthor();
|
||||
} else {
|
||||
statusHolder.reposter.setVisibility(GONE);
|
||||
statusHolder.rpUser.setVisibility(GONE);
|
||||
}
|
||||
statusHolder.username.setText(user.getUsername());
|
||||
statusHolder.screenname.setText(user.getScreenname());
|
||||
statusHolder.repost.setText(NUM_FORMAT.format(status.getRepostCount()));
|
||||
statusHolder.favorite.setText(NUM_FORMAT.format(status.getFavoriteCount()));
|
||||
statusHolder.created.setText(StringTools.formatCreationTime(resources, status.getTimestamp()));
|
||||
if (!status.getText().isEmpty()) {
|
||||
Spanned text = Tagger.makeTextWithLinks(status.getText(), settings.getHighlightColor());
|
||||
statusHolder.text.setText(text);
|
||||
statusHolder.text.setVisibility(VISIBLE);
|
||||
} else {
|
||||
statusHolder.text.setVisibility(GONE);
|
||||
}
|
||||
if (status.isReposted()) {
|
||||
statusHolder.rtIcon.setColorFilter(settings.getRepostIconColor());
|
||||
} else {
|
||||
statusHolder.rtIcon.setColorFilter(settings.getIconColor());
|
||||
}
|
||||
if (status.isFavorited()) {
|
||||
statusHolder.favIcon.setColorFilter(settings.getFavoriteIconColor());
|
||||
} else {
|
||||
statusHolder.favIcon.setColorFilter(settings.getIconColor());
|
||||
}
|
||||
if (user.isVerified()) {
|
||||
statusHolder.verifiedIcon.setVisibility(VISIBLE);
|
||||
} else {
|
||||
statusHolder.verifiedIcon.setVisibility(GONE);
|
||||
}
|
||||
if (user.isProtected()) {
|
||||
statusHolder.lockedIcon.setVisibility(VISIBLE);
|
||||
} else {
|
||||
statusHolder.lockedIcon.setVisibility(GONE);
|
||||
}
|
||||
if (settings.imagesEnabled() && !user.getImageUrl().isEmpty()) {
|
||||
String profileImageUrl;
|
||||
if (!user.hasDefaultProfileImage()) {
|
||||
profileImageUrl = StringTools.buildImageLink(user.getImageUrl(), settings.getImageSuffix());
|
||||
} else {
|
||||
profileImageUrl = user.getImageUrl();
|
||||
}
|
||||
picasso.load(profileImageUrl).transform(new RoundedCornersTransformation(2, 0)).error(R.drawable.no_image).into(statusHolder.profile);
|
||||
} else {
|
||||
statusHolder.profile.setImageResource(0);
|
||||
}
|
||||
if (status.getRepliedStatusId() > 0) {
|
||||
statusHolder.replyIcon.setVisibility(VISIBLE);
|
||||
statusHolder.replyname.setVisibility(VISIBLE);
|
||||
statusHolder.replyname.setText(status.getReplyName());
|
||||
} else {
|
||||
statusHolder.replyIcon.setVisibility(GONE);
|
||||
statusHolder.replyname.setVisibility(GONE);
|
||||
}
|
||||
if (settings.statusIndicatorsEnabled()) {
|
||||
if (status.getLocationName() != null && !status.getLocationName().isEmpty()) {
|
||||
statusHolder.location.setVisibility(VISIBLE);
|
||||
} else {
|
||||
statusHolder.location.setVisibility(GONE);
|
||||
}
|
||||
if (status.getMediaType() != Status.MEDIA_NONE) {
|
||||
if (status.getMediaType() == Status.MEDIA_PHOTO) {
|
||||
statusHolder.media.setImageResource(R.drawable.image);
|
||||
} else if (status.getMediaType() == Status.MEDIA_VIDEO) {
|
||||
statusHolder.media.setImageResource(R.drawable.video);
|
||||
} else if (status.getMediaType() == Status.MEDIA_GIF) {
|
||||
statusHolder.media.setImageResource(R.drawable.gif);
|
||||
}
|
||||
statusHolder.media.setColorFilter(settings.getIconColor());
|
||||
statusHolder.media.setVisibility(VISIBLE);
|
||||
} else {
|
||||
statusHolder.media.setVisibility(GONE);
|
||||
}
|
||||
} else {
|
||||
statusHolder.location.setVisibility(GONE);
|
||||
statusHolder.media.setVisibility(GONE);
|
||||
}
|
||||
((StatusHolder) holder).setContent(status);
|
||||
}
|
||||
} else if (holder instanceof PlaceHolder) {
|
||||
PlaceHolder placeHolder = (PlaceHolder) holder;
|
||||
|
@ -269,43 +120,87 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onHolderClick(int position) {
|
||||
long sinceId = 0;
|
||||
long maxId = 0;
|
||||
if (position == 0) {
|
||||
Status status = items.get(position + 1);
|
||||
if (status != null) {
|
||||
sinceId = status.getId();
|
||||
}
|
||||
} else if (position == items.size() - 1) {
|
||||
Status status = items.get(position - 1);
|
||||
if (status != null) {
|
||||
maxId = status.getId() - 1;
|
||||
}
|
||||
} else {
|
||||
Status status = items.get(position + 1);
|
||||
if (status != null) {
|
||||
sinceId = status.getId();
|
||||
}
|
||||
status = items.get(position - 1);
|
||||
if (status != null) {
|
||||
maxId = status.getId() - 1;
|
||||
}
|
||||
}
|
||||
boolean success = itemClickListener.onPlaceholderClick(sinceId, maxId, position);
|
||||
if (success) {
|
||||
loadingIndex = position;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStatusClick(int position, int type) {
|
||||
if (type == OnStatusClickListener.TYPE_STATUS) {
|
||||
Status status = items.get(position);
|
||||
if (status != null) {
|
||||
itemClickListener.onStatusSelected(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert data at specific index of the list
|
||||
*
|
||||
* @param statuses list of statuses to insert
|
||||
* @param newItems list of statuses to insert
|
||||
* @param index position to insert
|
||||
*/
|
||||
public void addItems(@NonNull List<Status> statuses, int index) {
|
||||
public void addItems(@NonNull List<Status> newItems, int index) {
|
||||
disableLoading();
|
||||
if (statuses.size() > MIN_COUNT) {
|
||||
if (this.statuses.isEmpty() || this.statuses.get(index) != null) {
|
||||
if (newItems.size() > MIN_COUNT) {
|
||||
if (items.isEmpty() || items.get(index) != null) {
|
||||
// Add placeholder
|
||||
this.statuses.add(index, null);
|
||||
items.add(index, null);
|
||||
notifyItemInserted(index);
|
||||
}
|
||||
} else {
|
||||
if (!this.statuses.isEmpty() && this.statuses.get(index) == null) {
|
||||
if (!items.isEmpty() && items.get(index) == null) {
|
||||
// remove placeholder
|
||||
this.statuses.remove(index);
|
||||
items.remove(index);
|
||||
notifyItemRemoved(index);
|
||||
}
|
||||
}
|
||||
if (!statuses.isEmpty()) {
|
||||
this.statuses.addAll(index, statuses);
|
||||
notifyItemRangeInserted(index, statuses.size());
|
||||
if (!newItems.isEmpty()) {
|
||||
items.addAll(index, newItems);
|
||||
notifyItemRangeInserted(index, newItems.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all items in the list
|
||||
*
|
||||
* @param statuses list of statuses to add
|
||||
* @param newItems list of statuses to add
|
||||
*/
|
||||
public void replaceItems(@NonNull List<Status> statuses) {
|
||||
this.statuses.clear();
|
||||
this.statuses.addAll(statuses);
|
||||
if (statuses.size() > MIN_COUNT) {
|
||||
this.statuses.add(null);
|
||||
public void replaceItems(@NonNull List<Status> newItems) {
|
||||
items.clear();
|
||||
items.addAll(newItems);
|
||||
if (newItems.size() > MIN_COUNT) {
|
||||
items.add(null);
|
||||
}
|
||||
loadingIndex = NO_LOADING;
|
||||
notifyDataSetChanged();
|
||||
|
@ -317,9 +212,9 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
* @param status status to update
|
||||
*/
|
||||
public void updateItem(Status status) {
|
||||
int index = statuses.indexOf(status);
|
||||
int index = items.indexOf(status);
|
||||
if (index >= 0) {
|
||||
statuses.set(index, status);
|
||||
items.set(index, status);
|
||||
notifyItemChanged(index);
|
||||
}
|
||||
}
|
||||
|
@ -330,13 +225,13 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
* @param id ID of the status
|
||||
*/
|
||||
public void removeItem(long id) {
|
||||
for (int pos = statuses.size() - 1; pos >= 0; pos--) {
|
||||
Status status = statuses.get(pos);
|
||||
for (int pos = items.size() - 1; pos >= 0; pos--) {
|
||||
Status status = items.get(pos);
|
||||
if (status != null) {
|
||||
Status embedded = status.getEmbeddedStatus();
|
||||
// remove status and any repost of it
|
||||
if (status.getId() == id || (embedded != null && embedded.getId() == id)) {
|
||||
statuses.remove(pos);
|
||||
items.remove(pos);
|
||||
notifyItemRemoved(pos);
|
||||
}
|
||||
}
|
||||
|
@ -349,7 +244,7 @@ public class StatusAdapter extends Adapter<ViewHolder> {
|
|||
* @return true if list is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return statuses.isEmpty();
|
||||
return items.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,24 +1,16 @@
|
|||
package org.nuclearfog.twidda.adapter;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.holder.TrendHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.TrendHolder.OnTrendClickListener;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.Trend;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -28,18 +20,13 @@ import java.util.List;
|
|||
* @author nuclearfog
|
||||
* @see org.nuclearfog.twidda.ui.fragments.TrendFragment
|
||||
*/
|
||||
public class TrendAdapter extends Adapter<ViewHolder> {
|
||||
public class TrendAdapter extends Adapter<ViewHolder> implements OnTrendClickListener {
|
||||
|
||||
/**
|
||||
* trend limit
|
||||
*/
|
||||
private static final int INIT_COUNT = 50;
|
||||
|
||||
/**
|
||||
* Locale specific number format
|
||||
*/
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
private TrendClickListener itemClickListener;
|
||||
private GlobalSettings settings;
|
||||
|
||||
|
@ -64,15 +51,7 @@ public class TrendAdapter extends Adapter<ViewHolder> {
|
|||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
final TrendHolder vh = new TrendHolder(parent, settings);
|
||||
vh.itemView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = vh.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
itemClickListener.onTrendClick(trends.get(position));
|
||||
}
|
||||
}
|
||||
});
|
||||
vh.setOnTrendClickListener(this);
|
||||
return vh;
|
||||
}
|
||||
|
||||
|
@ -81,16 +60,13 @@ public class TrendAdapter extends Adapter<ViewHolder> {
|
|||
public void onBindViewHolder(@NonNull ViewHolder vh, int index) {
|
||||
TrendHolder holder = (TrendHolder) vh;
|
||||
Trend trend = trends.get(index);
|
||||
holder.rank.setText(trend.getRank() + ".");
|
||||
holder.name.setText(trend.getName());
|
||||
if (trend.getPopularity() > 0) {
|
||||
Resources resources = holder.vol.getContext().getResources();
|
||||
String trendVol = NUM_FORMAT.format(trend.getPopularity()) + " " + resources.getString(R.string.trend_range);
|
||||
holder.vol.setText(trendVol);
|
||||
holder.vol.setVisibility(VISIBLE);
|
||||
} else {
|
||||
holder.vol.setVisibility(GONE);
|
||||
}
|
||||
holder.setContent(trend);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTrendClick(int position) {
|
||||
itemClickListener.onTrendClick(trends.get(position));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
package org.nuclearfog.twidda.adapter;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_ID;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -16,26 +11,22 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
|||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder.OnHolderClickListener;
|
||||
import org.nuclearfog.twidda.adapter.holder.UserHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.UserHolder.OnUserClickListener;
|
||||
import org.nuclearfog.twidda.backend.lists.Users;
|
||||
import org.nuclearfog.twidda.backend.utils.PicassoBuilder;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||
|
||||
/**
|
||||
* custom {@link androidx.recyclerview.widget.RecyclerView} adapter implementation to show users
|
||||
*
|
||||
* @author nuclearfog
|
||||
* @see org.nuclearfog.twidda.ui.fragments.UserFragment
|
||||
*/
|
||||
public class UserAdapter extends Adapter<ViewHolder> {
|
||||
public class UserAdapter extends Adapter<ViewHolder> implements OnUserClickListener, OnHolderClickListener {
|
||||
|
||||
/**
|
||||
* index of {@link #loadingIndex} if no index is defined
|
||||
|
@ -52,10 +43,7 @@ public class UserAdapter extends Adapter<ViewHolder> {
|
|||
*/
|
||||
private static final int ITEM_GAP = 1;
|
||||
|
||||
/**
|
||||
* locale specific number formatter
|
||||
*/
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
|
||||
private GlobalSettings settings;
|
||||
private Picasso picasso;
|
||||
|
@ -105,52 +93,12 @@ public class UserAdapter extends Adapter<ViewHolder> {
|
|||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == ITEM_USER) {
|
||||
final UserHolder vh = new UserHolder(parent, settings);
|
||||
vh.itemView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = vh.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
User user = users.get(position);
|
||||
if (user != null) {
|
||||
listener.onUserClick(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (enableDelete) {
|
||||
vh.delete.setVisibility(VISIBLE);
|
||||
vh.delete.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = vh.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
User user = users.get(position);
|
||||
if (user != null) {
|
||||
listener.onDelete(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
vh.delete.setVisibility(GONE);
|
||||
}
|
||||
UserHolder vh = new UserHolder(parent, settings, picasso);
|
||||
vh.setOnUserClickListener(this);
|
||||
return vh;
|
||||
} else {
|
||||
final PlaceHolder placeHolder = new PlaceHolder(parent, settings, false);
|
||||
placeHolder.loadBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = placeHolder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
boolean actionPerformed = listener.onPlaceholderClick(users.getNext());
|
||||
if (actionPerformed) {
|
||||
placeHolder.setLoading(true);
|
||||
loadingIndex = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
PlaceHolder placeHolder = new PlaceHolder(parent, settings, false);
|
||||
placeHolder.setOnHolderClickListener(this);
|
||||
return placeHolder;
|
||||
}
|
||||
}
|
||||
|
@ -161,32 +109,7 @@ public class UserAdapter extends Adapter<ViewHolder> {
|
|||
if (holder instanceof UserHolder) {
|
||||
User user = users.get(index);
|
||||
if (user != null) {
|
||||
UserHolder userholder = (UserHolder) holder;
|
||||
userholder.username.setText(user.getUsername());
|
||||
userholder.screenname.setText(user.getScreenname());
|
||||
userholder.followingCount.setText(NUM_FORMAT.format(user.getFollowing()));
|
||||
userholder.followerCount.setText(NUM_FORMAT.format(user.getFollower()));
|
||||
if (user.isVerified()) {
|
||||
userholder.verifyIcon.setVisibility(VISIBLE);
|
||||
} else {
|
||||
userholder.verifyIcon.setVisibility(GONE);
|
||||
}
|
||||
if (user.isProtected()) {
|
||||
userholder.lockedIcon.setVisibility(VISIBLE);
|
||||
} else {
|
||||
userholder.lockedIcon.setVisibility(GONE);
|
||||
}
|
||||
if (settings.imagesEnabled() && !user.getImageUrl().isEmpty()) {
|
||||
String profileImageUrl;
|
||||
if (!user.hasDefaultProfileImage()) {
|
||||
profileImageUrl = StringTools.buildImageLink(user.getImageUrl(), settings.getImageSuffix());
|
||||
} else {
|
||||
profileImageUrl = user.getImageUrl();
|
||||
}
|
||||
picasso.load(profileImageUrl).transform(new RoundedCornersTransformation(2, 0)).error(R.drawable.no_image).into(userholder.profileImg);
|
||||
} else {
|
||||
userholder.profileImg.setImageResource(0);
|
||||
}
|
||||
((UserHolder) holder).setContent(user);
|
||||
}
|
||||
} else if (holder instanceof PlaceHolder) {
|
||||
PlaceHolder placeHolder = (PlaceHolder) holder;
|
||||
|
@ -194,6 +117,37 @@ public class UserAdapter extends Adapter<ViewHolder> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onHolderClick(int position) {
|
||||
boolean actionPerformed = listener.onPlaceholderClick(users.getNext());
|
||||
if (actionPerformed) {
|
||||
loadingIndex = position;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onUserClick(int position, int type) {
|
||||
switch (type) {
|
||||
case OnUserClickListener.ITEM_CLICK:
|
||||
User user = users.get(position);
|
||||
if (user != null) {
|
||||
listener.onUserClick(user);
|
||||
}
|
||||
break;
|
||||
|
||||
case OnUserClickListener.ITEM_REMOVE:
|
||||
user = users.get(position);
|
||||
if (enableDelete && user != null) {
|
||||
listener.onDelete(user);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* insert an user list depending on cursor to the top or bottom
|
||||
*
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
package org.nuclearfog.twidda.adapter;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -16,27 +9,23 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
|||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.PlaceHolder.OnHolderClickListener;
|
||||
import org.nuclearfog.twidda.adapter.holder.UserlistHolder;
|
||||
import org.nuclearfog.twidda.adapter.holder.UserlistHolder.OnListClickListener;
|
||||
import org.nuclearfog.twidda.backend.lists.UserLists;
|
||||
import org.nuclearfog.twidda.backend.utils.PicassoBuilder;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
import org.nuclearfog.twidda.model.UserList;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||
|
||||
/**
|
||||
* custom {@link androidx.recyclerview.widget.RecyclerView} adapter implementation to show userlists
|
||||
*
|
||||
* @author nuclearfog
|
||||
* @see org.nuclearfog.twidda.ui.fragments.UserListFragment
|
||||
*/
|
||||
public class UserlistAdapter extends Adapter<ViewHolder> {
|
||||
public class UserlistAdapter extends Adapter<ViewHolder> implements OnListClickListener, OnHolderClickListener {
|
||||
|
||||
/**
|
||||
* indicator if there is no loading progress
|
||||
|
@ -56,11 +45,9 @@ public class UserlistAdapter extends Adapter<ViewHolder> {
|
|||
/**
|
||||
* locale specific number format
|
||||
*/
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
private ListClickListener listener;
|
||||
private GlobalSettings settings;
|
||||
private Resources resources;
|
||||
private Picasso picasso;
|
||||
|
||||
private UserLists userlists = new UserLists(0L, 0L);
|
||||
|
@ -74,7 +61,6 @@ public class UserlistAdapter extends Adapter<ViewHolder> {
|
|||
this.listener = listener;
|
||||
settings = GlobalSettings.getInstance(context);
|
||||
picasso = PicassoBuilder.get(context);
|
||||
resources = context.getResources();
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,47 +82,10 @@ public class UserlistAdapter extends Adapter<ViewHolder> {
|
|||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == ITEM_LIST) {
|
||||
final UserlistHolder itemHolder = new UserlistHolder(parent, settings);
|
||||
itemHolder.profile.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = itemHolder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
UserList item = userlists.get(position);
|
||||
if (item != null) {
|
||||
listener.onProfileClick(item.getListOwner());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
itemHolder.itemView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = itemHolder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
UserList item = userlists.get(position);
|
||||
if (item != null) {
|
||||
listener.onListClick(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return itemHolder;
|
||||
return new UserlistHolder(parent, settings, picasso, this);
|
||||
} else {
|
||||
final PlaceHolder placeHolder = new PlaceHolder(parent, settings, false);
|
||||
placeHolder.loadBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = placeHolder.getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
boolean actionPerformed = listener.onPlaceholderClick(userlists.getNext());
|
||||
if (actionPerformed) {
|
||||
placeHolder.setLoading(true);
|
||||
loadingIndex = position;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
PlaceHolder placeHolder = new PlaceHolder(parent, settings, false);
|
||||
placeHolder.setOnHolderClickListener(this);
|
||||
return placeHolder;
|
||||
}
|
||||
}
|
||||
|
@ -148,47 +97,7 @@ public class UserlistAdapter extends Adapter<ViewHolder> {
|
|||
UserlistHolder vh = (UserlistHolder) holder;
|
||||
UserList item = userlists.get(index);
|
||||
if (item != null) {
|
||||
User owner = item.getListOwner();
|
||||
vh.title.setText(item.getTitle());
|
||||
vh.description.setText(item.getDescription());
|
||||
vh.username.setText(owner.getUsername());
|
||||
vh.screenname.setText(owner.getScreenname());
|
||||
vh.date.setText(StringTools.formatCreationTime(resources, item.getTimestamp()));
|
||||
vh.member.setText(NUM_FORMAT.format(item.getMemberCount()));
|
||||
vh.subscriber.setText(NUM_FORMAT.format(item.getSubscriberCount()));
|
||||
if (settings.imagesEnabled() && !owner.getImageUrl().isEmpty()) {
|
||||
String profileImageUrl;
|
||||
if (!owner.hasDefaultProfileImage()) {
|
||||
profileImageUrl = StringTools.buildImageLink(owner.getImageUrl(), settings.getImageSuffix());
|
||||
} else {
|
||||
profileImageUrl = owner.getImageUrl();
|
||||
}
|
||||
picasso.load(profileImageUrl).transform(new RoundedCornersTransformation(3, 0)).error(R.drawable.no_image).into(vh.profile);
|
||||
} else {
|
||||
vh.profile.setImageResource(0);
|
||||
}
|
||||
if (!item.getListOwner().isCurrentUser() && item.isFollowing()) {
|
||||
vh.follow.setVisibility(VISIBLE);
|
||||
vh.followList.setVisibility(VISIBLE);
|
||||
} else {
|
||||
vh.follow.setVisibility(GONE);
|
||||
vh.followList.setVisibility(GONE);
|
||||
}
|
||||
if (owner.isVerified()) {
|
||||
vh.verified.setVisibility(VISIBLE);
|
||||
} else {
|
||||
vh.verified.setVisibility(GONE);
|
||||
}
|
||||
if (owner.isProtected()) {
|
||||
vh.locked.setVisibility(VISIBLE);
|
||||
} else {
|
||||
vh.locked.setVisibility(GONE);
|
||||
}
|
||||
if (item.isPrivate()) {
|
||||
vh.privateList.setVisibility(VISIBLE);
|
||||
} else {
|
||||
vh.privateList.setVisibility(GONE);
|
||||
}
|
||||
vh.setContent(item);
|
||||
}
|
||||
} else if (holder instanceof PlaceHolder) {
|
||||
PlaceHolder placeHolder = (PlaceHolder) holder;
|
||||
|
@ -196,6 +105,32 @@ public class UserlistAdapter extends Adapter<ViewHolder> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onUserlistClick(int position, int type) {
|
||||
UserList item = userlists.get(position);
|
||||
if (item != null) {
|
||||
switch (type) {
|
||||
case OnListClickListener.LIST_CLICK:
|
||||
listener.onListClick(item);
|
||||
break;
|
||||
|
||||
case OnListClickListener.PROFILE_CLICK:
|
||||
listener.onProfileClick(item.getListOwner());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onHolderClick(int position) {
|
||||
boolean actionPerformed = listener.onPlaceholderClick(userlists.getNext());
|
||||
if (actionPerformed)
|
||||
loadingIndex = position;
|
||||
return actionPerformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds new data to the list
|
||||
*
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package org.nuclearfog.twidda.adapter.holder;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
@ -22,11 +23,13 @@ import org.nuclearfog.twidda.database.GlobalSettings;
|
|||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class PlaceHolder extends ViewHolder {
|
||||
public class PlaceHolder extends ViewHolder implements OnClickListener {
|
||||
|
||||
public final ProgressBar loadCircle;
|
||||
public final Button loadBtn;
|
||||
|
||||
private OnHolderClickListener listener;
|
||||
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
* @param horizontal true if placeholder orientation is horizontal
|
||||
|
@ -45,11 +48,24 @@ public class PlaceHolder extends ViewHolder {
|
|||
AppStyles.setProgressColor(loadCircle, settings.getHighlightColor());
|
||||
// enable extra views
|
||||
if (horizontal) {
|
||||
loadBtn.setVisibility(INVISIBLE);
|
||||
loadCircle.setVisibility(VISIBLE);
|
||||
loadBtn.setVisibility(View.INVISIBLE);
|
||||
loadCircle.setVisibility(View.VISIBLE);
|
||||
background.getLayoutParams().height = MATCH_PARENT;
|
||||
background.getLayoutParams().width = WRAP_CONTENT;
|
||||
}
|
||||
loadBtn.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == loadBtn) {
|
||||
int position = getLayoutPosition();
|
||||
if (position != NO_POSITION && listener != null) {
|
||||
boolean enableLoading = listener.onHolderClick(position);
|
||||
setLoading(enableLoading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,11 +75,31 @@ public class PlaceHolder extends ViewHolder {
|
|||
*/
|
||||
public void setLoading(boolean enable) {
|
||||
if (enable) {
|
||||
loadCircle.setVisibility(VISIBLE);
|
||||
loadBtn.setVisibility(INVISIBLE);
|
||||
loadCircle.setVisibility(View.VISIBLE);
|
||||
loadBtn.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
loadCircle.setVisibility(INVISIBLE);
|
||||
loadBtn.setVisibility(VISIBLE);
|
||||
loadCircle.setVisibility(View.INVISIBLE);
|
||||
loadBtn.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set click listener for this item
|
||||
*/
|
||||
public void setOnHolderClickListener(OnHolderClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* listener used to call after item click
|
||||
*/
|
||||
public interface OnHolderClickListener {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param position position of the item
|
||||
* @return true to enable loading animation
|
||||
*/
|
||||
boolean onHolderClick(int position);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,13 @@
|
|||
package org.nuclearfog.twidda.adapter.holder;
|
||||
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.text.Spanned;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
@ -8,10 +15,21 @@ import android.widget.TextView;
|
|||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.tag.Tagger;
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.adapter.StatusAdapter;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.Notification;
|
||||
import org.nuclearfog.twidda.model.Status;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||
|
||||
/**
|
||||
* Holder class for the status item view
|
||||
|
@ -19,19 +37,27 @@ import org.nuclearfog.twidda.database.GlobalSettings;
|
|||
* @author nuclearfog
|
||||
* @see StatusAdapter
|
||||
*/
|
||||
public class StatusHolder extends ViewHolder {
|
||||
public class StatusHolder extends ViewHolder implements OnClickListener {
|
||||
|
||||
public final ImageView profile, rpUser, verifiedIcon, lockedIcon, rtIcon, favIcon, media, location, replyIcon;
|
||||
public final TextView username, screenname, text, repost, favorite, reposter, created, replyname;
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
private ImageView profile, rpUser, verifiedIcon, lockedIcon, rtIcon, favIcon, media, location, replyIcon;
|
||||
private TextView username, screenname, text, repost, favorite, reposter, created, replyname, label;
|
||||
|
||||
private GlobalSettings settings;
|
||||
private Picasso picasso;
|
||||
|
||||
private OnStatusClickListener listener;
|
||||
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
* @param settings app settings to set theme
|
||||
*/
|
||||
public StatusHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
public StatusHolder(ViewGroup parent, GlobalSettings settings, Picasso picasso) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_status, parent, false));
|
||||
CardView cardLayout = (CardView) itemView;
|
||||
ViewGroup container = itemView.findViewById(R.id.item_status_container);
|
||||
label = itemView.findViewById(R.id.item_status_label);
|
||||
profile = itemView.findViewById(R.id.item_status_profile_image);
|
||||
verifiedIcon = itemView.findViewById(R.id.item_status_verified_icon);
|
||||
lockedIcon = itemView.findViewById(R.id.item_status_locked_icon);
|
||||
|
@ -57,5 +83,175 @@ public class StatusHolder extends ViewHolder {
|
|||
}
|
||||
AppStyles.setTheme(container, 0);
|
||||
cardLayout.setCardBackgroundColor(settings.getCardColor());
|
||||
this.settings = settings;
|
||||
this.picasso = picasso;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = getLayoutPosition();
|
||||
if (position != NO_POSITION && listener != null) {
|
||||
if (v == itemView) {
|
||||
listener.onStatusClick(position, OnStatusClickListener.TYPE_STATUS);
|
||||
} else if (v == label) {
|
||||
listener.onStatusClick(position, OnStatusClickListener.TYPE_LABEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set view content
|
||||
*
|
||||
* @param status content to show
|
||||
*/
|
||||
public void setContent(Status status) {
|
||||
User user = status.getAuthor();
|
||||
if (status.getEmbeddedStatus() != null) {
|
||||
reposter.setText(user.getScreenname());
|
||||
reposter.setVisibility(View.VISIBLE);
|
||||
rpUser.setVisibility(View.VISIBLE);
|
||||
status = status.getEmbeddedStatus();
|
||||
user = status.getAuthor();
|
||||
} else {
|
||||
reposter.setVisibility(View.GONE);
|
||||
rpUser.setVisibility(View.GONE);
|
||||
}
|
||||
username.setText(user.getUsername());
|
||||
screenname.setText(user.getScreenname());
|
||||
repost.setText(NUM_FORMAT.format(status.getRepostCount()));
|
||||
favorite.setText(NUM_FORMAT.format(status.getFavoriteCount()));
|
||||
created.setText(StringTools.formatCreationTime(itemView.getResources(), status.getTimestamp()));
|
||||
if (!status.getText().isEmpty()) {
|
||||
Spanned textSpan = Tagger.makeTextWithLinks(status.getText(), settings.getHighlightColor());
|
||||
text.setText(textSpan);
|
||||
text.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
text.setVisibility(View.GONE);
|
||||
}
|
||||
if (status.isReposted()) {
|
||||
rtIcon.setColorFilter(settings.getRepostIconColor());
|
||||
} else {
|
||||
rtIcon.setColorFilter(settings.getIconColor());
|
||||
}
|
||||
if (status.isFavorited()) {
|
||||
favIcon.setColorFilter(settings.getFavoriteIconColor());
|
||||
} else {
|
||||
favIcon.setColorFilter(settings.getIconColor());
|
||||
}
|
||||
if (user.isVerified()) {
|
||||
verifiedIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
verifiedIcon.setVisibility(View.GONE);
|
||||
}
|
||||
if (user.isProtected()) {
|
||||
lockedIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
lockedIcon.setVisibility(View.GONE);
|
||||
}
|
||||
if (settings.imagesEnabled() && !user.getImageUrl().isEmpty()) {
|
||||
String profileImageUrl;
|
||||
if (!user.hasDefaultProfileImage()) {
|
||||
profileImageUrl = StringTools.buildImageLink(user.getImageUrl(), settings.getImageSuffix());
|
||||
} else {
|
||||
profileImageUrl = user.getImageUrl();
|
||||
}
|
||||
picasso.load(profileImageUrl).transform(new RoundedCornersTransformation(2, 0)).error(R.drawable.no_image).into(profile);
|
||||
} else {
|
||||
profile.setImageResource(0);
|
||||
}
|
||||
if (status.getRepliedStatusId() > 0) {
|
||||
replyIcon.setVisibility(View.VISIBLE);
|
||||
replyname.setVisibility(View.VISIBLE);
|
||||
replyname.setText(status.getReplyName());
|
||||
} else {
|
||||
replyIcon.setVisibility(View.GONE);
|
||||
replyname.setVisibility(View.GONE);
|
||||
}
|
||||
if (settings.statusIndicatorsEnabled()) {
|
||||
if (status.getLocationName() != null && !status.getLocationName().isEmpty()) {
|
||||
location.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
location.setVisibility(View.GONE);
|
||||
}
|
||||
if (status.getMediaType() != Status.MEDIA_NONE) {
|
||||
if (status.getMediaType() == Status.MEDIA_PHOTO) {
|
||||
media.setImageResource(R.drawable.image);
|
||||
} else if (status.getMediaType() == Status.MEDIA_VIDEO) {
|
||||
media.setImageResource(R.drawable.video);
|
||||
} else if (status.getMediaType() == Status.MEDIA_GIF) {
|
||||
media.setImageResource(R.drawable.gif);
|
||||
}
|
||||
media.setColorFilter(settings.getIconColor());
|
||||
media.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
media.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
location.setVisibility(View.GONE);
|
||||
media.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set notification label
|
||||
*/
|
||||
public void setLabel(Notification notification) {
|
||||
int iconRes;
|
||||
String text, name;
|
||||
if (notification.getUser() != null)
|
||||
name = notification.getUser().getScreenname();
|
||||
else
|
||||
name = "";
|
||||
Resources resources = itemView.getResources();
|
||||
|
||||
switch (notification.getType()) {
|
||||
default:
|
||||
text = "";
|
||||
iconRes = 0;
|
||||
break;
|
||||
|
||||
case Notification.TYPE_MENTION:
|
||||
text = resources.getString(R.string.info_user_mention, name);
|
||||
iconRes = R.drawable.mention;
|
||||
break;
|
||||
|
||||
case Notification.TYPE_REPOST:
|
||||
text = resources.getString(R.string.info_user_repost, name);
|
||||
iconRes = R.drawable.repost;
|
||||
break;
|
||||
|
||||
case Notification.TYPE_FAVORITE:
|
||||
text = resources.getString(R.string.info_user_favorited, name);
|
||||
iconRes = R.drawable.favorite;
|
||||
break;
|
||||
}
|
||||
label.setVisibility(View.VISIBLE);
|
||||
label.setText(text);
|
||||
label.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0);
|
||||
AppStyles.setDrawableColor(label, settings.getIconColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* set item click listener
|
||||
*/
|
||||
public void setOnStatusClickListener(OnStatusClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* item click listener
|
||||
*/
|
||||
public interface OnStatusClickListener {
|
||||
|
||||
int TYPE_STATUS = 1;
|
||||
|
||||
int TYPE_LABEL = 2;
|
||||
|
||||
/**
|
||||
* @param position position of this item
|
||||
* @param type type of user click {@link #TYPE_LABEL,#TYPE_STATUS}
|
||||
*/
|
||||
void onStatusClick(int position, int type);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,12 @@
|
|||
package org.nuclearfog.twidda.adapter.holder;
|
||||
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -10,6 +16,9 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
|||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.Trend;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
/**
|
||||
* ViewHolder for a trend item
|
||||
|
@ -17,9 +26,16 @@ import org.nuclearfog.twidda.database.GlobalSettings;
|
|||
* @author nuclearfog
|
||||
* @see org.nuclearfog.twidda.adapter.TrendAdapter
|
||||
*/
|
||||
public class TrendHolder extends ViewHolder {
|
||||
public class TrendHolder extends ViewHolder implements OnClickListener {
|
||||
|
||||
public final TextView name, rank, vol;
|
||||
/**
|
||||
* Locale specific number format
|
||||
*/
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
private TextView name, rank, vol;
|
||||
|
||||
private OnTrendClickListener listener;
|
||||
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
|
@ -34,5 +50,53 @@ public class TrendHolder extends ViewHolder {
|
|||
|
||||
AppStyles.setTheme(container, 0);
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
itemView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == itemView) {
|
||||
int position = getLayoutPosition();
|
||||
if (position != NO_POSITION && listener != null) {
|
||||
listener.onTrendClick(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set item click listener
|
||||
*/
|
||||
public void setOnTrendClickListener(OnTrendClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* set view content
|
||||
*
|
||||
* @param trend content information
|
||||
*/
|
||||
public void setContent(Trend trend) {
|
||||
rank.setText(trend.getRank() + ".");
|
||||
name.setText(trend.getName());
|
||||
if (trend.getPopularity() > 0) {
|
||||
Resources resources = vol.getResources();
|
||||
String trendVol = NUM_FORMAT.format(trend.getPopularity()) + " " + resources.getString(R.string.trend_range);
|
||||
vol.setText(trendVol);
|
||||
vol.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
vol.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Item click listener
|
||||
*/
|
||||
public interface OnTrendClickListener {
|
||||
|
||||
/**
|
||||
* @param position index of the view holder
|
||||
*/
|
||||
void onTrendClick(int position);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,13 @@
|
|||
package org.nuclearfog.twidda.adapter.holder;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
|
@ -9,9 +16,18 @@ import android.widget.TextView;
|
|||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.Notification;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||
|
||||
/**
|
||||
* View holder class for user item
|
||||
|
@ -19,19 +35,30 @@ import org.nuclearfog.twidda.database.GlobalSettings;
|
|||
* @author nuclearfog
|
||||
* @see org.nuclearfog.twidda.adapter.UserAdapter
|
||||
*/
|
||||
public class UserHolder extends ViewHolder {
|
||||
public class UserHolder extends ViewHolder implements OnClickListener {
|
||||
|
||||
public final TextView username, screenname, followingCount, followerCount;
|
||||
public final ImageView profileImg, verifyIcon, lockedIcon;
|
||||
public final ImageButton delete;
|
||||
/**
|
||||
* locale specific number formatter
|
||||
*/
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
private TextView username, screenname, followingCount, followerCount, label;
|
||||
private ImageView profileImg, verifyIcon, lockedIcon;
|
||||
private ImageButton delete;
|
||||
|
||||
private GlobalSettings settings;
|
||||
private Picasso picasso;
|
||||
|
||||
private OnUserClickListener listener;
|
||||
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public UserHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
public UserHolder(ViewGroup parent, GlobalSettings settings, Picasso picasso) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user, parent, false));
|
||||
CardView background = (CardView) itemView;
|
||||
ViewGroup container = itemView.findViewById(R.id.item_user_container);
|
||||
label = itemView.findViewById(R.id.item_user_label);
|
||||
username = itemView.findViewById(R.id.item_user_username);
|
||||
screenname = itemView.findViewById(R.id.item_user_screenname);
|
||||
followingCount = itemView.findViewById(R.id.item_user_following_count);
|
||||
|
@ -43,5 +70,112 @@ public class UserHolder extends ViewHolder {
|
|||
|
||||
AppStyles.setTheme(container, 0);
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
this.settings = settings;
|
||||
this.picasso = picasso;
|
||||
|
||||
itemView.setOnClickListener(this);
|
||||
delete.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = getLayoutPosition();
|
||||
if (listener != null && position != NO_POSITION) {
|
||||
if (v == itemView) {
|
||||
listener.onUserClick(position, OnUserClickListener.ITEM_CLICK);
|
||||
} else if (v == delete) {
|
||||
listener.onUserClick(position, OnUserClickListener.ITEM_REMOVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set item click listener
|
||||
*/
|
||||
public void setOnUserClickListener(OnUserClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* set user information
|
||||
*
|
||||
* @param user user information
|
||||
*/
|
||||
public void setContent(User user) {
|
||||
username.setText(user.getUsername());
|
||||
screenname.setText(user.getScreenname());
|
||||
followingCount.setText(NUM_FORMAT.format(user.getFollowing()));
|
||||
followerCount.setText(NUM_FORMAT.format(user.getFollower()));
|
||||
if (user.isVerified()) {
|
||||
verifyIcon.setVisibility(VISIBLE);
|
||||
} else {
|
||||
verifyIcon.setVisibility(GONE);
|
||||
}
|
||||
if (user.isProtected()) {
|
||||
lockedIcon.setVisibility(VISIBLE);
|
||||
} else {
|
||||
lockedIcon.setVisibility(GONE);
|
||||
}
|
||||
if (settings.imagesEnabled() && !user.getImageUrl().isEmpty()) {
|
||||
String profileImageUrl;
|
||||
if (!user.hasDefaultProfileImage()) {
|
||||
profileImageUrl = StringTools.buildImageLink(user.getImageUrl(), settings.getImageSuffix());
|
||||
} else {
|
||||
profileImageUrl = user.getImageUrl();
|
||||
}
|
||||
picasso.load(profileImageUrl).transform(new RoundedCornersTransformation(2, 0)).error(R.drawable.no_image).into(profileImg);
|
||||
} else {
|
||||
profileImg.setImageResource(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set notification label
|
||||
*/
|
||||
public void setLabel(Notification notification) {
|
||||
int iconRes;
|
||||
String text, name;
|
||||
Resources resources = itemView.getResources();
|
||||
if (notification.getUser() != null)
|
||||
name = notification.getUser().getScreenname();
|
||||
else
|
||||
name = "";
|
||||
|
||||
switch (notification.getType()) {
|
||||
default:
|
||||
text = "";
|
||||
iconRes = 0;
|
||||
break;
|
||||
|
||||
case Notification.TYPE_FOLLOW:
|
||||
text = resources.getString(R.string.info_user_follow, name);
|
||||
iconRes = R.drawable.follower;
|
||||
break;
|
||||
|
||||
case Notification.TYPE_REQUEST:
|
||||
text = resources.getString(R.string.info_user_follow_request, name);
|
||||
iconRes = R.drawable.follower_request;
|
||||
break;
|
||||
}
|
||||
label.setVisibility(VISIBLE);
|
||||
label.setCompoundDrawablesWithIntrinsicBounds(iconRes, 0, 0, 0);
|
||||
label.setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Item click listener
|
||||
*/
|
||||
public interface OnUserClickListener {
|
||||
|
||||
int ITEM_CLICK = 1;
|
||||
|
||||
int ITEM_REMOVE = 2;
|
||||
|
||||
/**
|
||||
* @param position position of the item
|
||||
* @param type type of action {@link #ITEM_REMOVE,#ITEM_CLICK}
|
||||
*/
|
||||
void onUserClick(int position, int type);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
package org.nuclearfog.twidda.adapter.holder;
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
@ -8,9 +12,18 @@ import android.widget.TextView;
|
|||
import androidx.cardview.widget.CardView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.backend.utils.AppStyles;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.database.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
import org.nuclearfog.twidda.model.UserList;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||
|
||||
/**
|
||||
* view holder class for an user list item
|
||||
|
@ -18,15 +31,22 @@ import org.nuclearfog.twidda.database.GlobalSettings;
|
|||
* @author nuclearfog
|
||||
* @see org.nuclearfog.twidda.adapter.UserlistAdapter
|
||||
*/
|
||||
public class UserlistHolder extends ViewHolder {
|
||||
public class UserlistHolder extends ViewHolder implements OnClickListener {
|
||||
|
||||
private static final NumberFormat NUM_FORMAT = NumberFormat.getIntegerInstance();
|
||||
|
||||
public final ImageView profile, verified, locked, privateList, follow;
|
||||
public final TextView title, description, username, screenname, date, member, subscriber, followList;
|
||||
|
||||
private GlobalSettings settings;
|
||||
private Picasso picasso;
|
||||
|
||||
private OnListClickListener listener;
|
||||
|
||||
/**
|
||||
* @param parent Parent view from adapter
|
||||
*/
|
||||
public UserlistHolder(ViewGroup parent, GlobalSettings settings) {
|
||||
public UserlistHolder(ViewGroup parent, GlobalSettings settings, Picasso picasso, OnListClickListener listener) {
|
||||
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false));
|
||||
CardView background = (CardView) itemView;
|
||||
ViewGroup container = itemView.findViewById(R.id.item_list_container);
|
||||
|
@ -43,8 +63,90 @@ public class UserlistHolder extends ViewHolder {
|
|||
member = itemView.findViewById(R.id.item_list_member);
|
||||
subscriber = itemView.findViewById(R.id.item_list_subscriber);
|
||||
followList = itemView.findViewById(R.id.item_list_following_indicator);
|
||||
this.settings = settings;
|
||||
this.picasso = picasso;
|
||||
this.listener = listener;
|
||||
|
||||
AppStyles.setTheme(container, 0);
|
||||
background.setCardBackgroundColor(settings.getCardColor());
|
||||
|
||||
itemView.setOnClickListener(this);
|
||||
profile.setOnClickListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = getLayoutPosition();
|
||||
if (position != NO_POSITION) {
|
||||
if (v == itemView) {
|
||||
listener.onUserlistClick(position, OnListClickListener.LIST_CLICK);
|
||||
} else if (v == profile) {
|
||||
listener.onUserlistClick(position, OnListClickListener.PROFILE_CLICK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set view content
|
||||
*/
|
||||
public void setContent(UserList userlist) {
|
||||
User owner = userlist.getListOwner();
|
||||
title.setText(userlist.getTitle());
|
||||
description.setText(userlist.getDescription());
|
||||
username.setText(owner.getUsername());
|
||||
screenname.setText(owner.getScreenname());
|
||||
date.setText(StringTools.formatCreationTime(itemView.getResources(), userlist.getTimestamp()));
|
||||
member.setText(NUM_FORMAT.format(userlist.getMemberCount()));
|
||||
subscriber.setText(NUM_FORMAT.format(userlist.getSubscriberCount()));
|
||||
if (settings.imagesEnabled() && !owner.getImageUrl().isEmpty()) {
|
||||
String profileImageUrl;
|
||||
if (!owner.hasDefaultProfileImage()) {
|
||||
profileImageUrl = StringTools.buildImageLink(owner.getImageUrl(), settings.getImageSuffix());
|
||||
} else {
|
||||
profileImageUrl = owner.getImageUrl();
|
||||
}
|
||||
picasso.load(profileImageUrl).transform(new RoundedCornersTransformation(3, 0)).error(R.drawable.no_image).into(profile);
|
||||
} else {
|
||||
profile.setImageResource(0);
|
||||
}
|
||||
if (!userlist.getListOwner().isCurrentUser() && userlist.isFollowing()) {
|
||||
follow.setVisibility(View.VISIBLE);
|
||||
followList.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
follow.setVisibility(View.GONE);
|
||||
followList.setVisibility(View.GONE);
|
||||
}
|
||||
if (owner.isVerified()) {
|
||||
verified.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
verified.setVisibility(View.GONE);
|
||||
}
|
||||
if (owner.isProtected()) {
|
||||
locked.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
locked.setVisibility(View.GONE);
|
||||
}
|
||||
if (userlist.isPrivate()) {
|
||||
privateList.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
privateList.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* item click listener
|
||||
*/
|
||||
public interface OnListClickListener {
|
||||
|
||||
int LIST_CLICK = 1;
|
||||
|
||||
int PROFILE_CLICK = 2;
|
||||
|
||||
/**
|
||||
* @param position position of the item
|
||||
* @param type type of click
|
||||
*/
|
||||
void onUserlistClick(int position, int type);
|
||||
}
|
||||
}
|
|
@ -247,15 +247,6 @@ public interface Connection {
|
|||
*/
|
||||
List<Status> getHomeTimeline(long minId, long maxId) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* show current user's home timeline
|
||||
*
|
||||
* @param minId get statuses with ID above the min ID
|
||||
* @param maxId get statuses with ID under the max ID
|
||||
* @return list of statuses
|
||||
*/
|
||||
List<Status> getMentionTimeline(long minId, long maxId) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* show the timeline of an user
|
||||
*
|
||||
|
|
|
@ -392,28 +392,6 @@ public class Mastodon implements Connection {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Status> getMentionTimeline(long minId, long maxId) throws MastodonException {
|
||||
List<String> params = new ArrayList<>();
|
||||
params.add("since_id=" + minId);
|
||||
params.add("max_id=" + maxId);
|
||||
params.add("limit=" + settings.getListSize());
|
||||
params.add("types[]=mention");
|
||||
try {
|
||||
List<Notification> notifications = createNotifications(get(ENDPOINT_NOTIFICATION, params));
|
||||
List<Status> mentions = new ArrayList<>(notifications.size());
|
||||
for (Notification notification : notifications) {
|
||||
if (notification.getType() == Notification.TYPE_MENTION) {
|
||||
mentions.add(notification.getStatus());
|
||||
}
|
||||
}
|
||||
return mentions;
|
||||
} catch (IOException e) {
|
||||
throw new MastodonException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Status> getUserTimeline(long id, long minId, long maxId) throws MastodonException {
|
||||
String endpoint = ENDPOINT_USER_TIMELINE + id + "/statuses";
|
||||
|
@ -733,8 +711,10 @@ public class Mastodon implements Connection {
|
|||
@Override
|
||||
public List<Notification> getNotifications(long minId, long maxId) throws ConnectionException {
|
||||
List<String> params = new ArrayList<>();
|
||||
params.add("since_id=" + minId);
|
||||
params.add("max_id=" + maxId);
|
||||
if (minId > 0)
|
||||
params.add("since_id=" + minId);
|
||||
if (maxId > minId)
|
||||
params.add("max_id=" + maxId);
|
||||
params.add("limit=" + settings.getListSize());
|
||||
try {
|
||||
return createNotifications(get(ENDPOINT_NOTIFICATION, params));
|
||||
|
|
|
@ -42,7 +42,7 @@ public class MastodonUser implements User {
|
|||
*/
|
||||
public MastodonUser(JSONObject json) throws JSONException {
|
||||
String idStr = json.getString("id");
|
||||
screenname = json.optString("acct", "");
|
||||
screenname = '@' + json.optString("acct", "");
|
||||
username = json.optString("display_name");
|
||||
createdAt = StringTools.getTime(json.optString("created_at", ""), StringTools.TIME_MASTODON);
|
||||
profileUrl = json.optString("avatar");
|
||||
|
|
|
@ -558,17 +558,6 @@ public class Twitter implements Connection {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Status> getMentionTimeline(long minId, long maxId) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
if (minId > 0)
|
||||
params.add("since_id=" + minId);
|
||||
if (maxId > 1)
|
||||
params.add("max_id=" + maxId);
|
||||
return getTweets1(TWEETS_MENTIONS, params);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Status> getUserTimeline(long id, long minId, long maxId) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
|
@ -1146,7 +1135,13 @@ public class Twitter implements Connection {
|
|||
|
||||
@Override
|
||||
public List<Notification> getNotifications(long minId, long maxId) throws ConnectionException {
|
||||
List<Status> mentions = getMentionTimeline(minId, maxId);
|
||||
List<String> params = new ArrayList<>();
|
||||
if (minId > 0)
|
||||
params.add("since_id=" + minId);
|
||||
if (maxId > 1)
|
||||
params.add("max_id=" + maxId);
|
||||
params.add("count=" + settings.getListSize());
|
||||
List<Status> mentions = getTweets1(TWEETS_MENTIONS, params);
|
||||
List<Notification> result = new ArrayList<>(mentions.size());
|
||||
for (Status status : mentions) {
|
||||
result.add(new TwitterNotification(status));
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package org.nuclearfog.twidda.backend.async;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.nuclearfog.twidda.backend.api.Connection;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionManager;
|
||||
import org.nuclearfog.twidda.model.Notification;
|
||||
import org.nuclearfog.twidda.ui.fragments.NotificationFragment;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Notification loader for {@link NotificationFragment}
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class NotificationLoader extends AsyncTask<Long, Void, List<Notification>> {
|
||||
|
||||
private WeakReference<NotificationFragment> callback;
|
||||
private Connection connection;
|
||||
|
||||
@Nullable
|
||||
private ConnectionException exception;
|
||||
private int pos;
|
||||
|
||||
|
||||
public NotificationLoader(NotificationFragment fragment, int pos) {
|
||||
super();
|
||||
callback = new WeakReference<>(fragment);
|
||||
connection = ConnectionManager.get(fragment.getContext());
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<Notification> doInBackground(Long... ids) {
|
||||
try {
|
||||
return connection.getNotifications(ids[0], ids[1]);
|
||||
} catch (ConnectionException exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<Notification> notifications) {
|
||||
NotificationFragment fragment = callback.get();
|
||||
if (fragment != null) {
|
||||
if (notifications != null) {
|
||||
fragment.onSuccess(notifications, pos);
|
||||
} else {
|
||||
fragment.onError(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,12 +27,7 @@ public class StatusLoader extends AsyncTask<Long, Void, List<Status>> {
|
|||
/**
|
||||
* home timeline
|
||||
*/
|
||||
public static final int HOME = 1;
|
||||
|
||||
/**
|
||||
* mention timeline
|
||||
*/
|
||||
public static final int MENTION = 2;
|
||||
public static final int HOME = 2;
|
||||
|
||||
/**
|
||||
* user timeline
|
||||
|
@ -117,21 +112,6 @@ public class StatusLoader extends AsyncTask<Long, Void, List<Status>> {
|
|||
}
|
||||
break;
|
||||
|
||||
case MENTION:
|
||||
if (sinceId == 0 && maxId == 0) {
|
||||
statuses = db.getMentionTimeline();
|
||||
if (statuses.isEmpty()) {
|
||||
statuses = connection.getMentionTimeline(sinceId, maxId);
|
||||
db.saveMentionTimeline(statuses);
|
||||
}
|
||||
} else if (sinceId > 0) {
|
||||
statuses = connection.getMentionTimeline(sinceId, maxId);
|
||||
db.saveMentionTimeline(statuses);
|
||||
} else if (maxId > 1) {
|
||||
statuses = connection.getMentionTimeline(sinceId, maxId);
|
||||
}
|
||||
break;
|
||||
|
||||
case USER:
|
||||
if (id > 0) {
|
||||
if (sinceId == 0 && maxId == 0) {
|
||||
|
|
|
@ -44,7 +44,6 @@ public class AppDatabase {
|
|||
public static final int FAV_MASK = 1; // status is favorited by user
|
||||
public static final int RTW_MASK = 1 << 1; // status is reposted by user
|
||||
public static final int HOM_MASK = 1 << 2; // status is from home timeline
|
||||
public static final int MEN_MASK = 1 << 3; // status is from mention timeline
|
||||
public static final int UTW_MASK = 1 << 4; // status is from an users timeline
|
||||
public static final int RPL_MASK = 1 << 5; // status is from a reply timeline
|
||||
public static final int MEDIA_IMAGE_MASK = 1 << 6; // status contains images
|
||||
|
@ -89,17 +88,6 @@ public class AppDatabase {
|
|||
+ " ORDER BY " + StatusTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get mention timeline
|
||||
*/
|
||||
static final String MENTION_QUERY = "SELECT * FROM " + STATUS_TABLE
|
||||
+ " WHERE " + StatusRegisterTable.NAME + "." + StatusRegisterTable.REGISTER + "&" + MEN_MASK + " IS NOT 0"
|
||||
+ " AND " + UserRegisterTable.NAME + "." + UserRegisterTable.REGISTER + "&" + EXCL_USR + " IS 0"
|
||||
+ " AND " + StatusRegisterTable.NAME + "." + StatusRegisterTable.OWNER + "=?"
|
||||
+ " AND " + UserRegisterTable.NAME + "." + UserRegisterTable.OWNER + "=?"
|
||||
+ " ORDER BY " + StatusTable.ID
|
||||
+ " DESC LIMIT ?";
|
||||
|
||||
/**
|
||||
* SQL query to get status of an user
|
||||
*/
|
||||
|
@ -258,18 +246,6 @@ public class AppDatabase {
|
|||
commit(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* save mention timeline
|
||||
*
|
||||
* @param mentions status
|
||||
*/
|
||||
public void saveMentionTimeline(List<Status> mentions) {
|
||||
SQLiteDatabase db = getDbWrite();
|
||||
for (Status status : mentions)
|
||||
saveStatus(status, MEN_MASK, db);
|
||||
commit(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* save user timeline
|
||||
*
|
||||
|
@ -379,29 +355,6 @@ public class AppDatabase {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* load mention timeline
|
||||
*
|
||||
* @return mention timeline
|
||||
*/
|
||||
public List<Status> getMentionTimeline() {
|
||||
String homeStr = Long.toString(settings.getLogin().getId());
|
||||
String[] args = {homeStr, homeStr, Integer.toString(settings.getListSize())};
|
||||
|
||||
SQLiteDatabase db = getDbRead();
|
||||
List<Status> result = new LinkedList<>();
|
||||
Cursor cursor = db.rawQuery(MENTION_QUERY, args);
|
||||
if (cursor.moveToFirst()) {
|
||||
do
|
||||
{
|
||||
Status status = getStatus(cursor);
|
||||
result.add(status);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
cursor.close();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* load user timeline
|
||||
*
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
package org.nuclearfog.twidda.ui.fragments;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.nuclearfog.twidda.adapter.NotificationAdapter;
|
||||
import org.nuclearfog.twidda.adapter.NotificationAdapter.OnNotificationClickListener;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||
import org.nuclearfog.twidda.backend.async.NotificationLoader;
|
||||
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
|
||||
import org.nuclearfog.twidda.model.Notification;
|
||||
import org.nuclearfog.twidda.model.Status;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* fragment to show notifications
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class NotificationFragment extends ListFragment implements OnNotificationClickListener {
|
||||
|
||||
private NotificationLoader notificationAsync;
|
||||
private NotificationAdapter adapter;
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
adapter = new NotificationAdapter(requireContext(), this);
|
||||
setAdapter(adapter);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (notificationAsync == null) {
|
||||
load(0L, 0L, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onReload() {
|
||||
long sinceId = 0;
|
||||
if (!adapter.isEmpty())
|
||||
sinceId = adapter.getItemId(0);
|
||||
load(sinceId, 0L, 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onReset() {
|
||||
adapter = new NotificationAdapter(requireContext(), this);
|
||||
setAdapter(adapter);
|
||||
load(0L, 0L, 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStatusClick(Status status) {
|
||||
if (!isRefreshing()) {
|
||||
// todo add implementation
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onUserClick(User user) {
|
||||
if (!isRefreshing()) {
|
||||
// todo add implementation
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onPlaceholderClick(long sinceId, long maxId, long position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* called from {@link NotificationLoader} when notifications were loaded successfully
|
||||
*
|
||||
* @param notifications new items
|
||||
* @param position index where to insert the new items
|
||||
*/
|
||||
public void onSuccess(List<Notification> notifications, int position) {
|
||||
adapter.addItems(notifications, position);
|
||||
setRefresh(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* called from {@link NotificationLoader} if an error occurs
|
||||
*/
|
||||
public void onError(@Nullable ConnectionException exception) {
|
||||
ErrorHandler.handleFailure(requireContext(), exception);
|
||||
adapter.disableLoading();
|
||||
setRefresh(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param minId lowest notification ID to load
|
||||
* @param maxId highest notification Id to load
|
||||
* @param pos index to insert the new items
|
||||
*/
|
||||
private void load(long minId, long maxId, int pos) {
|
||||
notificationAsync = new NotificationLoader(this, pos);
|
||||
notificationAsync.execute(minId, maxId);
|
||||
}
|
||||
}
|
|
@ -53,13 +53,6 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
|
|||
*/
|
||||
public static final int STATUS_FRAGMENT_HOME = 0xE7028B60;
|
||||
|
||||
/**
|
||||
* setup list for mention timeline
|
||||
*
|
||||
* @see #KEY_STATUS_FRAGMENT_MODE
|
||||
*/
|
||||
public static final int STATUS_FRAGMENT_MENTION = 0x9EC8274D;
|
||||
|
||||
/**
|
||||
* setup list for status timeline of a specific user
|
||||
*
|
||||
|
@ -131,7 +124,7 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
|
|||
public void onStart() {
|
||||
super.onStart();
|
||||
if (statusAsync == null) {
|
||||
load(0, 0, CLEAR_LIST);
|
||||
load(0L, 0L, CLEAR_LIST);
|
||||
setRefresh(true);
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +134,7 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
|
|||
protected void onReset() {
|
||||
adapter = new StatusAdapter(requireContext(), this);
|
||||
setAdapter(adapter);
|
||||
load(0, 0, CLEAR_LIST);
|
||||
load(0L, 0L, CLEAR_LIST);
|
||||
setRefresh(true);
|
||||
}
|
||||
|
||||
|
@ -178,7 +171,7 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
|
|||
long sinceId = 0;
|
||||
if (!adapter.isEmpty())
|
||||
sinceId = adapter.getItemId(0);
|
||||
load(sinceId, 0, 0);
|
||||
load(sinceId, 0L, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -239,11 +232,6 @@ public class StatusFragment extends ListFragment implements StatusSelectListener
|
|||
statusAsync.execute(sinceId, maxId);
|
||||
break;
|
||||
|
||||
case STATUS_FRAGMENT_MENTION:
|
||||
statusAsync = new StatusLoader(this, StatusLoader.MENTION, id, search, index);
|
||||
statusAsync.execute(sinceId, maxId);
|
||||
break;
|
||||
|
||||
case STATUS_FRAGMENT_USER:
|
||||
statusAsync = new StatusLoader(this, StatusLoader.USER, id, search, index);
|
||||
statusAsync.execute(sinceId, maxId);
|
||||
|
|
|
@ -12,13 +12,26 @@
|
|||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/item_status_layout_padding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_status_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:lines="1"
|
||||
android:drawablePadding="@dimen/item_status_drawable_margin"
|
||||
android:textSize="@dimen/item_status_textsize_notification"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_status_profile_image"
|
||||
android:layout_width="@dimen/item_status_profile_size"
|
||||
android:layout_height="@dimen/item_status_profile_size"
|
||||
android:contentDescription="@string/profile_image"
|
||||
android:layout_marginTop="@dimen/item_status_image_margin"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@id/item_status_label" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_status_verified_icon"
|
||||
|
|
|
@ -10,23 +10,43 @@
|
|||
android:id="@+id/item_user_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/useritem_layout_padding"
|
||||
android:padding="@dimen/item_user_layout_padding"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_user_label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:lines="1"
|
||||
android:drawablePadding="@dimen/item_user_drawable_margin"
|
||||
android:visibility="gone"
|
||||
android:textSize="@dimen/item_user_textsize_notification"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/item_user_notification_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="top"
|
||||
app:constraint_referenced_ids="item_user_profile,item_user_verified, item_user_username" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_user_profile"
|
||||
android:layout_width="@dimen/useritem_image_size"
|
||||
android:layout_height="@dimen/useritem_image_size"
|
||||
android:layout_width="@dimen/item_user_image_size"
|
||||
android:layout_height="@dimen/item_user_image_size"
|
||||
android:contentDescription="@string/profile_image"
|
||||
android:layout_marginTop="@dimen/item_user_image_margin"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_user_label"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_user_verified"
|
||||
android:layout_width="@dimen/useritem_icon_size"
|
||||
android:layout_height="@dimen/useritem_icon_size"
|
||||
android:layout_marginStart="@dimen/useritem_drawable_margin"
|
||||
android:layout_width="@dimen/item_user_icon_size"
|
||||
android:layout_height="@dimen/item_user_icon_size"
|
||||
android:layout_marginStart="@dimen/item_user_drawable_margin"
|
||||
android:src="@drawable/verify"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_profile"
|
||||
app:layout_constraintTop_toTopOf="@id/item_user_username"
|
||||
|
@ -38,19 +58,19 @@
|
|||
android:id="@+id/item_user_username"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="@dimen/useritem_drawable_margin"
|
||||
android:layout_marginStart="@dimen/useritem_textview_padding"
|
||||
android:layout_marginEnd="@dimen/useritem_textview_padding"
|
||||
android:drawablePadding="@dimen/item_user_drawable_margin"
|
||||
android:layout_marginStart="@dimen/item_user_textview_padding"
|
||||
android:layout_marginEnd="@dimen/item_user_textview_padding"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_verified"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/item_user_profile"
|
||||
app:layout_constraintEnd_toStartOf="@id/item_user_delete_buton" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_user_private"
|
||||
android:layout_width="@dimen/useritem_icon_size"
|
||||
android:layout_height="@dimen/useritem_icon_size"
|
||||
android:layout_marginStart="@dimen/useritem_drawable_margin"
|
||||
android:layout_width="@dimen/item_user_icon_size"
|
||||
android:layout_height="@dimen/item_user_icon_size"
|
||||
android:layout_marginStart="@dimen/item_user_drawable_margin"
|
||||
android:src="@drawable/lock"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_profile"
|
||||
app:layout_constraintTop_toTopOf="@id/item_user_screenname"
|
||||
|
@ -63,9 +83,9 @@
|
|||
android:id="@+id/item_user_screenname"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="@dimen/useritem_drawable_margin"
|
||||
android:layout_marginStart="@dimen/useritem_textview_padding"
|
||||
android:layout_marginEnd="@dimen/useritem_textview_padding"
|
||||
android:drawablePadding="@dimen/item_user_drawable_margin"
|
||||
android:layout_marginStart="@dimen/item_user_textview_padding"
|
||||
android:layout_marginEnd="@dimen/item_user_textview_padding"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_private"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_user_username"
|
||||
|
@ -73,10 +93,10 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/item_user_following_icon"
|
||||
android:layout_width="@dimen/useritem_icon_size"
|
||||
android:layout_height="@dimen/useritem_icon_size"
|
||||
android:layout_marginStart="@dimen/useritem_drawable_margin"
|
||||
android:layout_marginEnd="@dimen/useritem_drawable_margin"
|
||||
android:layout_width="@dimen/item_user_icon_size"
|
||||
android:layout_height="@dimen/item_user_icon_size"
|
||||
android:layout_marginStart="@dimen/item_user_drawable_margin"
|
||||
android:layout_marginEnd="@dimen/item_user_drawable_margin"
|
||||
android:src="@drawable/following"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_profile"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_user_screenname"
|
||||
|
@ -88,9 +108,9 @@
|
|||
android:id="@+id/item_user_following_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="@dimen/useritem_drawable_margin"
|
||||
android:drawablePadding="@dimen/item_user_drawable_margin"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/useritem_textsize_small"
|
||||
android:textSize="@dimen/item_user_textsize_small"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_following_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/item_user_following_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/item_user_following_icon"
|
||||
|
@ -98,10 +118,10 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/item_user_follower_icon"
|
||||
android:layout_width="@dimen/useritem_icon_size"
|
||||
android:layout_height="@dimen/useritem_icon_size"
|
||||
android:layout_marginStart="@dimen/useritem_drawable_margin"
|
||||
android:layout_marginEnd="@dimen/useritem_drawable_margin"
|
||||
android:layout_width="@dimen/item_user_icon_size"
|
||||
android:layout_height="@dimen/item_user_icon_size"
|
||||
android:layout_marginStart="@dimen/item_user_drawable_margin"
|
||||
android:layout_marginEnd="@dimen/item_user_drawable_margin"
|
||||
android:src="@drawable/follower"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_following_count"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_user_screenname"
|
||||
|
@ -113,10 +133,10 @@
|
|||
android:id="@+id/item_user_follower_count"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="@dimen/useritem_drawable_margin"
|
||||
android:layout_marginEnd="@dimen/useritem_textview_padding"
|
||||
android:drawablePadding="@dimen/item_user_drawable_margin"
|
||||
android:layout_marginEnd="@dimen/item_user_textview_padding"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/useritem_textsize_small"
|
||||
android:textSize="@dimen/item_user_textsize_small"
|
||||
app:layout_constraintStart_toEndOf="@id/item_user_follower_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/item_user_follower_icon"
|
||||
app:layout_constraintBottom_toBottomOf="@id/item_user_follower_icon"
|
||||
|
@ -124,14 +144,14 @@
|
|||
|
||||
<ImageButton
|
||||
android:id="@+id/item_user_delete_buton"
|
||||
android:layout_width="@dimen/useritem_button_size"
|
||||
android:layout_height="@dimen/useritem_button_size"
|
||||
android:layout_width="@dimen/item_user_button_size"
|
||||
android:layout_height="@dimen/item_user_button_size"
|
||||
android:visibility="invisible"
|
||||
android:padding="@dimen/useritem_button_padding"
|
||||
android:padding="@dimen/item_user_button_padding"
|
||||
android:contentDescription="@string/descr_remove_user"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/cross"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/item_user_label"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
style="@style/RoundButton" />
|
||||
|
|
|
@ -73,7 +73,9 @@
|
|||
<dimen name="item_status_profile_size">36sp</dimen>
|
||||
<dimen name="item_status_layout_padding">5dp</dimen>
|
||||
<dimen name="item_status_text_margin">5dp</dimen>
|
||||
<dimen name="item_status_image_margin">8dp</dimen>
|
||||
<dimen name="item_status_drawable_margin">5dp</dimen>
|
||||
<dimen name="item_status_textsize_notification">12sp</dimen>
|
||||
<dimen name="item_status_textsize_button">12sp</dimen>
|
||||
<dimen name="item_status_textsize_date">12sp</dimen>
|
||||
<dimen name="item_status_icon_size">14sp</dimen>
|
||||
|
@ -90,14 +92,16 @@
|
|||
<dimen name="trenditem_textsize_trendindex_width">40sp</dimen>
|
||||
|
||||
<!--dimens of item_user.xml-->
|
||||
<dimen name="useritem_image_size">56sp</dimen>
|
||||
<dimen name="useritem_layout_padding">5dp</dimen>
|
||||
<dimen name="useritem_textview_padding">5dp</dimen>
|
||||
<dimen name="useritem_drawable_margin">5dp</dimen>
|
||||
<dimen name="useritem_button_size">36dp</dimen>
|
||||
<dimen name="useritem_button_padding">7dp</dimen>
|
||||
<dimen name="useritem_textsize_small">12sp</dimen>
|
||||
<dimen name="useritem_icon_size">14sp</dimen>
|
||||
<dimen name="item_user_image_size">56sp</dimen>
|
||||
<dimen name="item_user_layout_padding">5dp</dimen>
|
||||
<dimen name="item_user_textview_padding">5dp</dimen>
|
||||
<dimen name="item_user_drawable_margin">5dp</dimen>
|
||||
<dimen name="item_user_button_size">36dp</dimen>
|
||||
<dimen name="item_user_button_padding">7dp</dimen>
|
||||
<dimen name="item_user_textsize_small">12sp</dimen>
|
||||
<dimen name="item_user_icon_size">14sp</dimen>
|
||||
<dimen name="item_user_image_margin">8dp</dimen>
|
||||
<dimen name="item_user_textsize_notification">12sp</dimen>
|
||||
|
||||
<!--dimens of item_list.xml-->
|
||||
<dimen name="listitem_padding">5dp</dimen>
|
||||
|
|
|
@ -279,5 +279,10 @@
|
|||
<string name="toolbar_tweet_liker">User liking this status</string>
|
||||
<string name="time_now">now</string>
|
||||
<string name="confirm_open_link">open in browser</string>
|
||||
<string name="info_user_favorited">%1$s favorited your status</string>
|
||||
<string name="info_user_follow">%1$s followed you</string>
|
||||
<string name="info_user_follow_request">%1$s request to follow you</string>
|
||||
<string name="info_user_mention">%1$s mentioned you</string>
|
||||
<string name="info_user_repost">%1$s reposted your status</string>
|
||||
|
||||
</resources>
|
|
@ -81,8 +81,8 @@
|
|||
<style name="CardViewStyle" parent="CardView">
|
||||
<item name="cardPreventCornerOverlap">false</item>
|
||||
<item name="cardUseCompatPadding">true</item>
|
||||
<item name="cardCornerRadius">2dp</item>
|
||||
<item name="cardElevation">2dp</item>
|
||||
<item name="cardCornerRadius">1dp</item>
|
||||
<item name="cardElevation">1dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
Loading…
Reference in New Issue