package it.niedermann.nextcloud.deck.ui.card; import android.annotation.SuppressLint; import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.PopupMenu; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.core.graphics.drawable.DrawableCompat; import androidx.fragment.app.FragmentManager; import androidx.lifecycle.LifecycleOwner; import androidx.recyclerview.widget.RecyclerView; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import it.niedermann.android.crosstabdnd.DragAndDropAdapter; import it.niedermann.android.crosstabdnd.DraggedItemLocalState; import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.R; import it.niedermann.nextcloud.deck.databinding.ItemCardBinding; import it.niedermann.nextcloud.deck.model.Account; import it.niedermann.nextcloud.deck.model.Card; import it.niedermann.nextcloud.deck.model.Label; import it.niedermann.nextcloud.deck.model.Stack; import it.niedermann.nextcloud.deck.model.User; import it.niedermann.nextcloud.deck.model.enums.DBStatus; import it.niedermann.nextcloud.deck.model.full.FullCard; import it.niedermann.nextcloud.deck.model.full.FullStack; import it.niedermann.nextcloud.deck.persistence.sync.SyncManager; import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper; import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.WrappedLiveData; import it.niedermann.nextcloud.deck.ui.branding.Branded; import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder; import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment; import it.niedermann.nextcloud.deck.util.DateUtil; import it.niedermann.nextcloud.deck.util.ViewUtil; import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce; import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme; import static it.niedermann.nextcloud.deck.util.MimeTypeUtil.TEXT_PLAIN; public class CardAdapter extends RecyclerView.Adapter implements DragAndDropAdapter, Branded { protected final SyncManager syncManager; private final FragmentManager fragmentManager; private final Account account; @Nullable private final Long currentBoardRemoteId; private final long boardId; private final long stackId; private final boolean canEdit; @NonNull private final Context context; @Nullable private final SelectCardListener selectCardListener; private List cardList = new LinkedList<>(); private LifecycleOwner lifecycleOwner; private List availableStacks = new ArrayList<>(); private String counterMaxValue; private int mainColor; @StringRes private int shareLinkRes; public CardAdapter(@NonNull Context context, @NonNull FragmentManager fragmentManager, @NonNull Account account, long boardId, @Nullable Long currentBoardRemoteId, long stackId, boolean canEdit, @NonNull SyncManager syncManager, @NonNull LifecycleOwner lifecycleOwner, @Nullable SelectCardListener selectCardListener) { this.context = context; this.fragmentManager = fragmentManager; this.lifecycleOwner = lifecycleOwner; this.account = account; this.shareLinkRes = account.getServerDeckVersionAsObject().getShareLinkResource(); this.boardId = boardId; this.currentBoardRemoteId = currentBoardRemoteId; this.stackId = stackId; this.canEdit = canEdit; this.syncManager = syncManager; this.selectCardListener = selectCardListener; this.mainColor = context.getResources().getColor(R.color.primary); syncManager.getStacksForBoard(account.getId(), boardId).observe(this.lifecycleOwner, (stacks) -> { availableStacks.clear(); availableStacks.addAll(stacks); }); setHasStableIds(true); } @Override public long getItemId(int position) { return cardList.get(position).getLocalId(); } @NonNull @Override public ItemCardViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { final Context context = viewGroup.getContext(); counterMaxValue = context.getString(R.string.counter_max_value); LayoutInflater layoutInflater = LayoutInflater.from(context); ItemCardBinding binding = ItemCardBinding.inflate(layoutInflater, viewGroup, false); return new ItemCardViewHolder(binding); } @SuppressLint("SetTextI18n") @Override public void onBindViewHolder(@NonNull ItemCardViewHolder viewHolder, int position) { final Context context = viewHolder.itemView.getContext(); final FullCard card = cardList.get(position); viewHolder.binding.card.setOnClickListener((v) -> { if (selectCardListener == null) { context.startActivity(EditActivity.createEditCardIntent(context, account, boardId, card.getLocalId())); } else { selectCardListener.onCardSelected(card); } }); if (canEdit && selectCardListener == null) { viewHolder.binding.card.setOnLongClickListener((v) -> { DeckLog.log("Starting drag and drop"); v.startDrag(ClipData.newPlainText("cardid", String.valueOf(card.getLocalId())), new View.DragShadowBuilder(v), new DraggedItemLocalState<>(card, viewHolder.binding.card, this, position), 0 ); return true; }); } else { viewHolder.binding.cardMenu.setVisibility(View.GONE); } viewHolder.binding.cardTitle.setText(card.getCard().getTitle().trim()); if (card.getAssignedUsers() != null && card.getAssignedUsers().size() > 0) { viewHolder.binding.overlappingAvatars.setAvatars(account, card.getAssignedUsers()); viewHolder.binding.overlappingAvatars.setVisibility(View.VISIBLE); } else { viewHolder.binding.overlappingAvatars.setVisibility(View.GONE); } DrawableCompat.setTint(viewHolder.binding.notSyncedYet.getDrawable(), mainColor); viewHolder.binding.notSyncedYet.setVisibility(DBStatus.LOCAL_EDITED.equals(card.getStatusEnum()) ? View.VISIBLE : View.GONE); if (card.getCard().getDueDate() != null) { setupDueDate(viewHolder.binding.cardDueDate, card.getCard()); viewHolder.binding.cardDueDate.setVisibility(View.VISIBLE); } else { viewHolder.binding.cardDueDate.setVisibility(View.GONE); } final int attachmentsCount = card.getAttachments().size(); if (attachmentsCount == 0) { viewHolder.binding.cardCountAttachments.setVisibility(View.GONE); } else { setupCounter(viewHolder.binding.cardCountAttachments, attachmentsCount); viewHolder.binding.cardCountAttachments.setVisibility(View.VISIBLE); } final int commentsCount = card.getCommentCount(); if (commentsCount == 0) { viewHolder.binding.cardCountComments.setVisibility(View.GONE); } else { setupCounter(viewHolder.binding.cardCountComments, commentsCount); viewHolder.binding.cardCountComments.setVisibility(View.VISIBLE); } List