358 lines
16 KiB
Java
358 lines
16 KiB
Java
package app.fedilab.android.mastodon.ui.drawer;
|
|
/* Copyright 2021 Thomas Schneider
|
|
*
|
|
* This file is a part of Fedilab
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
* see <http://www.gnu.org/licenses>. */
|
|
|
|
|
|
import static app.fedilab.android.BaseMainActivity.currentAccount;
|
|
import static app.fedilab.android.BaseMainActivity.currentNightMode;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.SharedPreferences;
|
|
import android.content.res.Configuration;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.view.LayoutInflater;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.appcompat.widget.LinearLayoutCompat;
|
|
import androidx.preference.PreferenceManager;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import com.bumptech.glide.Glide;
|
|
import com.bumptech.glide.request.RequestOptions;
|
|
|
|
import java.lang.ref.WeakReference;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
|
|
import app.fedilab.android.R;
|
|
import app.fedilab.android.databinding.DrawerConversationBinding;
|
|
import app.fedilab.android.databinding.ThumbnailBinding;
|
|
import app.fedilab.android.mastodon.activities.ContextActivity;
|
|
import app.fedilab.android.mastodon.activities.DirectMessageActivity;
|
|
import app.fedilab.android.mastodon.client.entities.api.Account;
|
|
import app.fedilab.android.mastodon.client.entities.api.Attachment;
|
|
import app.fedilab.android.mastodon.client.entities.api.Conversation;
|
|
import app.fedilab.android.mastodon.client.entities.api.Status;
|
|
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
|
|
import app.fedilab.android.mastodon.helper.Helper;
|
|
import app.fedilab.android.mastodon.helper.MastodonHelper;
|
|
|
|
|
|
public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
|
private final List<Conversation> conversationList;
|
|
public FetchMoreCallBack fetchMoreCallBack;
|
|
private Context context;
|
|
private boolean isExpended = false;
|
|
private RecyclerView mRecyclerView;
|
|
|
|
public ConversationAdapter(List<Conversation> conversations) {
|
|
if (conversations == null) {
|
|
conversations = new ArrayList<>();
|
|
}
|
|
this.conversationList = conversations;
|
|
}
|
|
|
|
public static void applyColorConversation(Context context, ConversationHolder holder) {
|
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
boolean customLight = sharedpreferences.getBoolean(context.getString(R.string.SET_CUSTOMIZE_LIGHT_COLORS), false);
|
|
boolean customDark = sharedpreferences.getBoolean(context.getString(R.string.SET_CUSTOMIZE_DARK_COLORS), false);
|
|
int theme_icons_color = -1;
|
|
int theme_statuses_color = -1;
|
|
int theme_text_color = -1;
|
|
if (currentNightMode == Configuration.UI_MODE_NIGHT_NO) { //LIGHT THEME
|
|
if (customLight) {
|
|
theme_icons_color = sharedpreferences.getInt(context.getString(R.string.SET_LIGHT_ICON), -1);
|
|
theme_statuses_color = sharedpreferences.getInt(context.getString(R.string.SET_LIGHT_BACKGROUND), -1);
|
|
theme_text_color = sharedpreferences.getInt(context.getString(R.string.SET_LIGHT_TEXT), -1);
|
|
}
|
|
} else {
|
|
if (customDark) {
|
|
theme_icons_color = sharedpreferences.getInt(context.getString(R.string.SET_DARK_ICON), -1);
|
|
theme_statuses_color = sharedpreferences.getInt(context.getString(R.string.SET_DARK_BACKGROUND), -1);
|
|
theme_text_color = sharedpreferences.getInt(context.getString(R.string.SET_DARK_TEXT), -1);
|
|
}
|
|
}
|
|
|
|
if (theme_icons_color != -1) {
|
|
Helper.changeDrawableColor(context, R.drawable.ic_star_outline, theme_icons_color);
|
|
Helper.changeDrawableColor(context, R.drawable.ic_person, theme_icons_color);
|
|
Helper.changeDrawableColor(context, R.drawable.ic_bot, theme_icons_color);
|
|
Helper.changeDrawableColor(context, R.drawable.ic_baseline_reply_16, theme_icons_color);
|
|
}
|
|
if (theme_statuses_color != -1) {
|
|
holder.binding.cardviewContainer.setBackgroundColor(theme_statuses_color);
|
|
}
|
|
if (theme_text_color != -1) {
|
|
holder.binding.statusContent.setTextColor(theme_text_color);
|
|
holder.binding.spoiler.setTextColor(theme_text_color);
|
|
Helper.changeDrawableColor(context, R.drawable.ic_baseline_lock_24, theme_text_color);
|
|
}
|
|
}
|
|
|
|
public int getCount() {
|
|
return conversationList.size();
|
|
}
|
|
|
|
public Conversation getItem(int position) {
|
|
return conversationList.get(position);
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
context = parent.getContext();
|
|
DrawerConversationBinding itemBinding = DrawerConversationBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
|
return new ConversationHolder(itemBinding);
|
|
}
|
|
|
|
@SuppressLint("ClickableViewAccessibility")
|
|
@Override
|
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
|
|
Conversation conversation = conversationList.get(position);
|
|
ConversationHolder holder = (ConversationHolder) viewHolder;
|
|
|
|
|
|
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
if (sharedpreferences.getBoolean(context.getString(R.string.SET_CARDVIEW), false)) {
|
|
holder.binding.cardviewContainer.setCardElevation(Helper.convertDpToPixel(5, context));
|
|
holder.binding.dividerCard.setVisibility(View.GONE);
|
|
}
|
|
|
|
//--- Profile Pictures for participants ---
|
|
holder.binding.participantsList.removeAllViews();
|
|
for (Account account : conversation.accounts) {
|
|
ImageView imageView = new ImageView(context);
|
|
LinearLayoutCompat.LayoutParams lp = new LinearLayoutCompat.LayoutParams((int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
|
|
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
|
lp.setMarginEnd((int) Helper.convertDpToPixel(6, context));
|
|
imageView.setAdjustViewBounds(true);
|
|
imageView.setLayoutParams(lp);
|
|
MastodonHelper.loadPPMastodon(imageView, account);
|
|
holder.binding.participantsList.addView(imageView);
|
|
}
|
|
if (conversation.last_status == null) {
|
|
return;
|
|
}
|
|
if (conversation.isFetchMore && fetchMoreCallBack != null) {
|
|
holder.binding.layoutFetchMore.fetchMoreContainer.setVisibility(View.VISIBLE);
|
|
holder.binding.layoutFetchMore.fetchMoreMin.setOnClickListener(v -> {
|
|
conversation.isFetchMore = false;
|
|
if (holder.getBindingAdapterPosition() < conversationList.size() - 1) {
|
|
String fromId;
|
|
if (conversation.positionFetchMore == Conversation.PositionFetchMore.TOP) {
|
|
fromId = conversationList.get(position + 1).id;
|
|
} else {
|
|
fromId = conversation.id;
|
|
}
|
|
fetchMoreCallBack.onClickMinId(fromId, conversation);
|
|
notifyItemChanged(position);
|
|
}
|
|
|
|
});
|
|
holder.binding.layoutFetchMore.fetchMoreMax.setOnClickListener(v -> {
|
|
//We hide the button
|
|
conversation.isFetchMore = false;
|
|
String fromId;
|
|
if (conversation.positionFetchMore == Conversation.PositionFetchMore.TOP) {
|
|
fromId = conversationList.get(position).id;
|
|
} else {
|
|
fromId = conversationList.get(position - 1).id;
|
|
}
|
|
notifyItemChanged(position);
|
|
fetchMoreCallBack.onClickMaxId(fromId, conversation);
|
|
});
|
|
} else {
|
|
holder.binding.layoutFetchMore.fetchMoreContainer.setVisibility(View.GONE);
|
|
}
|
|
//---- SPOILER TEXT -----
|
|
boolean expand_cw = sharedpreferences.getBoolean(context.getString(R.string.SET_EXPAND_CW), false);
|
|
if (conversation.last_status.spoiler_text != null && !conversation.last_status.spoiler_text.trim().isEmpty()) {
|
|
if (expand_cw || !conversation.last_status.sensitive) {
|
|
isExpended = true;
|
|
}
|
|
holder.binding.spoilerExpand.setOnClickListener(v -> {
|
|
isExpended = !isExpended;
|
|
notifyItemChanged(position);
|
|
});
|
|
holder.binding.spoiler.setVisibility(View.VISIBLE);
|
|
holder.binding.spoiler.setText(
|
|
conversation.last_status.getSpanSpoiler(context,
|
|
new WeakReference<>(holder.binding.spoiler), () -> mRecyclerView.post(() -> notifyItemChanged(holder.getBindingAdapterPosition()))),
|
|
TextView.BufferType.SPANNABLE);
|
|
} else {
|
|
holder.binding.spoiler.setVisibility(View.GONE);
|
|
holder.binding.spoilerExpand.setVisibility(View.GONE);
|
|
holder.binding.spoiler.setText(null);
|
|
}
|
|
//--- MAIN CONTENT ---
|
|
holder.binding.statusContent.setText(
|
|
conversation.last_status.getSpanContent(context, false,
|
|
new WeakReference<>(holder.binding.statusContent), () -> mRecyclerView.post(() -> notifyItemChanged(holder.getBindingAdapterPosition()))),
|
|
TextView.BufferType.SPANNABLE);
|
|
//--- DATE ---
|
|
holder.binding.lastMessageDate.setText(Helper.dateDiff(context, conversation.last_status.created_at));
|
|
|
|
boolean chatMode = sharedpreferences.getBoolean(context.getString(R.string.SET_CHAT_FOR_CONVERSATION), true);
|
|
holder.binding.statusContent.setOnClickListener(v -> {
|
|
Intent intent;
|
|
if (chatMode) {
|
|
intent = new Intent(context, DirectMessageActivity.class);
|
|
} else {
|
|
intent = new Intent(context, ContextActivity.class);
|
|
}
|
|
Bundle args = new Bundle();
|
|
args.putSerializable(Helper.ARG_STATUS, conversation.last_status);
|
|
new CachedBundle(context).insertBundle(args, currentAccount, bundleId -> {
|
|
Bundle bundle = new Bundle();
|
|
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
|
intent.putExtras(bundle);
|
|
context.startActivity(intent);
|
|
});
|
|
});
|
|
|
|
holder.binding.attachmentsListContainer.setOnTouchListener((v, event) -> {
|
|
if (event.getAction() == MotionEvent.ACTION_UP) {
|
|
Intent intent;
|
|
if (chatMode) {
|
|
intent = new Intent(context, DirectMessageActivity.class);
|
|
} else {
|
|
intent = new Intent(context, ContextActivity.class);
|
|
}
|
|
Bundle args = new Bundle();
|
|
args.putSerializable(Helper.ARG_STATUS, conversation.last_status);
|
|
new CachedBundle(context).insertBundle(args, currentAccount, bundleId -> {
|
|
Bundle bundle = new Bundle();
|
|
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
|
intent.putExtras(bundle);
|
|
context.startActivity(intent);
|
|
});
|
|
}
|
|
return false;
|
|
});
|
|
|
|
|
|
displayAttachments(holder, position);
|
|
if (holder.timer != null) {
|
|
holder.timer.cancel();
|
|
holder.timer = null;
|
|
}
|
|
|
|
if (conversation.last_status.emojis != null && conversation.last_status.emojis.size() > 0) {
|
|
holder.timer = new Timer();
|
|
holder.timer.scheduleAtFixedRate(new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
Runnable myRunnable = () -> holder.binding.statusContent.invalidate();
|
|
mainHandler.post(myRunnable);
|
|
}
|
|
}, 100, 100);
|
|
}
|
|
|
|
applyColorConversation(context, holder);
|
|
}
|
|
|
|
@Override
|
|
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
|
|
super.onAttachedToRecyclerView(recyclerView);
|
|
|
|
mRecyclerView = recyclerView;
|
|
}
|
|
|
|
private void displayAttachments(ConversationAdapter.ConversationHolder holder, int position) {
|
|
if (conversationList.get(position).last_status != null) {
|
|
Status status = conversationList.get(position).last_status;
|
|
holder.binding.attachmentsList.removeAllViews();
|
|
List<Attachment> attachmentList = status.media_attachments;
|
|
if (attachmentList != null && attachmentList.size() > 0) {
|
|
for (Attachment attachment : attachmentList) {
|
|
ThumbnailBinding thumbnailBinding = ThumbnailBinding.inflate(LayoutInflater.from(context), holder.binding.attachmentsList, false);
|
|
thumbnailBinding.buttonPlay.setVisibility(View.GONE);
|
|
if (attachment.type.compareToIgnoreCase("image") == 0) {
|
|
Glide.with(thumbnailBinding.preview.getContext())
|
|
.load(attachment.preview_url)
|
|
.into(thumbnailBinding.preview);
|
|
} else if (attachment.type.compareToIgnoreCase("video") == 0 || attachment.type.compareToIgnoreCase("gifv") == 0) {
|
|
thumbnailBinding.buttonPlay.setVisibility(View.VISIBLE);
|
|
long interval = 2000;
|
|
RequestOptions options = new RequestOptions().frame(interval);
|
|
Glide.with(thumbnailBinding.preview.getContext()).asBitmap()
|
|
.load(attachment.preview_url)
|
|
.apply(options)
|
|
.into(thumbnailBinding.preview);
|
|
} else if (attachment.type.compareToIgnoreCase("audio") == 0) {
|
|
Glide.with(thumbnailBinding.preview.getContext())
|
|
.load(R.drawable.ic_baseline_audio_file_24)
|
|
.into(thumbnailBinding.preview);
|
|
} else {
|
|
Glide.with(thumbnailBinding.preview.getContext())
|
|
.load(R.drawable.ic_baseline_insert_drive_file_24)
|
|
.into(thumbnailBinding.preview);
|
|
}
|
|
holder.binding.attachmentsList.addView(thumbnailBinding.getRoot());
|
|
}
|
|
holder.binding.attachmentsList.setVisibility(View.VISIBLE);
|
|
} else {
|
|
holder.binding.attachmentsList.setVisibility(View.GONE);
|
|
}
|
|
} else {
|
|
holder.binding.attachmentsList.setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
public long getItemId(int position) {
|
|
return position;
|
|
}
|
|
|
|
@Override
|
|
public int getItemCount() {
|
|
return conversationList.size();
|
|
}
|
|
|
|
@Override
|
|
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
|
|
super.onViewRecycled(holder);
|
|
if (holder instanceof ConversationHolder && ((ConversationHolder) holder).timer != null) {
|
|
((ConversationHolder) holder).timer.cancel();
|
|
}
|
|
}
|
|
|
|
public interface FetchMoreCallBack {
|
|
void onClickMinId(String min_id, Conversation conversationToUpdate);
|
|
|
|
void onClickMaxId(String max_id, Conversation conversationToUpdate);
|
|
}
|
|
|
|
static class ConversationHolder extends RecyclerView.ViewHolder {
|
|
DrawerConversationBinding binding;
|
|
Timer timer;
|
|
|
|
ConversationHolder(DrawerConversationBinding itemView) {
|
|
super(itemView.getRoot());
|
|
binding = itemView;
|
|
}
|
|
}
|
|
} |