Abit/app/src/main/java/ch/dissem/apps/abit/adapter/SwipeableMessageAdapter.java

335 lines
11 KiB
Java

/*
* Copyright 2015 Haruki Hasegawa
* Copyright 2016 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.apps.abit.adapter;
import android.annotation.SuppressLint;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemConstants;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultAction;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionMoveToSwipedDirection;
import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionRemoveItem;
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractSwipeableItemViewHolder;
import com.h6ah4i.android.widget.advrecyclerview.utils.RecyclerViewAdapterUtils;
import java.util.LinkedList;
import java.util.List;
import ch.dissem.apps.abit.Identicon;
import ch.dissem.apps.abit.R;
import ch.dissem.apps.abit.util.Assets;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.valueobject.Label;
import static ch.dissem.apps.abit.repository.AndroidMessageRepository.LABEL_ARCHIVE;
import static ch.dissem.apps.abit.util.Strings.prepareMessageExtract;
/**
* Adapted from the basic swipeable example by Haruki Hasegawa. See
*
* @author Christian Basler
* @see <a href="https://github.com/h6ah4i/android-advancedrecyclerview">
* https://github.com/h6ah4i/android-advancedrecyclerview</a>
*/
public class SwipeableMessageAdapter
extends RecyclerView.Adapter<SwipeableMessageAdapter.ViewHolder>
implements SwipeableItemAdapter<SwipeableMessageAdapter.ViewHolder>, SwipeableItemConstants {
private List<Plaintext> data = new LinkedList<>();
private EventListener eventListener;
private final View.OnClickListener itemViewOnClickListener;
private final View.OnClickListener swipeableViewContainerOnClickListener;
private Label label;
private int selectedPosition = -1;
private boolean activateOnItemClick;
public void setActivateOnItemClick(boolean activateOnItemClick) {
this.activateOnItemClick = activateOnItemClick;
}
public interface EventListener {
void onItemDeleted(Plaintext item);
void onItemArchived(Plaintext item);
void onItemViewClicked(View v);
}
@SuppressWarnings("WeakerAccess")
static class ViewHolder extends AbstractSwipeableItemViewHolder {
public final FrameLayout container;
public final ImageView avatar;
public final ImageView status;
public final TextView sender;
public final TextView subject;
public final TextView extract;
ViewHolder(View v) {
super(v);
container = (FrameLayout) v.findViewById(R.id.container);
avatar = (ImageView) v.findViewById(R.id.avatar);
status = (ImageView) v.findViewById(R.id.status);
sender = (TextView) v.findViewById(R.id.sender);
subject = (TextView) v.findViewById(R.id.subject);
extract = (TextView) v.findViewById(R.id.text);
}
@Override
public View getSwipeableContainerView() {
return container;
}
}
public SwipeableMessageAdapter() {
itemViewOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemViewClick(view);
}
};
swipeableViewContainerOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onSwipeableViewContainerClick(view);
}
};
// SwipeableItemAdapter requires stable ID, and also
// have to implement the getItemId() method appropriately.
setHasStableIds(true);
}
public void add(Plaintext item) {
data.add(item);
notifyDataSetChanged();
}
public void clear(Label newLabel) {
label = newLabel;
data.clear();
notifyDataSetChanged();
}
private void onItemViewClick(View v) {
if (eventListener != null) {
eventListener.onItemViewClicked(v);
}
}
private void onSwipeableViewContainerClick(View v) {
if (eventListener != null) {
eventListener.onItemViewClicked(
RecyclerViewAdapterUtils.getParentViewHolderItemView(v));
}
}
public Plaintext getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return (long) data.get(position).getId();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final View v = inflater.inflate(R.layout.message_row, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final Plaintext item = data.get(position);
if (activateOnItemClick) {
holder.container.setBackgroundResource(
position == selectedPosition
? R.drawable.bg_item_selected_state
: R.drawable.bg_item_normal_state
);
}
// set listeners
// (if the item is *pinned*, click event comes to the itemView)
holder.itemView.setOnClickListener(itemViewOnClickListener);
// (if the item is *not pinned*, click event comes to the container)
holder.container.setOnClickListener(swipeableViewContainerOnClickListener);
// set data
holder.avatar.setImageDrawable(new Identicon(item.getFrom()));
holder.status.setImageResource(Assets.getStatusDrawable(item.getStatus()));
holder.status.setContentDescription(
holder.status.getContext().getString(Assets.getStatusString(item.getStatus())));
holder.sender.setText(item.getFrom().toString());
holder.subject.setText(prepareMessageExtract(item.getSubject()));
holder.extract.setText(prepareMessageExtract(item.getText()));
if (item.isUnread()) {
holder.sender.setTypeface(Typeface.DEFAULT_BOLD);
holder.subject.setTypeface(Typeface.DEFAULT_BOLD);
} else {
holder.sender.setTypeface(Typeface.DEFAULT);
holder.subject.setTypeface(Typeface.DEFAULT);
}
}
@Override
public int getItemCount() {
return data.size();
}
@Override
public int onGetSwipeReactionType(ViewHolder holder, int position, int x, int y) {
if (label == LABEL_ARCHIVE || label.getType() == Label.Type.TRASH) {
return REACTION_CAN_SWIPE_LEFT | REACTION_CAN_NOT_SWIPE_RIGHT_WITH_RUBBER_BAND_EFFECT;
}
return REACTION_CAN_SWIPE_BOTH_H;
}
@Override
@SuppressLint("SwitchIntDef")
public void onSetSwipeBackground(ViewHolder holder, int position, int type) {
int bgRes = 0;
switch (type) {
case DRAWABLE_SWIPE_NEUTRAL_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_neutral;
break;
case DRAWABLE_SWIPE_LEFT_BACKGROUND:
bgRes = R.drawable.bg_swipe_item_left;
break;
case DRAWABLE_SWIPE_RIGHT_BACKGROUND:
if (label == LABEL_ARCHIVE || label.getType() == Label.Type.TRASH) {
bgRes = R.drawable.bg_swipe_item_neutral;
} else {
bgRes = R.drawable.bg_swipe_item_right;
}
break;
}
holder.itemView.setBackgroundResource(bgRes);
}
@Override
@SuppressLint("SwitchIntDef")
public SwipeResultAction onSwipeItem(ViewHolder holder, final int position, int result) {
switch (result) {
// swipe right
case RESULT_SWIPED_RIGHT:
return new SwipeRightResultAction(this, position);
case RESULT_SWIPED_LEFT:
return new SwipeLeftResultAction(this, position);
// other --- do nothing
case RESULT_CANCELED:
default:
return null;
}
}
public void setEventListener(EventListener eventListener) {
this.eventListener = eventListener;
}
public void setSelectedPosition(int selectedPosition) {
int oldPosition = this.selectedPosition;
this.selectedPosition = selectedPosition;
notifyItemChanged(oldPosition);
notifyItemChanged(selectedPosition);
}
private static class SwipeLeftResultAction extends SwipeResultActionMoveToSwipedDirection {
private SwipeableMessageAdapter adapter;
private final int position;
private final Plaintext item;
SwipeLeftResultAction(SwipeableMessageAdapter adapter, int position) {
this.adapter = adapter;
this.position = position;
this.item = adapter.data.get(position);
}
@Override
protected void onPerformAction() {
super.onPerformAction();
adapter.data.remove(position);
adapter.notifyItemRemoved(position);
}
@Override
protected void onSlideAnimationEnd() {
super.onSlideAnimationEnd();
if (adapter.eventListener != null) {
adapter.eventListener.onItemDeleted(item);
}
}
@Override
protected void onCleanUp() {
super.onCleanUp();
// clear the references
adapter = null;
}
}
private static class SwipeRightResultAction extends SwipeResultActionRemoveItem {
private SwipeableMessageAdapter adapter;
private final int position;
private final Plaintext item;
SwipeRightResultAction(SwipeableMessageAdapter adapter, int position) {
this.adapter = adapter;
this.position = position;
this.item = adapter.data.get(position);
}
@Override
protected void onPerformAction() {
super.onPerformAction();
adapter.data.remove(position);
adapter.notifyItemRemoved(position);
}
@Override
protected void onSlideAnimationEnd() {
super.onSlideAnimationEnd();
if (adapter.eventListener != null) {
adapter.eventListener.onItemArchived(item);
}
}
@Override
protected void onCleanUp() {
super.onCleanUp();
// clear the references
adapter = null;
}
}
}