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.common.collect.Collections2;
13import com.google.common.collect.ImmutableSet;
14
15import eu.siacs.conversations.R;
16import eu.siacs.conversations.entities.Reaction;
17import eu.siacs.conversations.utils.UIHelper;
18
19import java.util.Collection;
20import java.util.List;
21import java.util.Map;
22import java.util.function.Consumer;
23import java.util.stream.Collectors;
24import java.util.function.Function;
25
26public class BindingAdapters {
27
28 public static void setReactionsOnReceived(
29 final ChipGroup chipGroup,
30 final Reaction.Aggregated reactions,
31 final Consumer<Collection<String>> onModifiedReactions,
32 final Function<Map.Entry<EmojiSearch.Emoji, Collection<Reaction>>, Boolean> onDetailsClicked,
33 final Consumer<EmojiSearch.CustomEmoji> onCustomReaction,
34 final Consumer<Reaction> onCustomReactionRemove,
35 final Runnable addReaction) {
36 setReactions(chipGroup, reactions, true, onModifiedReactions, onDetailsClicked, onCustomReaction, onCustomReactionRemove, addReaction);
37 }
38
39 public static void setReactionsOnSent(
40 final ChipGroup chipGroup,
41 final Reaction.Aggregated reactions,
42 final Consumer<Collection<String>> onModifiedReactions,
43 final Function<Map.Entry<EmojiSearch.Emoji, Collection<Reaction>>, Boolean> onDetailsClicked) {
44 setReactions(chipGroup, reactions, false, onModifiedReactions, onDetailsClicked, null, null, null);
45 }
46
47 private static void setReactions(
48 final ChipGroup chipGroup,
49 final Reaction.Aggregated aggregated,
50 final boolean onReceived,
51 final Consumer<Collection<String>> onModifiedReactions,
52 final Function<Map.Entry<EmojiSearch.Emoji, Collection<Reaction>>, Boolean> onDetailsClicked,
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 -> onDetailsClicked.apply(reaction));
117 chipGroup.addView(chip);
118 }
119 if (addReaction != null) {
120 final Chip chip = new Chip(chipGroup.getContext());
121 chip.setChipMinHeight(size-32.0f);
122 chip.ensureAccessibleTouchTarget(size);
123 chip.setLayoutParams(layoutParams);
124 chip.setChipCornerRadius(corner);
125 chip.setChipIconResource(R.drawable.ic_add_reaction_24dp);
126 //chip.setChipStrokeColor(
127 // MaterialColors.getColorStateListOrNull(
128 // chipGroup.getContext(),
129 // com.google.android.material.R.attr.colorTertiary));
130 chip.setChipBackgroundColor(
131 MaterialColors.getColorStateListOrNull(
132 context,
133 com.google.android.material.R.attr.colorSurfaceContainerLow));
134 chip.setChipIconTint(
135 MaterialColors.getColorStateListOrNull(
136 context,
137 com.google.android.material.R.attr.colorOnSurface));
138 //chip.setEnsureMinTouchTargetSize(false);
139 chip.setTextEndPadding(0.0f);
140 chip.setTextStartPadding(0.0f);
141 chip.setOnClickListener(v -> addReaction.run());
142 chipGroup.addView(chip);
143 }
144 }
145 }
146}