Fix layout designer deadlock.

This commit is contained in:
Alex Hart 2021-05-07 15:25:30 -03:00 committed by Greyson Parrelli
parent dd934e0095
commit d672857e82
11 changed files with 44 additions and 62 deletions

View file

@ -19,7 +19,7 @@ public class EmojiFilter implements InputFilter {
char[] v = new char[end - start];
TextUtils.getChars(source, start, end, v, 0);
Spannable emojified = EmojiProvider.getInstance(view.getContext()).emojify(new String(v), view);
Spannable emojified = EmojiProvider.emojify(new String(v), view);
if (source instanceof Spanned && emojified != null) {
TextUtils.copySpansFrom((Spanned) source, start, end, null, emojified, 0);

View file

@ -5,6 +5,8 @@ import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatImageView;
import org.thoughtcrime.securesms.R;
public class EmojiImageView extends AppCompatImageView {
public EmojiImageView(Context context) {
super(context);
@ -15,6 +17,10 @@ public class EmojiImageView extends AppCompatImageView {
}
public void setImageEmoji(CharSequence emoji) {
setImageDrawable(EmojiProvider.getInstance(getContext()).getEmojiDrawable(emoji));
if (isInEditMode()) {
setImageResource(R.drawable.ic_emoji);
} else {
setImageDrawable(EmojiProvider.getEmojiDrawable(getContext(), emoji));
}
}
}

View file

@ -40,8 +40,7 @@ public class EmojiPageView extends FrameLayout implements VariationSelectorListe
layoutManager = new GridLayoutManager(context, 8);
scrollDisabler = new ScrollDisabler();
popup = new EmojiVariationSelectorPopup(context, emojiSelectionListener);
adapter = new EmojiPageViewGridAdapter(EmojiProvider.getInstance(context),
popup,
adapter = new EmojiPageViewGridAdapter(popup,
emojiSelectionListener,
this,
allowVariations);

View file

@ -19,20 +19,17 @@ import java.util.List;
public class EmojiPageViewGridAdapter extends RecyclerView.Adapter<EmojiPageViewGridAdapter.EmojiViewHolder> implements PopupWindow.OnDismissListener {
private final List<Emoji> emojiList;
private final EmojiProvider emojiProvider;
private final EmojiVariationSelectorPopup popup;
private final VariationSelectorListener variationSelectorListener;
private final EmojiEventListener emojiEventListener;
private final boolean allowVariations;
public EmojiPageViewGridAdapter(@NonNull EmojiProvider emojiProvider,
@NonNull EmojiVariationSelectorPopup popup,
public EmojiPageViewGridAdapter(@NonNull EmojiVariationSelectorPopup popup,
@NonNull EmojiEventListener emojiEventListener,
@NonNull VariationSelectorListener variationSelectorListener,
boolean allowVariations)
{
this.emojiList = new ArrayList<>();
this.emojiProvider = emojiProvider;
this.popup = popup;
this.emojiEventListener = emojiEventListener;
this.variationSelectorListener = variationSelectorListener;
@ -51,7 +48,7 @@ public class EmojiPageViewGridAdapter extends RecyclerView.Adapter<EmojiPageView
public void onBindViewHolder(@NonNull EmojiViewHolder viewHolder, int i) {
Emoji emoji = emojiList.get(i);
Drawable drawable = emojiProvider.getEmojiDrawable(emoji.getValue());
final Drawable drawable = EmojiProvider.getEmojiDrawable(viewHolder.imageView.getContext(), emoji.getValue());
if (drawable != null) {
viewHolder.textView.setVisibility(View.GONE);

View file

@ -28,45 +28,31 @@ import java.util.concurrent.ExecutionException;
class EmojiProvider {
private static final String TAG = Log.tag(EmojiProvider.class);
private static volatile EmojiProvider instance = null;
private static final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
private static final String TAG = Log.tag(EmojiProvider.class);
private static final Paint PAINT = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
private final Context context;
public static EmojiProvider getInstance(Context context) {
if (instance == null) {
synchronized (EmojiProvider.class) {
if (instance == null) {
instance = new EmojiProvider(context);
}
}
}
return instance;
}
private EmojiProvider(Context context) {
this.context = context.getApplicationContext();
}
@Nullable EmojiParser.CandidateList getCandidates(@Nullable CharSequence text) {
static @Nullable EmojiParser.CandidateList getCandidates(@Nullable CharSequence text) {
if (text == null) return null;
return new EmojiParser(EmojiSource.getLatest().getEmojiTree()).findCandidates(text);
}
@Nullable Spannable emojify(@Nullable CharSequence text, @NonNull TextView tv) {
return emojify(getCandidates(text), text, tv);
static @Nullable Spannable emojify(@Nullable CharSequence text, @NonNull TextView tv) {
if (tv.isInEditMode()) {
return null;
} else {
return emojify(getCandidates(text), text, tv);
}
}
@Nullable Spannable emojify(@Nullable EmojiParser.CandidateList matches,
@Nullable CharSequence text,
@NonNull TextView tv)
static @Nullable Spannable emojify(@Nullable EmojiParser.CandidateList matches,
@Nullable CharSequence text,
@NonNull TextView tv)
{
if (matches == null || text == null) return null;
if (matches == null || text == null || tv.isInEditMode()) return null;
SpannableStringBuilder builder = new SpannableStringBuilder(text);
for (EmojiParser.Candidate candidate : matches) {
Drawable drawable = getEmojiDrawable(candidate.getDrawInfo());
Drawable drawable = getEmojiDrawable(tv.getContext(), candidate.getDrawInfo());
if (drawable != null) {
builder.setSpan(new EmojiSpan(drawable, tv), candidate.getStartIndex(), candidate.getEndIndex(),
@ -77,12 +63,12 @@ class EmojiProvider {
return builder;
}
@Nullable Drawable getEmojiDrawable(CharSequence emoji) {
static @Nullable Drawable getEmojiDrawable(@NonNull Context context, @Nullable CharSequence emoji) {
EmojiDrawInfo drawInfo = EmojiSource.getLatest().getEmojiTree().getEmoji(emoji, 0, emoji.length());
return getEmojiDrawable(drawInfo);
return getEmojiDrawable(context, drawInfo);
}
private @Nullable Drawable getEmojiDrawable(@Nullable EmojiDrawInfo drawInfo) {
private static @Nullable Drawable getEmojiDrawable(@NonNull Context context, @Nullable EmojiDrawInfo drawInfo) {
if (drawInfo == null) {
return null;
}
@ -151,7 +137,7 @@ class EmojiProvider {
canvas.drawBitmap(bmp,
emojiBounds,
getBounds(),
paint);
PAINT);
}
public void setBitmap(Bitmap bitmap) {

View file

@ -91,8 +91,7 @@ public class EmojiTextView extends AppCompatTextView {
}
@Override public void setText(@Nullable CharSequence text, BufferType type) {
EmojiProvider provider = EmojiProvider.getInstance(getContext());
EmojiParser.CandidateList candidates = !isInEditMode() ? provider.getCandidates(text) : null;
EmojiParser.CandidateList candidates = isInEditMode() ? null : EmojiProvider.getCandidates(text);
if (scaleEmojis && candidates != null && candidates.allEmojis) {
int emojis = candidates.size();
@ -124,7 +123,7 @@ public class EmojiTextView extends AppCompatTextView {
ellipsizeAnyTextForMaxLength();
}
} else {
CharSequence emojified = provider.emojify(candidates, text, this);
CharSequence emojified = EmojiProvider.emojify(candidates, text, this);
super.setText(new SpannableStringBuilder(emojified).append(Optional.fromNullable(overflowText).or("")), BufferType.SPANNABLE);
// Android fails to ellipsize spannable strings. (https://issuetracker.google.com/issues/36991688)
@ -165,12 +164,12 @@ public class EmojiTextView extends AppCompatTextView {
.append(ELLIPSIS)
.append(Util.emptyIfNull(overflowText));
EmojiParser.CandidateList newCandidates = EmojiProvider.getInstance(getContext()).getCandidates(newContent);
EmojiParser.CandidateList newCandidates = isInEditMode() ? null : EmojiProvider.getCandidates(newContent);
if (useSystemEmoji || newCandidates == null || newCandidates.size() == 0) {
super.setText(newContent, BufferType.NORMAL);
} else {
CharSequence emojified = EmojiProvider.getInstance(getContext()).emojify(newCandidates, newContent, this);
CharSequence emojified = EmojiProvider.emojify(newCandidates, newContent, this);
super.setText(emojified, BufferType.SPANNABLE);
}
}
@ -199,8 +198,8 @@ public class EmojiTextView extends AppCompatTextView {
.append(ellipsized.subSequence(0, ellipsized.length()))
.append(Optional.fromNullable(overflowText).or(""));
EmojiParser.CandidateList newCandidates = EmojiProvider.getInstance(getContext()).getCandidates(newContent);
CharSequence emojified = EmojiProvider.getInstance(getContext()).emojify(newCandidates, newContent, this);
EmojiParser.CandidateList newCandidates = isInEditMode() ? null : EmojiProvider.getCandidates(newContent);
CharSequence emojified = EmojiProvider.emojify(newCandidates, newContent, this);
super.setText(emojified, BufferType.SPANNABLE);
}

View file

@ -12,10 +12,7 @@ import org.thoughtcrime.securesms.emoji.ObsoleteEmoji;
import org.thoughtcrime.securesms.util.StringUtil;
import org.thoughtcrime.securesms.util.Util;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
@ -63,7 +60,7 @@ public final class EmojiUtil {
if (Util.isEmpty(emoji)) {
return null;
} else {
return EmojiProvider.getInstance(context).getEmojiDrawable(emoji);
return EmojiProvider.getEmojiDrawable(context, emoji);
}
}
@ -74,7 +71,7 @@ public final class EmojiUtil {
* followed by a more wide check for all of the valid emoji unicode ranges (which could lead to
* some false positives). YMMV.
*/
public static boolean isEmoji(@NonNull Context context, @Nullable String text) {
public static boolean isEmoji(@Nullable String text) {
if (Util.isEmpty(text)) {
return false;
}
@ -83,7 +80,7 @@ public final class EmojiUtil {
return false;
}
EmojiParser.CandidateList candidates = EmojiProvider.getInstance(context).getCandidates(text);
EmojiParser.CandidateList candidates = EmojiProvider.getCandidates(text);
return (candidates != null && candidates.size() > 0) || EMOJI_PATTERN.matcher(text).matches();
}

View file

@ -42,7 +42,7 @@ public class EmojiVariationSelectorPopup extends PopupWindow {
for (String variation : variations) {
ImageView imageView = (ImageView) LayoutInflater.from(context).inflate(R.layout.emoji_variation_selector_item, list, false);
imageView.setImageDrawable(EmojiProvider.getInstance(context).getEmojiDrawable(variation));
imageView.setImageDrawable(EmojiProvider.getEmojiDrawable(context, variation));
imageView.setOnClickListener(v -> {
listener.onEmojiSelected(variation);
dismiss();

View file

@ -106,7 +106,6 @@ import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.Hex;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MessageRecordUtil;
import org.thoughtcrime.securesms.util.RemoteDeleteUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
@ -154,7 +153,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
/**
@ -719,7 +717,7 @@ public final class MessageContentProcessor {
private void handleReaction(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
SignalServiceDataMessage.Reaction reaction = message.getReaction().get();
if (!EmojiUtil.isEmoji(context, reaction.getEmoji())) {
if (!EmojiUtil.isEmoji(reaction.getEmoji())) {
Log.w(TAG, "Reaction text is not a valid emoji! Ignoring the message.");
return;
}

View file

@ -241,7 +241,7 @@ public class EditAboutFragment extends Fragment implements ManageProfileActivity
}
public void bind(@NonNull AboutPreset preset) {
this.emoji.setImageDrawable(EmojiUtil.convertToDrawable(itemView.getContext(), preset.getEmoji()));
this.emoji.setImageDrawable(EmojiUtil.convertToDrawable(requireContext(), preset.getEmoji()));
this.body.setText(preset.getBodyRes());
}
}

View file

@ -71,10 +71,10 @@ public class EmojiUtilTest_isEmoji {
@Test
public void isEmoji() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
Application application = ApplicationProvider.getApplicationContext();
PowerMockito.mockStatic(ApplicationDependencies.class);
PowerMockito.when(ApplicationDependencies.getApplication()).thenReturn((Application) context);
PowerMockito.when(ApplicationDependencies.getApplication()).thenReturn(application);
PowerMockito.mockStatic(AttachmentSecretProvider.class);
PowerMockito.when(AttachmentSecretProvider.getInstance(any())).thenThrow(IOException.class);
PowerMockito.whenNew(SignalStore.class).withAnyArguments().thenReturn(null);
@ -82,6 +82,6 @@ public class EmojiUtilTest_isEmoji {
PowerMockito.when(SignalStore.internalValues()).thenReturn(PowerMockito.mock(InternalValues.class));
EmojiSource.refresh();
assertEquals(output, EmojiUtil.isEmoji(context, input));
assertEquals(output, EmojiUtil.isEmoji(input));
}
}