1package eu.siacs.conversations.ui;
2
3import android.view.View;
4import android.view.ViewGroup;
5import android.util.TypedValue;
6
7import com.cheogram.android.EmojiSearch;
8
9import com.google.android.material.chip.Chip;
10import com.google.android.material.chip.ChipGroup;
11import com.google.android.material.color.MaterialColors;
12import com.google.android.material.dialog.MaterialAlertDialogBuilder;
13import com.google.common.collect.Collections2;
14import com.google.common.collect.ImmutableSet;
15
16import eu.siacs.conversations.R;
17import eu.siacs.conversations.entities.Conversation;
18import eu.siacs.conversations.entities.Reaction;
19import eu.siacs.conversations.utils.UIHelper;
20
21import java.util.Collection;
22import java.util.List;
23import java.util.Map;
24import java.util.function.Consumer;
25import java.util.stream.Collectors;
26
27public class BindingAdapters {
28
29 public static void setReactionsOnReceived(
30 final ChipGroup chipGroup,
31 final Conversation conversation,
32 final Reaction.Aggregated reactions,
33 final Consumer<Collection<String>> onModifiedReactions,
34 final Consumer<EmojiSearch.CustomEmoji> onCustomReaction,
35 final Consumer<Reaction> onCustomReactionRemove,
36 final Runnable addReaction) {
37 setReactions(chipGroup, conversation, reactions, true, onModifiedReactions, onCustomReaction, onCustomReactionRemove, addReaction);
38 }
39
40 public static void setReactionsOnSent(
41 final ChipGroup chipGroup,
42 final Reaction.Aggregated reactions,
43 final Consumer<Collection<String>> onModifiedReactions) {
44 setReactions(chipGroup, null, reactions, false, onModifiedReactions, null, null, null);
45 }
46
47 private static void setReactions(
48 final ChipGroup chipGroup,
49 final Conversation conversation,
50 final Reaction.Aggregated aggregated,
51 final boolean onReceived,
52 final Consumer<Collection<String>> onModifiedReactions,
53 final Consumer<EmojiSearch.CustomEmoji> onCustomReaction,
54 final Consumer<Reaction> onCustomReactionRemove,
55 final Runnable addReaction) {
56 final var context = chipGroup.getContext();
57 final var size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 35, context.getResources().getDisplayMetrics());
58 final var corner = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 35, context.getResources().getDisplayMetrics());
59 final var layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, size);
60 final List<Map.Entry<EmojiSearch.Emoji, Collection<Reaction>>> reactions = aggregated.reactions;
61 if (reactions == null || reactions.isEmpty()) {
62 chipGroup.setVisibility(View.GONE);
63 } else {
64 chipGroup.removeAllViews();
65 chipGroup.setVisibility(View.VISIBLE);
66 for (final var reaction : reactions) {
67 final var emoji = reaction.getKey();
68 final var count = reaction.getValue().size();
69 final Chip chip = new Chip(chipGroup.getContext());
70 //chip.setEnsureMinTouchTargetSize(false);
71 chip.setChipMinHeight(size-32.0f);
72 chip.ensureAccessibleTouchTarget(size);
73 chip.setLayoutParams(layoutParams);
74 chip.setChipCornerRadius(corner);
75 emoji.setupChip(chip, count);
76 final var oneOfOurs = reaction.getValue().stream().filter(r -> !r.received).findFirst();
77 // received = surface; sent = surface high matches bubbles
78 if (oneOfOurs.isPresent()) {
79 chip.setChipBackgroundColor(
80 MaterialColors.getColorStateListOrNull(
81 context,
82 com.google.android.material.R.attr
83 .colorSurfaceContainerHighest));
84 } else {
85 chip.setChipBackgroundColor(
86 MaterialColors.getColorStateListOrNull(
87 context,
88 com.google.android.material.R.attr.colorSurfaceContainerLow));
89 }
90 chip.setTextEndPadding(0.0f);
91 chip.setTextStartPadding(0.0f);
92 chip.setOnClickListener(
93 v -> {
94 if (oneOfOurs.isPresent()) {
95 if (emoji instanceof EmojiSearch.CustomEmoji) {
96 onCustomReactionRemove.accept(oneOfOurs.get());
97 } else {
98 onModifiedReactions.accept(
99 ImmutableSet.copyOf(
100 Collections2.filter(
101 aggregated.ourReactions,
102 r -> !r.equals(emoji.toString()))));
103 }
104 } else {
105 if (emoji instanceof EmojiSearch.CustomEmoji) {
106 onCustomReaction.accept((EmojiSearch.CustomEmoji) emoji);
107 } else {
108 onModifiedReactions.accept(
109 new ImmutableSet.Builder<String>()
110 .addAll(aggregated.ourReactions)
111 .add(emoji.toString())
112 .build());
113 }
114 }
115 });
116 chip.setOnLongClickListener(v -> {
117 final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
118 builder.setTitle(emoji.toString());
119 builder.setMessage(reaction.getValue().stream().map(r -> UIHelper.getDisplayName(conversation, r)).collect(Collectors.joining("\n")));
120 builder.setPositiveButton(context.getResources().getString(R.string.ok), null);
121 builder.create().show();
122 return true;
123 });
124 chipGroup.addView(chip);
125 }
126 if (addReaction != null) {
127 final Chip chip = new Chip(chipGroup.getContext());
128 chip.setChipMinHeight(size-32.0f);
129 chip.ensureAccessibleTouchTarget(size);
130 chip.setLayoutParams(layoutParams);
131 chip.setChipCornerRadius(corner);
132 chip.setChipIconResource(R.drawable.ic_add_reaction_24dp);
133 //chip.setChipStrokeColor(
134 // MaterialColors.getColorStateListOrNull(
135 // chipGroup.getContext(),
136 // com.google.android.material.R.attr.colorTertiary));
137 chip.setChipBackgroundColor(
138 MaterialColors.getColorStateListOrNull(
139 context,
140 com.google.android.material.R.attr.colorSurfaceContainerLow));
141 chip.setChipIconTint(
142 MaterialColors.getColorStateListOrNull(
143 context,
144 com.google.android.material.R.attr.colorOnSurface));
145 //chip.setEnsureMinTouchTargetSize(false);
146 chip.setTextEndPadding(0.0f);
147 chip.setTextStartPadding(0.0f);
148 chip.setOnClickListener(v -> addReaction.run());
149 chipGroup.addView(chip);
150 }
151 }
152 }
153}