session-android/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionRecipientsAdapter.java

195 lines
6.7 KiB
Java
Raw Normal View History

Add emoji reacts support (#889) * feat: Add emoji reacts support * Remove message multi-selection * Add emoji reaction model * Add emoji reaction panel * Blur reacts panel background * Show emoji keyboard * Add emoji sprites * Update reaction proto * Emoji database updates * Emoji database refactor * Emoji reaction persistence * Optimize reactions retrieval * Fix emoji group query * Display emojis * Fix emoji persistence * Cleanup * Persistence refactor * Add reactions bottom sheet * Cleanup * Ui tweaks * React with any emoji * Show emoji react notifications * Remove reaction * Show reactions modal on long press * Click to react (+1) with an emoji * Click to react with an emoji * Enable emoji expand/collapse * fix: some compile issues from merge conflicts * fix: compile issues merging quote and media message UI * fix: xml IDs and adding in legacy is selected for future inclusion * Fix view constraints * Fix merge issue * Add message selection option in conversation context menu * Add sogs emoji integration * Handle sogs emoji reactions * Enable sending/deleting sogs emojis * fix: improve the visible message layout * fix: add file IDs to request parameters for message send (#940) * Fix open group polling from seqno instead of last hash (#939) * fix: reset seqno to get recent messages from open groups * build: upgrade build numbers * fix: actually run the migration * Using StringBuilder to construct request url * Fix reaction filter * fix: is_mms added in second projection query * Update default emojis * fix: include legacy and new open groups in server ID tracking (#941) * feat: add hidden moderator and admin roles, separated as they may be used independently in future (#942) * Cleanup * Fix view constraints * Add reactions capability check * Fix reactions alignment * Ui fixes * Display reactions list * feat: add formatted count strings * fix: account for negatives and add tests * Migrate old official open group locations for polling and adding (#932) * feat: adding in first part of open group migrations and tests for migration logic / helpers * feat: test code and migration logic for open groups in the case of no conflicts * feat: add in extra test cases and refactor code for migrator * refactor: migrate open group join URLs and references to server in adding new open groups to catch legacy and re-write it * refactor: joining open groups using OpenGroupUrlParser.kt now * fix: add in compile issues for renamed OpenGroupApi.kt from OpenGroupV2 * fix: prevent duplicates of http/https for new open group DNS and prevent adding new groups based on public key * fix: room and server swapped parameters * fix: replace default server for config messages * fix: actually using public key to de-dupe didn't work for rooms * build: bump version code and name * Display reactions list on open groups for moderators * Ui tweaks * Ui tweaks for moderation * Refactor * fix: compile issue * fix: de-duping joined queries in the get X from cursor * Restore import * fix: colouring the reaction overlay scrubber * fix: highlight colour, show reaction count if 1 or above * Cleanup * fix: light mode accent * fix: light / dark mode themeing in reactions dialog fragment * Emoji notification blinded id check * fix: show reaction list correctly and pass isUserModerator to bind methods * fix: remove unnecessary places for the moderator * fix: X button for removing own react not showing up properly * feat: add clear all header view * fix: migrate the clear all to the correct location * fix: use display instead of base * Truncate emoji sender ids * feat: add notify thread function in thread db * Notify threads on reaction received * fix: design fixes for the reaction list * fix: emoji reactions bottom sheet dialog UI designs * feat: add unsupported emoji reaction * fix: crash and doing vector properly * Fix reaction database queries * Fix background open group adder job * Show new open group reactions * Fetch a maximum of 5 reactors * Handle open group reactions polling conflicts * Add count to user reaction * Show number of additional reactors * fix: unreads set same as the unread query * fix: design changes * fix: update dependency to improve flexboxlayout behaviour, design consistencies * Add select message icon and update long press menu items order and wording * Fix crash on reactors dialog * fix: colours and backgrounds to match designs * fix: add header in recipient item * fix: margins * fix: alignments and layout issues for emoji reactions view * feat: add overflow previews and logic for overflow * Dim action bar * Add emoji search * Search index fix * Set count for 1:1 and closed group reactions when inserting in local database * Use on screen toolbar to allow overlaying * Show/hide scroll to bottom button * feat: add extended properties so it doesn't collapse on re-bind * Cleanup * feat: prevent keeping extended on rebinding if we get a new message ID * fix: long press works on devices now, fix release lint issue and crash for emoji search DBs from emoji builds * Display message timestamp * Fix modal items alignment * fix: sort order and emoji count in compareTo * Scale down really large messages to fit * Prevent closed group crash * Fix reaction author Co-authored-by: charles <charles@oxen.io> Co-authored-by: jubb <hjubb@users.noreply.github.com>
2022-09-04 13:03:32 +02:00
package org.thoughtcrime.securesms.reactions;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.session.libsignal.utilities.SessionId;
Add emoji reacts support (#889) * feat: Add emoji reacts support * Remove message multi-selection * Add emoji reaction model * Add emoji reaction panel * Blur reacts panel background * Show emoji keyboard * Add emoji sprites * Update reaction proto * Emoji database updates * Emoji database refactor * Emoji reaction persistence * Optimize reactions retrieval * Fix emoji group query * Display emojis * Fix emoji persistence * Cleanup * Persistence refactor * Add reactions bottom sheet * Cleanup * Ui tweaks * React with any emoji * Show emoji react notifications * Remove reaction * Show reactions modal on long press * Click to react (+1) with an emoji * Click to react with an emoji * Enable emoji expand/collapse * fix: some compile issues from merge conflicts * fix: compile issues merging quote and media message UI * fix: xml IDs and adding in legacy is selected for future inclusion * Fix view constraints * Fix merge issue * Add message selection option in conversation context menu * Add sogs emoji integration * Handle sogs emoji reactions * Enable sending/deleting sogs emojis * fix: improve the visible message layout * fix: add file IDs to request parameters for message send (#940) * Fix open group polling from seqno instead of last hash (#939) * fix: reset seqno to get recent messages from open groups * build: upgrade build numbers * fix: actually run the migration * Using StringBuilder to construct request url * Fix reaction filter * fix: is_mms added in second projection query * Update default emojis * fix: include legacy and new open groups in server ID tracking (#941) * feat: add hidden moderator and admin roles, separated as they may be used independently in future (#942) * Cleanup * Fix view constraints * Add reactions capability check * Fix reactions alignment * Ui fixes * Display reactions list * feat: add formatted count strings * fix: account for negatives and add tests * Migrate old official open group locations for polling and adding (#932) * feat: adding in first part of open group migrations and tests for migration logic / helpers * feat: test code and migration logic for open groups in the case of no conflicts * feat: add in extra test cases and refactor code for migrator * refactor: migrate open group join URLs and references to server in adding new open groups to catch legacy and re-write it * refactor: joining open groups using OpenGroupUrlParser.kt now * fix: add in compile issues for renamed OpenGroupApi.kt from OpenGroupV2 * fix: prevent duplicates of http/https for new open group DNS and prevent adding new groups based on public key * fix: room and server swapped parameters * fix: replace default server for config messages * fix: actually using public key to de-dupe didn't work for rooms * build: bump version code and name * Display reactions list on open groups for moderators * Ui tweaks * Ui tweaks for moderation * Refactor * fix: compile issue * fix: de-duping joined queries in the get X from cursor * Restore import * fix: colouring the reaction overlay scrubber * fix: highlight colour, show reaction count if 1 or above * Cleanup * fix: light mode accent * fix: light / dark mode themeing in reactions dialog fragment * Emoji notification blinded id check * fix: show reaction list correctly and pass isUserModerator to bind methods * fix: remove unnecessary places for the moderator * fix: X button for removing own react not showing up properly * feat: add clear all header view * fix: migrate the clear all to the correct location * fix: use display instead of base * Truncate emoji sender ids * feat: add notify thread function in thread db * Notify threads on reaction received * fix: design fixes for the reaction list * fix: emoji reactions bottom sheet dialog UI designs * feat: add unsupported emoji reaction * fix: crash and doing vector properly * Fix reaction database queries * Fix background open group adder job * Show new open group reactions * Fetch a maximum of 5 reactors * Handle open group reactions polling conflicts * Add count to user reaction * Show number of additional reactors * fix: unreads set same as the unread query * fix: design changes * fix: update dependency to improve flexboxlayout behaviour, design consistencies * Add select message icon and update long press menu items order and wording * Fix crash on reactors dialog * fix: colours and backgrounds to match designs * fix: add header in recipient item * fix: margins * fix: alignments and layout issues for emoji reactions view * feat: add overflow previews and logic for overflow * Dim action bar * Add emoji search * Search index fix * Set count for 1:1 and closed group reactions when inserting in local database * Use on screen toolbar to allow overlaying * Show/hide scroll to bottom button * feat: add extended properties so it doesn't collapse on re-bind * Cleanup * feat: prevent keeping extended on rebinding if we get a new message ID * fix: long press works on devices now, fix release lint issue and crash for emoji search DBs from emoji builds * Display message timestamp * Fix modal items alignment * fix: sort order and emoji count in compareTo * Scale down really large messages to fit * Prevent closed group crash * Fix reaction author Co-authored-by: charles <charles@oxen.io> Co-authored-by: jubb <hjubb@users.noreply.github.com>
2022-09-04 13:03:32 +02:00
import org.thoughtcrime.securesms.components.ProfilePictureView;
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
import org.thoughtcrime.securesms.database.model.MessageId;
import java.util.Collections;
import java.util.List;
import network.loki.messenger.R;
final class ReactionRecipientsAdapter extends RecyclerView.Adapter<ReactionRecipientsAdapter.ViewHolder> {
private static final int MAX_REACTORS = 5;
private static final int HEADER_COUNT = 1;
private static final int HEADER_POSITION = 0;
private static final int FOOTER_COUNT = 1;
private static final int FOOTER_POSITION = 6;
private static final int HEADER_TYPE = 0;
private static final int RECIPIENT_TYPE = 1;
private static final int FOOTER_TYPE = 2;
private ReactionViewPagerAdapter.Listener callback;
private List<ReactionDetails> data = Collections.emptyList();
private MessageId messageId;
private boolean isUserModerator;
private EmojiCount emojiData;
public ReactionRecipientsAdapter(ReactionViewPagerAdapter.Listener callback) {
this.callback = callback;
}
public void updateData(MessageId messageId, EmojiCount newData, boolean isUserModerator) {
this.messageId = messageId;
emojiData = newData;
data = newData.getReactions();
this.isUserModerator = isUserModerator;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
switch (position) {
case HEADER_POSITION:
return HEADER_TYPE;
case FOOTER_POSITION:
return FOOTER_TYPE;
default:
return RECIPIENT_TYPE;
}
}
@Override
public @NonNull
ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case HEADER_TYPE:
return new HeaderViewHolder(callback, LayoutInflater.from(parent.getContext()).inflate(R.layout.reactions_bottom_sheet_dialog_fragment_recycler_header, parent, false));
case FOOTER_TYPE:
return new FooterViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.reactions_bottom_sheet_dialog_fragment_recycler_footer, parent, false));
default:
return new RecipientViewHolder(callback, LayoutInflater.from(parent.getContext()).inflate(R.layout.reactions_bottom_sheet_dialog_fragment_recipient_item, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
if (holder instanceof RecipientViewHolder) {
((RecipientViewHolder) holder).bind(data.get(position - HEADER_COUNT));
} else if (holder instanceof HeaderViewHolder) {
((HeaderViewHolder) holder).bind(emojiData, messageId, isUserModerator);
} else if (holder instanceof FooterViewHolder) {
((FooterViewHolder) holder).bind(emojiData);
}
}
@Override
public void onViewRecycled(@NonNull ViewHolder holder) {
if (holder instanceof RecipientViewHolder) {
((RecipientViewHolder) holder).unbind();
}
}
@Override
public int getItemCount() {
if (data.isEmpty()) {
return 0;
} else if (emojiData.getCount() <= MAX_REACTORS) {
return data.size() + HEADER_COUNT;
} else {
return MAX_REACTORS + HEADER_COUNT + FOOTER_COUNT;
}
}
static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
}
static class HeaderViewHolder extends ViewHolder {
private final ReactionViewPagerAdapter.Listener callback;
public HeaderViewHolder(ReactionViewPagerAdapter.Listener callback, @NonNull View itemView) {
super(itemView);
this.callback = callback;
}
private void bind(@NonNull final EmojiCount emoji, final MessageId messageId, boolean isUserModerator) {
View clearAll = itemView.findViewById(R.id.header_view_clear_all);
clearAll.setVisibility(isUserModerator ? View.VISIBLE : View.GONE);
clearAll.setOnClickListener(isUserModerator ? (View.OnClickListener) v -> {
callback.onClearAll(emoji.getBaseEmoji(), messageId);
} : null);
EmojiImageView emojiView = itemView.findViewById(R.id.header_view_emoji);
emojiView.setImageEmoji(emoji.getDisplayEmoji());
TextView count = itemView.findViewById(R.id.header_view_emoji_count);
count.setText(String.format(" · %s", emoji.getCount()));
}
}
static final class RecipientViewHolder extends ViewHolder {
private ReactionViewPagerAdapter.Listener callback;
private final ProfilePictureView avatar;
private final TextView recipient;
private final ImageView remove;
public RecipientViewHolder(ReactionViewPagerAdapter.Listener callback, @NonNull View itemView) {
super(itemView);
this.callback = callback;
avatar = itemView.findViewById(R.id.reactions_bottom_view_avatar);
recipient = itemView.findViewById(R.id.reactions_bottom_view_recipient_name);
remove = itemView.findViewById(R.id.reactions_bottom_view_recipient_remove);
}
void bind(@NonNull ReactionDetails reaction) {
this.remove.setOnClickListener((v) -> {
MessageId messageId = new MessageId(reaction.getLocalId(), reaction.isMms());
callback.onRemoveReaction(reaction.getBaseEmoji(), messageId, reaction.getTimestamp());
});
this.avatar.update(reaction.getSender());
if (reaction.getSender().isLocalNumber()) {
this.recipient.setText(R.string.ReactionsRecipientAdapter_you);
this.remove.setVisibility(View.VISIBLE);
} else {
String name = reaction.getSender().getName();
if (name != null && new SessionId(name).getPrefix() != null) {
name = name.substring(0, 4) + "..." + name.substring(name.length() - 4);
}
this.recipient.setText(name);
this.remove.setVisibility(View.GONE);
}
}
void unbind() {
avatar.recycle();
}
}
static class FooterViewHolder extends ViewHolder {
public FooterViewHolder(@NonNull View itemView) {
super(itemView);
}
private void bind(@NonNull final EmojiCount emoji) {
if (emoji.getCount() > 5) {
TextView count = itemView.findViewById(R.id.footer_view_emoji_count);
count.setText(itemView.getContext().getResources().getQuantityString(R.plurals.ReactionsRecipientAdapter_other_reactors, emoji.getCount() - 5, emoji.getCount() - 5, emoji.getBaseEmoji()));
itemView.setVisibility(View.VISIBLE);
} else {
itemView.setVisibility(View.GONE);
}
}
}
}