diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java index c8283640b..56ec0c3f0 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/settings/SettingsManager.java @@ -1,6 +1,7 @@ package org.briarproject.bramble.api.settings; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @NotNullByDefault @@ -11,6 +12,11 @@ public interface SettingsManager { */ Settings getSettings(String namespace) throws DbException; + /** + * Returns all settings in the given namespace. + */ + Settings getSettings(Transaction txn, String namespace) throws DbException; + /** * Merges the given settings with any existing settings in the given * namespace. diff --git a/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsManagerImpl.java index 5663f8e8b..13d2c6a25 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/settings/SettingsManagerImpl.java @@ -34,6 +34,12 @@ class SettingsManagerImpl implements SettingsManager { return s; } + @Override + public Settings getSettings(Transaction txn, String namespace) + throws DbException { + return db.getSettings(txn, namespace); + } + @Override public void mergeSettings(Settings s, String namespace) throws DbException { Transaction txn = db.startTransaction(false); diff --git a/briar-android/build.gradle b/briar-android/build.gradle index d9e683775..bb4988e82 100644 --- a/briar-android/build.gradle +++ b/briar-android/build.gradle @@ -31,9 +31,8 @@ dependencies { implementation 'info.guardianproject.trustedintents:trustedintents:0.2' implementation 'de.hdodenhof:circleimageview:2.2.0' implementation 'com.google.zxing:core:3.3.0' - implementation 'com.jpardogo.materialtabstrip:library:1.1.0' - implementation 'com.github.bumptech.glide:glide:3.8.0' implementation 'uk.co.samuelwall:material-tap-target-prompt:2.8.0' + implementation 'com.vanniktech:emoji-google:0.5.1' annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2' @@ -80,7 +79,7 @@ android { buildToolsVersion '27.0.3' defaultConfig { - minSdkVersion 14 + minSdkVersion 15 targetSdkVersion 26 versionCode 10013 versionName "1.0.13" diff --git a/briar-android/proguard-rules.txt b/briar-android/proguard-rules.txt index 88fb5b29b..f673f857a 100644 --- a/briar-android/proguard-rules.txt +++ b/briar-android/proguard-rules.txt @@ -27,9 +27,4 @@ -dontnote org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout # Emoji --keep class org.thoughtcrime.securesms.** --keep class com.astuetz.PagerSlidingTabStrip$OnTabReselectedListener --keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { - **[] $VALUES; - public *; -} +-keep class com.vanniktech.emoji.** diff --git a/briar-android/src/main/assets/emoji_activity.png b/briar-android/src/main/assets/emoji_activity.png deleted file mode 100644 index 908370dd1..000000000 Binary files a/briar-android/src/main/assets/emoji_activity.png and /dev/null differ diff --git a/briar-android/src/main/assets/emoji_animals_nature.png b/briar-android/src/main/assets/emoji_animals_nature.png deleted file mode 100644 index 7a0661fe1..000000000 Binary files a/briar-android/src/main/assets/emoji_animals_nature.png and /dev/null differ diff --git a/briar-android/src/main/assets/emoji_flags.png b/briar-android/src/main/assets/emoji_flags.png deleted file mode 100644 index 80f6bbd0d..000000000 Binary files a/briar-android/src/main/assets/emoji_flags.png and /dev/null differ diff --git a/briar-android/src/main/assets/emoji_food_drink.png b/briar-android/src/main/assets/emoji_food_drink.png deleted file mode 100644 index 33d7cd0a6..000000000 Binary files a/briar-android/src/main/assets/emoji_food_drink.png and /dev/null differ diff --git a/briar-android/src/main/assets/emoji_objects.png b/briar-android/src/main/assets/emoji_objects.png deleted file mode 100644 index f2b6dfbf9..000000000 Binary files a/briar-android/src/main/assets/emoji_objects.png and /dev/null differ diff --git a/briar-android/src/main/assets/emoji_smiley_people.png b/briar-android/src/main/assets/emoji_smiley_people.png deleted file mode 100644 index 9325d703a..000000000 Binary files a/briar-android/src/main/assets/emoji_smiley_people.png and /dev/null differ diff --git a/briar-android/src/main/assets/emoji_symbols.png b/briar-android/src/main/assets/emoji_symbols.png deleted file mode 100644 index e88275b2f..000000000 Binary files a/briar-android/src/main/assets/emoji_symbols.png and /dev/null differ diff --git a/briar-android/src/main/assets/emoji_travel_places.png b/briar-android/src/main/assets/emoji_travel_places.png deleted file mode 100644 index 16e2be37d..000000000 Binary files a/briar-android/src/main/assets/emoji_travel_places.png and /dev/null differ diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java index 771a2ad57..6971b49a6 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java @@ -28,6 +28,7 @@ import org.briarproject.briar.BriarCoreEagerSingletons; import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.android.login.SignInReminderReceiver; import org.briarproject.briar.android.reporting.BriarReportSender; +import org.briarproject.briar.android.view.TextInputView; import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.DozeWatchdog; import org.briarproject.briar.api.android.LockManager; @@ -49,8 +50,6 @@ import org.briarproject.briar.api.privategroup.PrivateGroupManager; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory; import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager; import org.briarproject.briar.api.test.TestDataCreator; -import org.thoughtcrime.securesms.components.emoji.EmojiProvider; -import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel; import java.util.concurrent.Executor; @@ -161,12 +160,10 @@ public interface AndroidComponent void inject(BriarReportSender briarReportSender); - void inject(EmojiProvider emojiProvider); - - void inject(RecentEmojiPageModel recentEmojiPageModel); - void inject(NotificationCleanupService notificationCleanupService); + void inject(TextInputView textInputView); + // Eager singleton load void inject(AppModule.EagerSingletons init); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index 3c3512281..606647958 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -5,6 +5,8 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.StrictMode; +import com.vanniktech.emoji.RecentEmoji; + import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.db.DatabaseConfig; @@ -65,6 +67,8 @@ public class AppModule { NetworkUsageLogger networkUsageLogger; @Inject DozeWatchdog dozeWatchdog; + @Inject + RecentEmoji recentEmoji; } private final Application application; @@ -211,4 +215,11 @@ public class AppModule { return lockManager; } + @Provides + @Singleton + RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager, + RecentEmojiImpl recentEmoji) { + lifecycleManager.registerClient(recentEmoji); + return recentEmoji; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java index e56adf30e..554bc1755 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarApplicationImpl.java @@ -9,6 +9,9 @@ import android.os.StrictMode.ThreadPolicy; import android.os.StrictMode.VmPolicy; import android.preference.PreferenceManager; +import com.vanniktech.emoji.EmojiManager; +import com.vanniktech.emoji.google.GoogleEmojiProvider; + import org.acra.ACRA; import org.acra.ReportingInteractionMode; import org.acra.annotation.ReportsCrashes; @@ -110,6 +113,7 @@ public class BriarApplicationImpl extends Application LOG.info("Created"); applicationComponent = createApplicationComponent(); + EmojiManager.install(new GoogleEmojiProvider()); } protected AndroidComponent createApplicationComponent() { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/RecentEmojiImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/RecentEmojiImpl.java new file mode 100644 index 000000000..72e4b7e96 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/RecentEmojiImpl.java @@ -0,0 +1,114 @@ +package org.briarproject.briar.android; + +import com.vanniktech.emoji.EmojiRange; +import com.vanniktech.emoji.EmojiUtils; +import com.vanniktech.emoji.RecentEmoji; +import com.vanniktech.emoji.emoji.Emoji; + +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.Transaction; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.bramble.api.settings.Settings; +import org.briarproject.bramble.api.settings.SettingsManager; +import org.briarproject.bramble.api.sync.Client; +import org.briarproject.bramble.api.system.AndroidExecutor; +import org.briarproject.bramble.util.StringUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault +class RecentEmojiImpl implements RecentEmoji, Client { + + private static final Logger LOG = + Logger.getLogger(RecentEmojiImpl.class.getName()); + + private static final String EMOJI_LRU_PREFERENCE = "pref_emoji_recent2"; + private static final int EMOJI_LRU_SIZE = 50; + + // UI thread + private final LinkedHashSet recentlyUsed = new LinkedHashSet<>(); + + private final Executor dbExecutor; + private final AndroidExecutor androidExecutor; + private final SettingsManager settingsManager; + + @Inject + RecentEmojiImpl(@DatabaseExecutor Executor dbExecutor, + AndroidExecutor androidExecutor, SettingsManager settingsManager) { + this.dbExecutor = dbExecutor; + this.androidExecutor = androidExecutor; + this.settingsManager = settingsManager; + } + + @Override + public Collection getRecentEmojis() { + return new ArrayList<>(recentlyUsed); + } + + @Override + public void addEmoji(Emoji emoji) { + recentlyUsed.remove(emoji); + recentlyUsed.add(emoji); + + if (recentlyUsed.size() > EMOJI_LRU_SIZE) { + Iterator iterator = recentlyUsed.iterator(); + iterator.next(); + iterator.remove(); + } + } + + @Override + public void persist() { + if (!recentlyUsed.isEmpty()) save(serialize(recentlyUsed)); + } + + @Override + public void createLocalState(Transaction txn) throws DbException { + Settings settings = + settingsManager.getSettings(txn, SETTINGS_NAMESPACE); + String serialized = settings.get(EMOJI_LRU_PREFERENCE); + if (serialized != null) { + androidExecutor.runOnUiThread(() -> + recentlyUsed.addAll(deserialize(serialized))); + } + } + + private String serialize(Collection emojis) { + Collection strings = new ArrayList<>(emojis.size()); + for (Emoji emoji : emojis) strings.add(emoji.getUnicode()); + return StringUtils.join(strings, "\t"); + } + + private Collection deserialize(String serialized) { + Collection ranges = EmojiUtils.emojis(serialized); + Collection result = new ArrayList<>(ranges.size()); + for (EmojiRange range : ranges) result.add(range.emoji); + return result; + } + + private void save(String serialized) { + dbExecutor.execute(() -> { + Settings settings = new Settings(); + settings.put(EMOJI_LRU_PREFERENCE, serialized); + try { + settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); + } catch (DbException e) { + logException(LOG, WARNING, e); + } + }); + } +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java index 81434df6a..a21557d16 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/ReblogFragment.java @@ -119,6 +119,7 @@ public class ReblogFragment extends BaseFragment implements TextInputListener { @Override public void onSendClick(String text) { + ui.input.hideSoftKeyboard(); String comment = getComment(); feedController.repeatPost(item, comment, new UiExceptionHandler(this) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java index 20c4500fe..eb7b9812c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/blog/WriteBlogPostActivity.java @@ -134,6 +134,7 @@ public class WriteBlogPostActivity extends BriarActivity @Override public void onSendClick(String body) { // hide publish button, show progress bar + input.hideSoftKeyboard(); input.setVisibility(GONE); progressBar.setVisibility(VISIBLE); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java index fd77da85d..822262459 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java @@ -202,7 +202,6 @@ public class GroupActivity extends if (!enabled) { textInput.setVisibility(GONE); if (textInput.isKeyboardOpen()) textInput.hideSoftKeyboard(); - if (textInput.isEmojiDrawerOpen()) textInput.hideEmojiDrawer(); } else { textInput.setVisibility(VISIBLE); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java index 9bcd6c451..1427f33ef 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/LargeTextInputView.java @@ -8,6 +8,8 @@ import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.Button; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.R; import javax.annotation.Nullable; @@ -15,6 +17,8 @@ import javax.annotation.Nullable; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; @UiThread +@MethodsNotNullByDefault +@ParametersNotNullByDefault public class LargeTextInputView extends TextInputView { public LargeTextInputView(Context context) { @@ -46,30 +50,28 @@ public class LargeTextInputView extends TextInputView { R.styleable.LargeTextInputView); String buttonText = attributes.getString(R.styleable.LargeTextInputView_buttonText); - int maxLines = - attributes - .getInteger(R.styleable.LargeTextInputView_maxLines, 0); + int maxLines = attributes + .getInteger(R.styleable.LargeTextInputView_maxLines, 0); boolean fillHeight = attributes - .getBoolean(R.styleable.LargeTextInputView_fillHeight, - false); + .getBoolean(R.styleable.LargeTextInputView_fillHeight, false); attributes.recycle(); if (buttonText != null) setButtonText(buttonText); - if (maxLines > 0) ui.editText.setMaxLines(maxLines); + if (maxLines > 0) editText.setMaxLines(maxLines); if (fillHeight) { ViewGroup layout = findViewById(R.id.input_layout); LayoutParams params = (LayoutParams) layout.getLayoutParams(); params.height = 0; params.weight = 1; layout.setLayoutParams(params); - ViewGroup.LayoutParams editParams = ui.editText.getLayoutParams(); + ViewGroup.LayoutParams editParams = editText.getLayoutParams(); editParams.height = MATCH_PARENT; - ui.editText.setLayoutParams(editParams); + editText.setLayoutParams(editParams); } } public void setButtonText(String text) { - ((Button) ui.sendButton).setText(text); + ((Button) sendButton).setText(text); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java index 06bd583e6..0733fb4a0 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/view/TextInputView.java @@ -8,35 +8,47 @@ import android.os.IBinder; import android.support.annotation.CallSuper; import android.support.annotation.StringRes; import android.support.annotation.UiThread; +import android.support.v7.widget.AppCompatImageButton; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.InputMethodManager; +import com.vanniktech.emoji.EmojiEditText; +import com.vanniktech.emoji.EmojiPopup; +import com.vanniktech.emoji.RecentEmoji; + +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.R; +import org.briarproject.briar.android.BriarApplication; import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout; -import org.thoughtcrime.securesms.components.emoji.EmojiDrawer; -import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiEventListener; -import org.thoughtcrime.securesms.components.emoji.EmojiEditText; -import org.thoughtcrime.securesms.components.emoji.EmojiToggle; import javax.annotation.Nullable; +import javax.inject.Inject; import static android.content.Context.INPUT_METHOD_SERVICE; import static android.content.Context.LAYOUT_INFLATER_SERVICE; -import static android.view.KeyEvent.KEYCODE_BACK; import static android.view.KeyEvent.KEYCODE_ENTER; import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT; @UiThread -public class TextInputView extends KeyboardAwareLinearLayout - implements EmojiEventListener { +@MethodsNotNullByDefault +@ParametersNotNullByDefault +public class TextInputView extends KeyboardAwareLinearLayout { - protected final ViewHolder ui; - protected TextInputListener listener; + @Inject + RecentEmoji recentEmoji; + + @Nullable + TextInputListener listener; + + AppCompatImageButton emojiToggle; + EmojiEditText editText; + EmojiPopup emojiPopup; + View sendButton; public TextInputView(Context context) { this(context, null); @@ -49,11 +61,12 @@ public class TextInputView extends KeyboardAwareLinearLayout public TextInputView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); + BriarApplication app = + (BriarApplication) context.getApplicationContext(); + app.getApplicationComponent().inject(this); setOrientation(VERTICAL); setLayoutTransition(new LayoutTransition()); - inflateLayout(context); - ui = new ViewHolder(); setUpViews(context, attrs); } @@ -65,89 +78,79 @@ public class TextInputView extends KeyboardAwareLinearLayout @CallSuper protected void setUpViews(Context context, @Nullable AttributeSet attrs) { + emojiToggle = findViewById(R.id.emoji_toggle); + editText = findViewById(R.id.input_text); + emojiPopup = EmojiPopup.Builder + .fromRootView(this) + .setRecentEmoji(recentEmoji) + .setOnEmojiPopupShownListener(this::showKeyboardIcon) + .setOnEmojiPopupDismissListener(this::showEmojiIcon) + .build(editText); + sendButton = findViewById(R.id.btn_send); + // get attributes TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.TextInputView); String hint = attributes.getString(R.styleable.TextInputView_hint); attributes.recycle(); - if (hint != null) { - ui.editText.setHint(hint); - } + if (hint != null) editText.setHint(hint); - ui.emojiToggle.attach(ui.emojiDrawer); - ui.emojiToggle.setOnClickListener(v -> onEmojiToggleClicked()); - ui.editText.setOnClickListener(v -> showSoftKeyboard()); - ui.editText.setOnKeyListener((v, keyCode, event) -> { - if (keyCode == KEYCODE_BACK && isEmojiDrawerOpen()) { - hideEmojiDrawer(); - return true; - } + emojiToggle.setOnClickListener(v -> emojiPopup.toggle()); + editText.setOnClickListener(v -> showSoftKeyboard()); + editText.setOnKeyListener((v, keyCode, event) -> { if (keyCode == KEYCODE_ENTER && event.isCtrlPressed()) { trySendMessage(); return true; } return false; }); - ui.sendButton.setOnClickListener(v -> trySendMessage()); - ui.emojiDrawer.setEmojiEventListener(this); + sendButton.setOnClickListener(v -> trySendMessage()); + } + + private void showEmojiIcon() { + emojiToggle.setImageResource(R.drawable.ic_emoji_toggle); + } + + private void showKeyboardIcon() { + emojiToggle.setImageResource(R.drawable.ic_keyboard); } private void trySendMessage() { if (listener != null) { - listener.onSendClick(ui.editText.getText().toString()); + listener.onSendClick(editText.getText().toString()); } } - @Override - public void setVisibility(int visibility) { - if (visibility == GONE && isKeyboardOpen()) { - onKeyboardClose(); - } - super.setVisibility(visibility); - } - - @Override - public void onKeyEvent(KeyEvent keyEvent) { - ui.editText.dispatchKeyEvent(keyEvent); - } - - @Override - public void onEmojiSelected(String emoji) { - ui.editText.insertEmoji(emoji); - } - @Override public boolean requestFocus(int direction, Rect previouslyFocusedRect) { - return ui.editText.requestFocus(direction, previouslyFocusedRect); + return editText.requestFocus(direction, previouslyFocusedRect); } - private void onEmojiToggleClicked() { - if (isEmojiDrawerOpen()) { - showSoftKeyboard(); - } else { - showEmojiDrawer(); - } + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (emojiPopup.isShowing()) emojiPopup.dismiss(); } public void setText(String text) { - ui.editText.setText(text); + editText.setText(text); } public Editable getText() { - return ui.editText.getText(); + return editText.getText(); } public void setHint(@StringRes int res) { - ui.editText.setHint(res); + editText.setHint(res); } public void setSendButtonEnabled(boolean enabled) { - ui.sendButton.setEnabled(enabled); + sendButton.setEnabled(enabled); } public void addTextChangedListener(TextWatcher watcher) { - ui.editText.addTextChangedListener(watcher); + editText.addTextChangedListener(watcher); } public void setListener(TextInputListener listener) { @@ -155,58 +158,17 @@ public class TextInputView extends KeyboardAwareLinearLayout } public void showSoftKeyboard() { - if (isKeyboardOpen()) return; - - if (ui.emojiDrawer.isShowing()) { - postOnKeyboardOpen(this::hideEmojiDrawer); - } - ui.editText.post(() -> { - ui.editText.requestFocus(); - InputMethodManager imm = (InputMethodManager) - getContext().getSystemService(INPUT_METHOD_SERVICE); - imm.showSoftInput(ui.editText, SHOW_IMPLICIT); - }); + Object o = getContext().getSystemService(INPUT_METHOD_SERVICE); + ((InputMethodManager) o).showSoftInput(editText, SHOW_IMPLICIT); } public void hideSoftKeyboard() { - IBinder token = ui.editText.getWindowToken(); + if (emojiPopup.isShowing()) emojiPopup.dismiss(); + IBinder token = editText.getWindowToken(); Object o = getContext().getSystemService(INPUT_METHOD_SERVICE); ((InputMethodManager) o).hideSoftInputFromWindow(token, 0); } - public void showEmojiDrawer() { - if (isKeyboardOpen()) { - postOnKeyboardClose(() -> ui.emojiDrawer.show(getKeyboardHeight())); - hideSoftKeyboard(); - } else { - ui.emojiDrawer.show(getKeyboardHeight()); - ui.editText.requestFocus(); - } - } - - public void hideEmojiDrawer() { - ui.emojiDrawer.hide(); - } - - public boolean isEmojiDrawerOpen() { - return ui.emojiDrawer.isShowing(); - } - - protected class ViewHolder { - - private final EmojiToggle emojiToggle; - final EmojiEditText editText; - final View sendButton; - final EmojiDrawer emojiDrawer; - - private ViewHolder() { - emojiToggle = findViewById(R.id.emoji_toggle); - editText = findViewById(R.id.input_text); - emojiDrawer = findViewById(R.id.emoji_drawer); - sendButton = findViewById(R.id.btn_send); - } - } - public interface TextInputListener { void onSendClick(String text); } diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/RepeatableImageKey.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/RepeatableImageKey.java deleted file mode 100644 index 51e740186..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/RepeatableImageKey.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.thoughtcrime.securesms.components; - -import android.content.Context; -import android.support.annotation.UiThread; -import android.support.v7.widget.AppCompatImageButton; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -import static android.view.HapticFeedbackConstants.KEYBOARD_TAP; -import static android.view.MotionEvent.ACTION_CANCEL; -import static android.view.MotionEvent.ACTION_DOWN; -import static android.view.MotionEvent.ACTION_UP; - -@UiThread -public class RepeatableImageKey extends AppCompatImageButton { - - private KeyEventListener listener; - - public RepeatableImageKey(Context context) { - super(context); - init(); - } - - public RepeatableImageKey(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public RepeatableImageKey(Context context, AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - setOnClickListener(new RepeaterClickListener()); - setOnTouchListener(new RepeaterTouchListener()); - } - - public void setOnKeyEventListener(KeyEventListener listener) { - this.listener = listener; - } - - private void notifyListener() { - if (listener != null) listener.onKeyEvent(); - } - - private class RepeaterClickListener implements OnClickListener { - @Override - public void onClick(View v) { - notifyListener(); - } - } - - private class Repeater implements Runnable { - @Override - public void run() { - notifyListener(); - postDelayed(this, ViewConfiguration.getKeyRepeatDelay()); - } - } - - private class RepeaterTouchListener implements OnTouchListener { - - private final Repeater repeater; - - private RepeaterTouchListener() { - repeater = new Repeater(); - } - - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - switch (motionEvent.getAction()) { - case ACTION_DOWN: - view.postDelayed(repeater, - ViewConfiguration.getKeyRepeatTimeout()); - performHapticFeedback(KEYBOARD_TAP); - return false; - case ACTION_CANCEL: - case ACTION_UP: - view.removeCallbacks(repeater); - return false; - default: - return false; - } - } - } - - public interface KeyEventListener { - void onKeyEvent(); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java deleted file mode 100644 index 28a71933f..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/AnimatingImageSpan.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Drawable.Callback; -import android.support.annotation.UiThread; -import android.text.style.ImageSpan; - -@UiThread -class AnimatingImageSpan extends ImageSpan { - - AnimatingImageSpan(Drawable drawable, Callback callback) { - super(drawable, ALIGN_BOTTOM); - drawable.setCallback(callback); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java deleted file mode 100644 index d54f4cbca..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiDrawer.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.support.annotation.NonNull; -import android.support.annotation.UiThread; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.support.v7.widget.AppCompatImageView; -import android.util.AttributeSet; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import com.astuetz.PagerSlidingTabStrip; -import com.astuetz.PagerSlidingTabStrip.CustomTabProvider; - -import org.briarproject.briar.R; -import org.thoughtcrime.securesms.components.RepeatableImageKey; -import org.thoughtcrime.securesms.components.emoji.EmojiPageView.EmojiSelectionListener; - -import java.util.LinkedList; -import java.util.List; -import java.util.logging.Logger; - -import javax.annotation.Nullable; - -import static android.support.v4.widget.ImageViewCompat.setImageTintList; -import static android.view.KeyEvent.ACTION_DOWN; -import static android.view.KeyEvent.KEYCODE_DEL; -import static android.widget.ImageView.ScaleType.CENTER_INSIDE; -import static java.util.logging.Level.INFO; - -@UiThread -public class EmojiDrawer extends LinearLayout { - - private static final Logger LOG = - Logger.getLogger(EmojiDrawer.class.getName()); - private static final KeyEvent DELETE_KEY_EVENT = - new KeyEvent(ACTION_DOWN, KEYCODE_DEL); - - private ViewPager pager; - private List models; - private PagerSlidingTabStrip strip; - private RecentEmojiPageModel recentModel; - private EmojiEventListener listener; - private EmojiDrawerListener drawerListener; - - public EmojiDrawer(Context context) { - this(context, null); - } - - public EmojiDrawer(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - setOrientation(VERTICAL); - } - - private void initView() { - View v = LayoutInflater.from(getContext()) - .inflate(R.layout.emoji_drawer, this, true); - initializeResources(v); - initializePageModels(); - initializeEmojiGrid(); - } - - public void setEmojiEventListener(EmojiEventListener listener) { - this.listener = listener; - } - - public void setDrawerListener(EmojiDrawerListener listener) { - this.drawerListener = listener; - } - - private void initializeResources(View v) { - this.pager = v.findViewById(R.id.emoji_pager); - this.strip = v.findViewById(R.id.tabs); - - RepeatableImageKey backspace = v.findViewById(R.id.backspace); - backspace.setOnKeyEventListener(() -> { - if (listener != null) listener.onKeyEvent(DELETE_KEY_EVENT); - }); - } - - public boolean isShowing() { - return getVisibility() == VISIBLE; - } - - public void show(int height) { - if (this.pager == null) initView(); - ViewGroup.LayoutParams params = getLayoutParams(); - params.height = height; - if (LOG.isLoggable(INFO)) - LOG.info("Showing emoji drawer with height " + params.height); - setLayoutParams(params); - setVisibility(VISIBLE); - if (drawerListener != null) drawerListener.onShown(); - } - - public void hide() { - setVisibility(GONE); - if (drawerListener != null) drawerListener.onHidden(); - } - - private void initializeEmojiGrid() { - pager.setAdapter(new EmojiPagerAdapter(getContext(), models, - emoji -> { - recentModel.onCodePointSelected(emoji); - if (listener != null) listener.onEmojiSelected(emoji); - })); - - if (recentModel.getEmoji().length == 0) { - pager.setCurrentItem(1); - } - strip.setViewPager(pager); - } - - private void initializePageModels() { - this.models = new LinkedList<>(); - this.recentModel = new RecentEmojiPageModel(getContext()); - this.models.add(recentModel); - this.models.addAll(EmojiProvider.getInstance(getContext()) - .getStaticPages()); - } - - public static class EmojiPagerAdapter extends PagerAdapter - implements CustomTabProvider { - private Context context; - private List pages; - private EmojiSelectionListener listener; - - private EmojiPagerAdapter(@NonNull Context context, - @NonNull List pages, - @Nullable EmojiSelectionListener listener) { - super(); - this.context = context; - this.pages = pages; - this.listener = listener; - } - - @Override - public int getCount() { - return pages.size(); - } - - @NonNull - @Override - public Object instantiateItem(@NonNull ViewGroup container, - int position) { - EmojiPageView page = new EmojiPageView(context); - page.setModel(pages.get(position)); - page.setEmojiSelectedListener(listener); - container.addView(page); - return page; - } - - @Override - public void destroyItem(@NonNull ViewGroup container, int position, - @NonNull Object object) { - container.removeView((View) object); - } - - @Override - public boolean isViewFromObject(@NonNull View view, - @NonNull Object object) { - return view == object; - } - - @Override - public View getCustomTabView(ViewGroup viewGroup, int i) { - ImageView image = new AppCompatImageView(context); - image.setScaleType(CENTER_INSIDE); - image.setImageResource(pages.get(i).getIcon()); - setImageTintList(image, ColorStateList.valueOf( - ContextCompat.getColor(context, R.color.color_primary))); - return image; - } - - @Override - public void tabSelected(View view) { - view.animate().setDuration(300).alpha(1); - } - - @Override - public void tabUnselected(View view) { - view.animate().setDuration(400).alpha(0.4f); - } - } - - public interface EmojiEventListener extends EmojiSelectionListener { - void onKeyEvent(KeyEvent keyEvent); - } - - public interface EmojiDrawerListener { - void onShown(); - - void onHidden(); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java deleted file mode 100644 index 6e325a9ad..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiEditText.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.UiThread; -import android.support.v7.widget.AppCompatEditText; -import android.text.InputFilter; -import android.util.AttributeSet; - -import org.briarproject.briar.R; -import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable; - -import javax.annotation.Nullable; - -@UiThread -public class EmojiEditText extends AppCompatEditText { - - public EmojiEditText(Context context) { - this(context, null); - } - - public EmojiEditText(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, R.attr.editTextStyle); - } - - public EmojiEditText(Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - // this ensures the view is redrawn when invalidated - setLayerType(LAYER_TYPE_SOFTWARE, null); - setFilters(new InputFilter[] {new EmojiFilter(this)}); - } - - public void insertEmoji(String emoji) { - int start = getSelectionStart(); - int end = getSelectionEnd(); - - getText().replace(Math.min(start, end), Math.max(start, end), emoji); - setSelection(start + emoji.length()); - } - - @Override - public void invalidateDrawable(@NonNull Drawable drawable) { - if (drawable instanceof EmojiDrawable) invalidate(); - else super.invalidateDrawable(drawable); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java deleted file mode 100644 index 3afc44c2f..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.support.annotation.UiThread; -import android.text.InputFilter; -import android.text.Spannable; -import android.text.Spanned; -import android.text.TextUtils; -import android.widget.TextView; - -import javax.annotation.Nullable; - -@UiThread -class EmojiFilter implements InputFilter { - - private final TextView view; - - EmojiFilter(TextView view) { - this.view = view; - } - - @Nullable - @Override - public CharSequence filter(CharSequence source, int start, int end, - Spanned dest, int dstart, int dend) { - - char[] v = new char[end - start]; - TextUtils.getChars(source, start, end, v, 0); - Spannable emojified = EmojiProvider.getInstance(view.getContext()) - .emojify(new String(v), view); - if (source instanceof Spanned && emojified != null) { - TextUtils.copySpansFrom((Spanned) source, start, end, null, - emojified, 0); - } - return emojified; - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java deleted file mode 100644 index eeaf12409..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageModel.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; - -import javax.annotation.Nullable; - -interface EmojiPageModel { - - @DrawableRes - int getIcon(); - - @NonNull - String[] getEmoji(); - - boolean hasSpriteMap(); - - @Nullable - String getSprite(); -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java deleted file mode 100644 index 91598c381..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPageView.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.support.annotation.UiThread; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; -import android.widget.GridView; - -import org.briarproject.briar.R; - -import javax.annotation.Nullable; - -@UiThread -public class EmojiPageView extends FrameLayout { - - private final GridView grid; - - private EmojiSelectionListener listener; - - public EmojiPageView(Context context) { - this(context, null); - } - - public EmojiPageView(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public EmojiPageView(Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - View view = LayoutInflater.from(getContext()) - .inflate(R.layout.emoji_grid_layout, this, true); - grid = view.findViewById(R.id.emoji); - grid.setColumnWidth(getResources() - .getDimensionPixelSize(R.dimen.emoji_drawer_size) + 2 * - getResources().getDimensionPixelSize( - R.dimen.emoji_drawer_item_padding)); - grid.setOnItemClickListener((parent, view1, position, id) -> { - if (listener != null) - listener.onEmojiSelected(((EmojiView) view1).getEmoji()); - }); - } - - public void setModel(EmojiPageModel model) { - grid.setAdapter(new EmojiGridAdapter(getContext(), model)); - } - - public void setEmojiSelectedListener(EmojiSelectionListener listener) { - this.listener = listener; - } - - private static class EmojiGridAdapter extends BaseAdapter { - - private final Context context; - private final EmojiPageModel model; - private final int emojiSize; - - private EmojiGridAdapter(Context context, EmojiPageModel model) { - this.context = context; - this.model = model; - emojiSize = (int) context.getResources() - .getDimension(R.dimen.emoji_drawer_size); - } - - @Override - public int getCount() { - return model.getEmoji().length; - } - - @Nullable - @Override - public Object getItem(int position) { - return null; - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - EmojiView view; - int pad = context.getResources() - .getDimensionPixelSize(R.dimen.emoji_drawer_item_padding); - if (convertView != null && convertView instanceof EmojiView) { - view = (EmojiView) convertView; - } else { - EmojiView emojiView = new EmojiView(context); - emojiView.setPadding(pad, pad, pad, pad); - emojiView.setLayoutParams( - new AbsListView.LayoutParams(emojiSize + 2 * pad, - emojiSize + 2 * pad)); - view = emojiView; - } - String emoji = model.getEmoji()[position]; - view.setEmoji(emoji); - - return view; - } - } - - interface EmojiSelectionListener { - void onEmojiSelected(String emoji); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPages.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPages.java deleted file mode 100644 index 6d77f74b9..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiPages.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; - -import org.briarproject.briar.R; - -import java.util.Arrays; -import java.util.List; - -class EmojiPages { - - static List getPages(Context ctx) { - return Arrays.asList( - new StaticEmojiPageModel(ctx, R.drawable.ic_emoji_smiley_people, - R.array.emoji_smiley_people, - "emoji_smiley_people.png"), - new StaticEmojiPageModel(ctx, - R.drawable.ic_emoji_animals_nature, - R.array.emoji_animals_nature, - "emoji_animals_nature.png"), - new StaticEmojiPageModel(ctx, R.drawable.ic_emoji_food_drink, - R.array.emoji_food_drink, - "emoji_food_drink.png"), - new StaticEmojiPageModel(ctx, R.drawable.ic_emoji_travel_places, - R.array.emoji_travel_places, - "emoji_travel_places.png"), - new StaticEmojiPageModel(ctx, R.drawable.ic_emoji_activity, - R.array.emoji_activity, - "emoji_activity.png"), - new StaticEmojiPageModel(ctx, R.drawable.ic_emoji_objects, - R.array.emoji_objects, - "emoji_objects.png"), - new StaticEmojiPageModel(ctx, R.drawable.ic_emoji_symbols, - R.array.emoji_symbols, - "emoji_symbols.png"), - new StaticEmojiPageModel(ctx, R.drawable.ic_emoji_flags, - R.array.emoji_flags, - "emoji_flags.png"), - - new StaticEmojiPageModel(R.drawable.ic_emoji_emoticons, - new String[] { - ":-)", ";-)", "(-:", ":->", ":-D", "\\o/", - ":-P", "B-)", ":-$", ":-*", "O:-)", "=-O", - "O_O", "O_o", "o_O", ":O", ":-!", ":-x", - ":-|", ":-\\", ":-(", ":'(", ":-[", ">:-(", - "^.^", "^_^", "\\(\u02c6\u02da\u02c6)/", - "\u30fd(\u00b0\u25c7\u00b0 )\u30ce", - "\u00af\\(\u00b0_o)/\u00af", - "\u00af\\_(\u30c4)_/\u00af", "(\u00ac_\u00ac)", - "(>_<)", "(\u2565\ufe4f\u2565)", - "(\u261e\uff9f\u30ee\uff9f)\u261e", - "\u261c(\uff9f\u30ee\uff9f\u261c)", - "\u261c(\u2312\u25bd\u2312)\u261e", - "(\u256f\u00b0\u25a1\u00b0)\u256f\ufe35", - "\u253b\u2501\u253b", - "\u252c\u2500\u252c", - "\u30ce(\u00b0\u2013\u00b0\u30ce)", - "(^._.^)\uff89", - "\u0e05^\u2022\ufecc\u2022^\u0e05", - "(\u2022_\u2022)", - " \u25a0-\u25a0\u00ac <(\u2022_\u2022) ", - "(\u25a0_\u25a0\u00ac)" - }, null)); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java deleted file mode 100644 index 90afbdeca..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java +++ /dev/null @@ -1,306 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.support.annotation.UiThread; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.util.SparseArray; -import android.widget.TextView; - -import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; -import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; -import org.briarproject.bramble.api.system.AndroidExecutor; -import org.briarproject.briar.R; -import org.briarproject.briar.android.BriarApplication; -import org.thoughtcrime.securesms.components.util.FutureTaskListener; -import org.thoughtcrime.securesms.components.util.ListenableFutureTask; -import org.thoughtcrime.securesms.util.BitmapDecodingException; -import org.thoughtcrime.securesms.util.BitmapUtil; - -import java.io.IOException; -import java.lang.ref.SoftReference; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.annotation.Nullable; -import javax.inject.Inject; - -import static android.graphics.Paint.ANTI_ALIAS_FLAG; -import static android.graphics.Paint.FILTER_BITMAP_FLAG; -import static android.graphics.PixelFormat.TRANSLUCENT; -import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static org.briarproject.bramble.util.LogUtils.logException; - -@MethodsNotNullByDefault -@ParametersNotNullByDefault -public class EmojiProvider { - - private static volatile EmojiProvider INSTANCE = null; - - private static final Paint PAINT = - new Paint(FILTER_BITMAP_FLAG | ANTI_ALIAS_FLAG); - - @Inject - AndroidExecutor androidExecutor; - - private static final Logger LOG = - Logger.getLogger(EmojiProvider.class.getName()); - - private final SparseArray offsets = new SparseArray<>(); - - private static final Pattern EMOJI_RANGE = Pattern.compile( - // 0x203c,0x2049 0x20a0-0x32ff 0x1f00-0x1fff 0xfe4e5-0xfe4ee - // |=== !!, ?! ===||==== misc ===||========= emoticons =======||========== flags ==========| - "[\\u203c\\u2049\\u20a0-\\u32ff\\ud83c\\udc00-\\ud83f\\udfff\\udbb9\\udce5-\\udbb9\\udcee]"); - - private static final int EMOJI_RAW_HEIGHT = 64; - private static final int EMOJI_RAW_WIDTH = 64; - private static final int EMOJI_VERT_PAD = 0; - private static final int EMOJI_PER_ROW = 32; - - private final Context context; - private final float decodeScale; - private final List staticPages; - - static EmojiProvider getInstance(Context context) { - if (INSTANCE == null) { - synchronized (EmojiProvider.class) { - if (INSTANCE == null) { - LOG.info("Creating new instance of EmojiProvider"); - INSTANCE = new EmojiProvider(context); - BriarApplication app = - (BriarApplication) context.getApplicationContext(); - app.getApplicationComponent().inject(INSTANCE); - } - } - } - return INSTANCE; - } - - private EmojiProvider(Context context) { - this.context = context.getApplicationContext(); - float drawerSize = - context.getResources().getDimension(R.dimen.emoji_drawer_size); - decodeScale = Math.min(1f, drawerSize / EMOJI_RAW_HEIGHT); - staticPages = EmojiPages.getPages(context); - for (EmojiPageModel page : staticPages) { - if (page.hasSpriteMap()) { - EmojiPageBitmap pageBitmap = new EmojiPageBitmap(page); - for (int i = 0; i < page.getEmoji().length; i++) { - offsets.put(Character.codePointAt(page.getEmoji()[i], 0), - new DrawInfo(pageBitmap, i)); - } - } - } - } - - @Nullable - @UiThread - Spannable emojify(@Nullable CharSequence text, TextView tv) { - if (text == null) return null; - Matcher matches = EMOJI_RANGE.matcher(text); - SpannableStringBuilder builder = new SpannableStringBuilder(text); - - while (matches.find()) { - int codePoint = matches.group().codePointAt(0); - Drawable drawable = getEmojiDrawable(codePoint); - if (drawable != null) { - builder.setSpan(new EmojiSpan(drawable, tv), matches.start(), - matches.end(), SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - return builder; - } - - @Nullable - @UiThread - Drawable getEmojiDrawable(int emojiCode) { - return getEmojiDrawable(offsets.get(emojiCode)); - } - - @Nullable - private Drawable getEmojiDrawable(@Nullable DrawInfo drawInfo) { - if (drawInfo == null) { - return null; - } - - EmojiDrawable drawable = new EmojiDrawable(drawInfo, decodeScale); - drawInfo.page.get().addListener(new FutureTaskListener() { - @Override - public void onSuccess(Bitmap result) { - androidExecutor.runOnUiThread(() -> drawable.setBitmap(result)); - } - - @Override - public void onFailure(Throwable error) { - logException(LOG, WARNING, error); - } - }); - return drawable; - } - - List getStaticPages() { - return staticPages; - } - - - static class EmojiDrawable extends Drawable { - - private final DrawInfo info; - private final float intrinsicWidth, intrinsicHeight, verticalPad; - - private Bitmap bmp; - - private EmojiDrawable(DrawInfo info, float decodeScale) { - this.info = info; - intrinsicWidth = EMOJI_RAW_WIDTH * decodeScale; - intrinsicHeight = EMOJI_RAW_HEIGHT * decodeScale; - verticalPad = EMOJI_VERT_PAD * decodeScale; - } - - @Override - public int getIntrinsicWidth() { - return (int) intrinsicWidth; - } - - @Override - public int getIntrinsicHeight() { - return (int) intrinsicHeight; - } - - @Override - public void draw(Canvas canvas) { - if (bmp == null) { - return; - } - - int row = info.index / EMOJI_PER_ROW; - int rowIndex = info.index % EMOJI_PER_ROW; - - int left = (int) (rowIndex * intrinsicWidth); - int top = (int) (row * intrinsicHeight + row * verticalPad); - int right = (int) ((rowIndex + 1) * intrinsicWidth); - int bottom = - (int) ((row + 1) * intrinsicHeight + row * verticalPad); - canvas.drawBitmap(bmp, new Rect(left, top, right, bottom), - getBounds(), PAINT); - } - - void setBitmap(Bitmap bitmap) { - if (bmp == null || !bmp.sameAs(bitmap)) { - bmp = bitmap; - invalidateSelf(); - } - } - - @Override - public int getOpacity() { - return TRANSLUCENT; - } - - @Override - public void setAlpha(int alpha) { - } - - @Override - public void setColorFilter(@Nullable ColorFilter cf) { - } - } - - - private static class DrawInfo { - - private final EmojiPageBitmap page; - private final int index; - - private DrawInfo(EmojiPageBitmap page, int index) { - this.page = page; - this.index = index; - } - - @Override - public String toString() { - return "DrawInfo{ " + "page = " + page + ", index = " + index + '}'; - } - } - - private class EmojiPageBitmap { - - private final EmojiPageModel model; - - private ListenableFutureTask task; - - private volatile SoftReference bitmapReference; - - private EmojiPageBitmap(EmojiPageModel model) { - this.model = model; - } - - @UiThread - private ListenableFutureTask get() { - if (bitmapReference != null) { - Bitmap bitmap = bitmapReference.get(); - if (bitmap != null) return new ListenableFutureTask<>(bitmap); - } - if (task != null) return task; - Callable callable = () -> { - if (LOG.isLoggable(INFO)) - LOG.info("Loading page " + model.getSprite()); - return loadPage(); - }; - task = new ListenableFutureTask<>(callable); - new AsyncTask() { - @Override - protected Void doInBackground(Void... params) { - task.run(); - return null; - } - - @Override - protected void onPostExecute(Void aVoid) { - task = null; - } - }.execute(); - return task; - } - - private Bitmap loadPage() throws IOException { - if (bitmapReference != null) { - Bitmap bitmap = bitmapReference.get(); - if (bitmap != null) return bitmap; - } - - try { - Bitmap bitmap = BitmapUtil.createScaledBitmap(context, - "file:///android_asset/" + model.getSprite(), - decodeScale); - bitmapReference = new SoftReference<>(bitmap); - if (LOG.isLoggable(INFO)) - LOG.info("Loaded page " + model.getSprite()); - return bitmap; - } catch (BitmapDecodingException e) { - logException(LOG, WARNING, e); - throw new IOException(e); - } - } - - @Nullable - @Override - public String toString() { - return model.getSprite(); - } - } - -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java deleted file mode 100644 index 7cab093d8..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiSpan.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.graphics.Paint; -import android.graphics.Paint.FontMetricsInt; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.UiThread; -import android.widget.TextView; - -import org.briarproject.briar.R; - -@UiThread -class EmojiSpan extends AnimatingImageSpan { - - private final int size; - private final FontMetricsInt fm; - - EmojiSpan(@NonNull Drawable drawable, @NonNull TextView tv) { - super(drawable, tv); - fm = tv.getPaint().getFontMetricsInt(); - size = fm != null ? Math.abs(fm.descent) + Math.abs(fm.ascent) - : tv.getResources().getDimensionPixelSize( - R.dimen.conversation_item_body_text_size); - getDrawable().setBounds(0, 0, size, size); - } - - @Override - public int getSize(Paint paint, CharSequence text, int start, int end, - FontMetricsInt fm) { - if (fm != null && this.fm != null) { - fm.ascent = this.fm.ascent; - fm.descent = this.fm.descent; - fm.top = this.fm.top; - fm.bottom = this.fm.bottom; - return size; - } else { - return super.getSize(paint, text, start, end, fm); - } - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java deleted file mode 100644 index 76458decf..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiTextView.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.UiThread; -import android.support.v7.widget.AppCompatTextView; -import android.util.AttributeSet; -import android.view.ViewConfiguration; - -import org.thoughtcrime.securesms.components.emoji.EmojiProvider.EmojiDrawable; - -import javax.annotation.Nullable; - -import static android.widget.TextView.BufferType.SPANNABLE; - -@UiThread -public class EmojiTextView extends AppCompatTextView { - - public EmojiTextView(Context context) { - this(context, null); - } - - public EmojiTextView(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public EmojiTextView(Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - // this ensures the view is redrawn when invalidated - setLayerType(LAYER_TYPE_SOFTWARE, null); - } - - @Override - public void setText(@Nullable CharSequence text, BufferType type) { - CharSequence source = - EmojiProvider.getInstance(getContext()).emojify(text, this); - super.setText(source, SPANNABLE); - } - - @Override - public void invalidateDrawable(@NonNull Drawable drawable) { - if (drawable instanceof EmojiDrawable) invalidate(); - else super.invalidateDrawable(drawable); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, - int bottom) { - // disable software layer if cache size is too small for it - int drawingCacheSize = ViewConfiguration.get(getContext()) - .getScaledMaximumDrawingCacheSize(); - int width = right - left; - int height = bottom - top; - int size = width * height * 4; - if (size > drawingCacheSize) { - setLayerType(LAYER_TYPE_NONE, null); - } - super.onLayout(changed, left, top, right, bottom); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java deleted file mode 100644 index 5858af0a7..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.support.annotation.UiThread; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.AppCompatImageButton; -import android.util.AttributeSet; - -import org.briarproject.briar.R; -import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiDrawerListener; - -import javax.annotation.Nullable; - -@UiThread -public class EmojiToggle extends AppCompatImageButton - implements EmojiDrawerListener { - - private final Drawable emojiToggle; - private final Drawable imeToggle; - - public EmojiToggle(Context context) { - this(context, null); - } - - public EmojiToggle(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public EmojiToggle(Context context, @Nullable AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); - - emojiToggle = ContextCompat - .getDrawable(getContext(), R.drawable.ic_emoji_toggle); - imeToggle = ContextCompat - .getDrawable(getContext(), R.drawable.ic_keyboard); - setToEmoji(); - } - - public void setToEmoji() { - setImageDrawable(emojiToggle); - } - - public void setToIme() { - setImageDrawable(imeToggle); - } - - public void attach(EmojiDrawer drawer) { - drawer.setDrawerListener(this); - } - - @Override - public void onShown() { - setToIme(); - } - - @Override - public void onHidden() { - setToEmoji(); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiView.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiView.java deleted file mode 100644 index 2b6d61039..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiView.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.UiThread; -import android.util.AttributeSet; -import android.view.View; - -import javax.annotation.Nullable; - -import static android.graphics.Paint.ANTI_ALIAS_FLAG; -import static android.graphics.Paint.Align.CENTER; -import static android.graphics.Paint.FILTER_BITMAP_FLAG; -import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute; - -@UiThread -public class EmojiView extends View implements Drawable.Callback { - - private final Paint paint = new Paint(ANTI_ALIAS_FLAG | FILTER_BITMAP_FLAG); - - private String emoji; - private Drawable drawable; - - public EmojiView(Context context) { - this(context, null); - } - - public EmojiView(Context context, @Nullable AttributeSet attrs) { - this(context, attrs, 0); - } - - public EmojiView(Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public void setEmoji(String emoji) { - this.emoji = emoji; - this.drawable = EmojiProvider.getInstance(getContext()) - .getEmojiDrawable(Character.codePointAt(emoji, 0)); - postInvalidate(); - } - - public String getEmoji() { - return emoji; - } - - @Override - protected void onDraw(Canvas canvas) { - if (drawable != null) { - drawable.setBounds(getPaddingLeft(), - getPaddingTop(), - getWidth() - getPaddingRight(), - getHeight() - getPaddingBottom()); - drawable.setCallback(this); - drawable.draw(canvas); - } else { - float targetFontSize = - 0.75f * getHeight() - getPaddingTop() - getPaddingBottom(); - paint.setTextSize(targetFontSize); - int color = resolveColorAttribute(getContext(), - android.R.attr.textColorPrimary); - paint.setColor(color); - paint.setTextAlign(CENTER); - int xPos = (canvas.getWidth() / 2); - int yPos = (int) ((canvas.getHeight() / 2) - - ((paint.descent() + paint.ascent()) / 2)); - - float overflow = paint.measureText(emoji) / - (getWidth() - getPaddingLeft() - getPaddingRight()); - if (overflow > 1f) { - paint.setTextSize(targetFontSize / overflow); - yPos = (int) ((canvas.getHeight() / 2) - - ((paint.descent() + paint.ascent()) / 2)); - } - canvas.drawText(emoji, xPos, yPos, paint); - } - } - - @Override - public void invalidateDrawable(@NonNull Drawable drawable) { - super.invalidateDrawable(drawable); - postInvalidate(); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java deleted file mode 100644 index f47ce308f..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/RecentEmojiPageModel.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.support.annotation.DrawableRes; - -import org.briarproject.bramble.api.db.DatabaseExecutor; -import org.briarproject.bramble.api.db.DbException; -import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; -import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; -import org.briarproject.bramble.api.settings.Settings; -import org.briarproject.bramble.api.settings.SettingsManager; -import org.briarproject.bramble.util.StringUtils; -import org.briarproject.briar.R; -import org.briarproject.briar.android.BriarApplication; - -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.concurrent.Executor; -import java.util.logging.Logger; - -import javax.annotation.Nullable; -import javax.inject.Inject; - -import static java.util.logging.Level.WARNING; -import static org.briarproject.bramble.util.LogUtils.logException; -import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE; - -@MethodsNotNullByDefault -@ParametersNotNullByDefault -public class RecentEmojiPageModel implements EmojiPageModel { - - private static final Logger LOG = - Logger.getLogger(RecentEmojiPageModel.class.getName()); - - private static final String EMOJI_LRU_PREFERENCE = "pref_emoji_recent2"; - private static final int EMOJI_LRU_SIZE = 50; - - private final LinkedHashSet recentlyUsed; // UI thread - - @Inject - SettingsManager settingsManager; - - @Inject - @DatabaseExecutor - Executor dbExecutor; - - RecentEmojiPageModel(Context context) { - BriarApplication app = - (BriarApplication) context.getApplicationContext(); - app.getApplicationComponent().inject(this); - recentlyUsed = getPersistedCache(); - } - - private LinkedHashSet getPersistedCache() { - String serialized; - try { - // FIXME: Don't make DB calls on the UI thread - Settings settings = settingsManager.getSettings(SETTINGS_NAMESPACE); - serialized = settings.get(EMOJI_LRU_PREFERENCE); - } catch (DbException e) { - logException(LOG, WARNING, e); - serialized = null; - } - return deserialize(serialized); - } - - @DrawableRes - @Override - public int getIcon() { - return R.drawable.ic_emoji_recent; - } - - @Override - public String[] getEmoji() { - return toReversePrimitiveArray(recentlyUsed); - } - - @Override - public boolean hasSpriteMap() { - return false; - } - - @Override - public String getSprite() { - return null; - } - - void onCodePointSelected(String emoji) { - recentlyUsed.remove(emoji); - recentlyUsed.add(emoji); - - if (recentlyUsed.size() > EMOJI_LRU_SIZE) { - Iterator iterator = recentlyUsed.iterator(); - iterator.next(); - iterator.remove(); - } - save(serialize(recentlyUsed)); - } - - private String serialize(LinkedHashSet emojis) { - return StringUtils.join(emojis, "\t"); - } - - private LinkedHashSet deserialize(@Nullable String serialized) { - if (serialized == null) return new LinkedHashSet<>(); - String[] list = serialized.split("\t"); - LinkedHashSet result = new LinkedHashSet<>(list.length); - Collections.addAll(result, list); - return result; - } - - private void save(String serialized) { - dbExecutor.execute(() -> { - Settings settings = new Settings(); - settings.put(EMOJI_LRU_PREFERENCE, serialized); - try { - settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE); - } catch (DbException e) { - logException(LOG, WARNING, e); - } - }); - } - - private String[] toReversePrimitiveArray(LinkedHashSet emojiSet) { - String[] emojis = new String[emojiSet.size()]; - int i = emojiSet.size() - 1; - for (String emoji : emojiSet) { - emojis[i--] = emoji; - } - return emojis; - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java b/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java deleted file mode 100644 index 4f9c9b94c..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/components/emoji/StaticEmojiPageModel.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.thoughtcrime.securesms.components.emoji; - -import android.content.Context; -import android.support.annotation.ArrayRes; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.UiThread; - -import javax.annotation.Nullable; - -@UiThread -class StaticEmojiPageModel implements EmojiPageModel { - - @DrawableRes - private final int icon; - @NonNull - private final String[] emoji; - @Nullable - private final String sprite; - - StaticEmojiPageModel(@DrawableRes int icon, @NonNull String[] emoji, - @Nullable String sprite) { - this.icon = icon; - this.emoji = emoji; - this.sprite = sprite; - } - - StaticEmojiPageModel(Context ctx, @DrawableRes int icon, - @ArrayRes int res, @Nullable String sprite) { - this(icon, getEmoji(ctx, res), sprite); - } - - @DrawableRes - @Override - public int getIcon() { - return icon; - } - - @Override - @NonNull - public String[] getEmoji() { - return emoji; - } - - @Override - public boolean hasSpriteMap() { - return sprite != null; - } - - @Nullable - @Override - public String getSprite() { - return sprite; - } - - @NonNull - private static String[] getEmoji(Context ctx, @ArrayRes int res) { - String[] rawStrings = ctx.getResources().getStringArray(res); - String[] emoji = new String[rawStrings.length]; - int i = 0; - for (String codePoint : rawStrings) { - String[] bytes = codePoint.split(","); - int[] codePoints = new int[bytes.length]; - int j = 0; - for (String b : bytes) { - codePoints[j] = Integer.valueOf(b, 16); - } - emoji[i] = new String(codePoints, 0, codePoints.length); - i++; - } - return emoji; - } - -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapDecodingException.java b/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapDecodingException.java deleted file mode 100644 index 777fdfb2e..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapDecodingException.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.thoughtcrime.securesms.util; - -public class BitmapDecodingException extends Exception { - - BitmapDecodingException(String s) { - super(s); - } - - BitmapDecodingException(Exception nested) { - super(nested); - } -} diff --git a/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java b/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java deleted file mode 100644 index 32d924d7b..000000000 --- a/briar-android/src/main/java/org/thoughtcrime/securesms/util/BitmapUtil.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.thoughtcrime.securesms.util; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.util.Pair; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.Priority; -import com.bumptech.glide.load.DecodeFormat; -import com.bumptech.glide.load.engine.Resource; -import com.bumptech.glide.load.resource.bitmap.BitmapResource; -import com.bumptech.glide.load.resource.bitmap.Downsampler; -import com.bumptech.glide.load.resource.bitmap.FitCenter; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.logging.Logger; - -import static java.util.logging.Level.WARNING; -import static org.briarproject.bramble.util.LogUtils.logException; - -public class BitmapUtil { - - private static final Logger LOG = - Logger.getLogger(BitmapUtil.class.getName()); - - private static InputStream getInputStreamForModel(Context context, - T model) - throws BitmapDecodingException { - try { - return Glide.buildStreamModelLoader(model, context) - .getResourceFetcher(model, -1, -1) - .loadData(Priority.NORMAL); - } catch (Exception e) { - throw new BitmapDecodingException(e); - } - } - - private static Bitmap createScaledBitmapInto(Context context, T model, - int width, int height) - throws BitmapDecodingException { - Bitmap rough = Downsampler.AT_LEAST - .decode(getInputStreamForModel(context, model), - Glide.get(context).getBitmapPool(), - width, height, DecodeFormat.PREFER_RGB_565); - - Resource resource = BitmapResource - .obtain(rough, Glide.get(context).getBitmapPool()); - Resource result = - new FitCenter(context).transform(resource, width, height); - - if (result == null) { - throw new BitmapDecodingException("unable to transform Bitmap"); - } - return result.get(); - } - - public static Bitmap createScaledBitmap(Context context, T model, - float scale) throws BitmapDecodingException { - Pair dimens = - getDimensions(getInputStreamForModel(context, model)); - return createScaledBitmapInto(context, model, - (int) (dimens.first * scale), (int) (dimens.second * scale)); - } - - private static BitmapFactory.Options getImageDimensions( - InputStream inputStream) - throws BitmapDecodingException { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BufferedInputStream fis = new BufferedInputStream(inputStream); - BitmapFactory.decodeStream(fis, null, options); - try { - fis.close(); - } catch (IOException e) { - logException(LOG, WARNING, e); - } - - if (options.outWidth == -1 || options.outHeight == -1) { - throw new BitmapDecodingException( - "Failed to decode image dimensions: " + options.outWidth + - ", " + options.outHeight); - } - - return options; - } - - private static Pair getDimensions(InputStream inputStream) - throws BitmapDecodingException { - BitmapFactory.Options options = getImageDimensions(inputStream); - return new Pair<>(options.outWidth, options.outHeight); - } - -} diff --git a/briar-android/src/main/res/drawable/ic_emoji_activity.xml b/briar-android/src/main/res/drawable/ic_emoji_activity.xml deleted file mode 100644 index 3b74969d3..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_activity.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/briar-android/src/main/res/drawable/ic_emoji_animals_nature.xml b/briar-android/src/main/res/drawable/ic_emoji_animals_nature.xml deleted file mode 100644 index 29b9c0c45..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_animals_nature.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/briar-android/src/main/res/drawable/ic_emoji_emoticons.xml b/briar-android/src/main/res/drawable/ic_emoji_emoticons.xml deleted file mode 100644 index 262be839f..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_emoticons.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - \ No newline at end of file diff --git a/briar-android/src/main/res/drawable/ic_emoji_flags.xml b/briar-android/src/main/res/drawable/ic_emoji_flags.xml deleted file mode 100644 index c4b56853f..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_flags.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/briar-android/src/main/res/drawable/ic_emoji_food_drink.xml b/briar-android/src/main/res/drawable/ic_emoji_food_drink.xml deleted file mode 100644 index 625a7c12b..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_food_drink.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/briar-android/src/main/res/drawable/ic_emoji_objects.xml b/briar-android/src/main/res/drawable/ic_emoji_objects.xml deleted file mode 100644 index 7b15232cf..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_objects.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/briar-android/src/main/res/drawable/ic_emoji_recent.xml b/briar-android/src/main/res/drawable/ic_emoji_recent.xml deleted file mode 100644 index fc0081fc7..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_recent.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/briar-android/src/main/res/drawable/ic_emoji_smiley_people.xml b/briar-android/src/main/res/drawable/ic_emoji_smiley_people.xml deleted file mode 100644 index 8af140980..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_smiley_people.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/briar-android/src/main/res/drawable/ic_emoji_symbols.xml b/briar-android/src/main/res/drawable/ic_emoji_symbols.xml deleted file mode 100644 index 524912968..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_symbols.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/briar-android/src/main/res/drawable/ic_emoji_travel_places.xml b/briar-android/src/main/res/drawable/ic_emoji_travel_places.xml deleted file mode 100644 index c52b6076f..000000000 --- a/briar-android/src/main/res/drawable/ic_emoji_travel_places.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/briar-android/src/main/res/layout/activity_conversation.xml b/briar-android/src/main/res/layout/activity_conversation.xml index 6208ec5fd..229c1d13e 100644 --- a/briar-android/src/main/res/layout/activity_conversation.xml +++ b/briar-android/src/main/res/layout/activity_conversation.xml @@ -24,7 +24,7 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/briar-android/src/main/res/layout/emoji_grid_layout.xml b/briar-android/src/main/res/layout/emoji_grid_layout.xml deleted file mode 100644 index c1486e2dc..000000000 --- a/briar-android/src/main/res/layout/emoji_grid_layout.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/briar-android/src/main/res/layout/introduction_message.xml b/briar-android/src/main/res/layout/introduction_message.xml index 9fe6196d5..303352afa 100644 --- a/briar-android/src/main/res/layout/introduction_message.xml +++ b/briar-android/src/main/res/layout/introduction_message.xml @@ -36,7 +36,7 @@ android:layout_marginStart="@dimen/listitem_horizontal_margin" tools:src="@mipmap/ic_launcher_round"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/briar-android/src/main/res/layout/text_input_view_large.xml b/briar-android/src/main/res/layout/text_input_view_large.xml index a4a9d7b02..b5ced660d 100644 --- a/briar-android/src/main/res/layout/text_input_view_large.xml +++ b/briar-android/src/main/res/layout/text_input_view_large.xml @@ -27,17 +27,18 @@ android:layout_height="match_parent" android:orientation="horizontal"> - - - - diff --git a/briar-android/src/main/res/values/emoji.xml b/briar-android/src/main/res/values/emoji.xml deleted file mode 100644 index ab8e62d01..000000000 --- a/briar-android/src/main/res/values/emoji.xml +++ /dev/null @@ -1,1352 +0,0 @@ - - - - - - 1f3c1 - 1f3f3 - 1f3f4 - 1f6a9 - 1f3e7 - 1f6ae - 1f6b0 - 267f - 1f6b9 - 1f6ba - 1f6bb - 1f6bc - 1f6be - 1f6c2 - 1f6c3 - 1f6c4 - 1f6c5 - 26a0 - 1f6b8 - 26d4 - 1f6ab - 1f6b3 - 1f6ad - 1f6af - 1f6b1 - 1f6b7 - 2622 - 2623 - 2b06 - 2197 - 27a1 - 2198 - 2b07 - 2199 - 2b05 - 2196 - 2195 - 2194 - 21a9 - 21aa - 2934 - 2935 - 1f503 - 1f504 - 1f519 - 1f51a - 1f51b - 1f51c - 1f51d - 1f6d0 - 269b - 1f549 - 2721 - 2638 - 262f - 271d - 2626 - 262a - 262e - 1f54e - 1f52f - 267b - 1f4db - 269c - 1f530 - 1f531 - 2b55 - 2705 - 2611 - 2714 - 2716 - 274c - 274e - 2795 - 2796 - 2797 - 27b0 - 27bf - 303d - 2733 - 2734 - 2747 - 1f4b1 - 1f4b2 - 203c - 2049 - 2753 - 2754 - 2755 - 2757 - 3030 - a9 - ae - 2122 - 2648 - 2649 - 264a - 264b - 264c - 264d - 264e - 264f - 2650 - 2651 - 2652 - 2653 - 26ce - 1f500 - 1f501 - 1f502 - 25b6 - 23e9 - 23ed - 23ef - 25c0 - 23ea - 23ee - 1f53c - 23eb - 1f53d - 23ec - 23f8 - 23f9 - 23fa - 23cf - 1f3a6 - 1f505 - 1f506 - 1f4f6 - 1f4f5 - 1f4f3 - 1f4f4 - 23,20e3 - 2a,20e3 - 30,20e3 - 31,20e3 - 32,20e3 - 33,20e3 - 34,20e3 - 35,20e3 - 36,20e3 - 37,20e3 - 38,20e3 - 39,20e3 - 1f51f - 1f4af - 1f51e - 1f520 - 1f521 - 1f522 - 1f523 - 1f524 - 1f170 - 1f18e - 1f171 - 1f191 - 1f192 - 1f193 - 2139 - 1f194 - 24c2 - 1f195 - 1f196 - 1f17e - 1f197 - 1f17f - 1f198 - 1f199 - 1f19a - 1f201 - 1f202 - 1f237 - 1f236 - 1f22f - 1f250 - 1f239 - 1f21a - 1f232 - 1f251 - 1f238 - 1f234 - 1f233 - 3297 - 3299 - 1f23a - 1f235 - 25aa - 25ab - 25fb - 25fc - 25fd - 25fe - 2b1b - 2b1c - 1f536 - 1f537 - 1f538 - 1f539 - 1f53a - 1f53b - 1f4a0 - 1f518 - 1f532 - 1f533 - 26aa - 26ab - 1f534 - 1f535 - - - 1f435 - 1f412 - 1f436 - 1f415 - 1f429 - 1f43a - 1f431 - 1f408 - 1f981 - 1f42f - 1f405 - 1f406 - 1f434 - 1f40e - 1f984 - 1f42e - 1f402 - 1f403 - 1f404 - 1f437 - 1f416 - 1f417 - 1f43d - 1f40f - 1f411 - 1f410 - 1f42a - 1f42b - 1f418 - 1f42d - 1f401 - 1f400 - 1f439 - 1f430 - 1f407 - 1f43f - 1f43b - 1f428 - 1f43c - 1f43e - 1f983 - 1f414 - 1f413 - 1f423 - 1f424 - 1f425 - 1f426 - 1f427 - 1f54a - 1f438 - 1f40a - 1f422 - 1f40d - 1f432 - 1f409 - 1f433 - 1f40b - 1f42c - 1f41f - 1f420 - 1f421 - 1f419 - 1f41a - 1f980 - 1f40c - 1f41b - 1f41c - 1f41d - 1f41e - 1f577 - 1f578 - 1f982 - 1f490 - 1f338 - 1f4ae - 1f3f5 - 1f339 - 1f33a - 1f33b - 1f33c - 1f337 - 2618 - 1f331 - 1f332 - 1f333 - 1f334 - 1f335 - 1f33e - 1f33f - 1f340 - 1f341 - 1f342 - 1f343 - - - 1f600 - 1f601 - 1f602 - 1f603 - 1f604 - 1f605 - 1f606 - 1f609 - 1f60a - 1f60b - 1f60e - 1f60d - 1f618 - 1f617 - 1f619 - 1f61a - 263a - 1f642 - 1f917 - 1f607 - 1f914 - 1f610 - 1f611 - 1f636 - 1f644 - 1f60f - 1f623 - 1f625 - 1f62e - 1f910 - 1f62f - 1f62a - 1f62b - 1f634 - 1f60c - 1f913 - 1f61b - 1f61c - 1f61d - 2639 - 1f641 - 1f612 - 1f613 - 1f614 - 1f615 - 1f616 - 1f643 - 1f637 - 1f912 - 1f915 - 1f911 - 1f632 - 1f61e - 1f61f - 1f624 - 1f622 - 1f62d - 1f626 - 1f627 - 1f628 - 1f629 - 1f62c - 1f630 - 1f631 - 1f633 - 1f635 - 1f621 - 1f620 - 1f608 - 1f47f - 1f479 - 1f47a - 1f480 - 2620 - 1f47b - 1f47d - 1f47e - 1f916 - 1f4a9 - 1f63a - 1f638 - 1f639 - 1f63b - 1f63c - 1f63d - 1f640 - 1f63f - 1f63e - 1f648 - 1f649 - 1f64a - 1f466 - 1f467 - 1f468 - 1f469 - 1f474 - 1f475 - 1f476 - 1f471 - 1f46e - 1f472 - 1f473 - 1f477 - 26d1 - 1f478 - 1f482 - 1f575 - 1f385 - 1f47c - 1f46f - 1f486 - 1f487 - 1f470 - 1f64d - 1f64e - 1f645 - 1f646 - 1f481 - 1f64b - 1f647 - 1f64c - 1f64f - 1f5e3 - 1f464 - 1f465 - 1f6b6 - 1f3c3 - 1f483 - 1f574 - 1f46b - 1f46c - 1f46d - 1f48f - 1f468,200d,2764,fe0f,200d,1f48b,200d,1f468 - 1f469,200d,2764,fe0f,200d,1f48b,200d,1f469 - 1f491 - 1f468,200d,2764,fe0f,200d,1f468 - 1f469,200d,2764,fe0f,200d,1f469 - 1f46a - 1f468,200d,1f468,200d,1f466 - 1f468,200d,1f468,200d,1f466,200d,1f466 - 1f468,200d,1f468,200d,1f467 - 1f468,200d,1f468,200d,1f467,200d,1f466 - 1f468,200d,1f468,200d,1f467,200d,1f467 - 1f468,200d,1f469,200d,1f466 - 1f468,200d,1f469,200d,1f466,200d,1f466 - 1f468,200d,1f469,200d,1f467 - 1f468,200d,1f469,200d,1f467,200d,1f466 - 1f468,200d,1f469,200d,1f467,200d,1f467 - 1f469,200d,1f469,200d,1f466 - 1f469,200d,1f469,200d,1f466,200d,1f466 - 1f469,200d,1f469,200d,1f467 - 1f469,200d,1f469,200d,1f467,200d,1f466 - 1f469,200d,1f469,200d,1f467,200d,1f467 - 1f3fb - 1f3fc - 1f3fd - 1f3fe - 1f3ff - 1f4aa - 1f448 - 1f449 - 261d - 1f446 - 1f595 - 1f447 - 270c - 1f596 - 1f918 - 1f590 - 270a - 270b - 1f44a - 1f44c - 1f44d - 1f44e - 1f44b - 1f44f - 1f450 - 270d - 1f485 - 1f442 - 1f443 - 1f463 - 1f440 - 1f441 - 1f445 - 1f444 - 1f48b - 1f498 - 2764 - 1f493 - 1f494 - 1f495 - 1f496 - 1f497 - 1f499 - 1f49a - 1f49b - 1f49c - 1f49d - 1f49e - 1f49f - 2763 - 1f48c - 1f4a4 - 1f4a2 - 1f4a3 - 1f4a5 - 1f4a6 - 1f4a8 - 1f4ab - 1f4ac - 1f5e8 - 1f5ef - 1f4ad - 1f441,200d,1f5e8 - 1f573 - 1f453 - 1f576 - 1f454 - 1f455 - 1f456 - 1f457 - 1f458 - 1f459 - 1f45a - 1f45b - 1f45c - 1f45d - 1f6cd - 1f392 - 1f45e - 1f45f - 1f460 - 1f461 - 1f462 - 1f451 - 1f452 - 1f3a9 - 1f393 - 1f4ff - 1f484 - 1f48d - 1f48e - - - 1f347 - 1f348 - 1f349 - 1f34a - 1f34b - 1f34c - 1f34d - 1f34e - 1f34f - 1f350 - 1f351 - 1f352 - 1f353 - 1f345 - 1f346 - 1f33d - 1f336 - 1f344 - 1f330 - 1f35e - 1f9c0 - 1f356 - 1f357 - 1f354 - 1f35f - 1f355 - 1f32d - 1f32e - 1f32f - 1f37f - 1f372 - 1f371 - 1f358 - 1f359 - 1f35a - 1f35b - 1f35c - 1f35d - 1f360 - 1f362 - 1f363 - 1f364 - 1f365 - 1f361 - 1f366 - 1f367 - 1f368 - 1f369 - 1f36a - 1f382 - 1f370 - 1f36b - 1f36c - 1f36d - 1f36e - 1f36f - 1f37c - 2615 - 1f375 - 1f376 - 1f37e - 1f377 - 1f378 - 1f379 - 1f37a - 1f37b - 1f37d - 1f374 - 1f373 - 1f3fa - - - 1f507 - 1f508 - 1f509 - 1f50a - 1f4e2 - 1f4e3 - 1f4ef - 1f514 - 1f515 - 1f3bc - 1f3b5 - 1f3b6 - 1f399 - 1f39a - 1f39b - 1f3a4 - 1f3a7 - 1f3b7 - 1f3b8 - 1f3b9 - 1f3ba - 1f3bb - 1f4fb - 1f4f1 - 1f4f2 - 260e - 1f4de - 1f4df - 1f4e0 - 1f50b - 1f50c - 1f4bb - 1f5a5 - 1f5a8 - 2328 - 1f5b1 - 1f5b2 - 1f4bd - 1f4be - 1f4bf - 1f4c0 - 1f3a5 - 1f3ac - 1f4fd - 1f4fa - 1f4f7 - 1f4f8 - 1f4f9 - 1f4fc - 1f50d - 1f50e - 1f52c - 1f52d - 1f4e1 - 1f56f - 1f4a1 - 1f526 - 1f3ee - 1f4d4 - 1f4d5 - 1f4d6 - 1f4d7 - 1f4d8 - 1f4d9 - 1f4da - 1f4d3 - 1f4d2 - 1f4c3 - 1f4dc - 1f4c4 - 1f4f0 - 1f5de - 1f4d1 - 1f516 - 1f4b0 - 1f4b4 - 1f4b5 - 1f4b6 - 1f4b7 - 1f4b8 - 1f4b3 - 1f4b9 - 2709 - 1f4e7 - 1f4e8 - 1f4e9 - 1f4e4 - 1f4e5 - 1f4e6 - 1f4eb - 1f4ea - 1f4ec - 1f4ed - 1f4ee - 1f5f3 - 270f - 2712 - 1f58b - 1f58a - 1f58c - 1f58d - 1f4dd - 1f4bc - 1f4c1 - 1f4c2 - 1f5c2 - 1f4c5 - 1f4c6 - 1f5d2 - 1f5d3 - 1f4c7 - 1f4c8 - 1f4c9 - 1f4ca - 1f4cb - 1f4cc - 1f4cd - 1f4ce - 1f587 - 1f4cf - 1f4d0 - 2702 - 1f5c3 - 1f5c4 - 1f5d1 - 1f512 - 1f513 - 1f50f - 1f510 - 1f511 - 1f5dd - 1f528 - 26cf - 2692 - 1f6e0 - 1f527 - 1f529 - 2699 - 1f5dc - 2697 - 2696 - 1f517 - 26d3 - 1f489 - 1f48a - 1f5e1 - 1f52a - 2694 - 1f52b - 1f6e1 - 1f3f9 - 1f6ac - 26b0 - 26b1 - 1f5ff - 1f6e2 - 1f52e - - - 1f383 - 1f384 - 1f386 - 1f387 - 2728 - 1f388 - 1f389 - 1f38a - 1f38b - 1f38c - 1f38d - 1f38e - 1f38f - 1f390 - 1f391 - 1f380 - 1f381 - 1f396 - 1f397 - 1f39e - 1f39f - 1f3ab - 1f3f7 - 26bd - 26be - 1f3c0 - 1f3c8 - 1f3c9 - 1f3be - 1f3b1 - 1f3b3 - 26f3 - 1f3cc - 26f8 - 1f3a3 - 1f3bd - 1f3bf - 26f7 - 1f3c2 - 1f3c4 - 1f3c7 - 1f3ca - 26f9 - 1f3cb - 1f6b4 - 1f6b5 - 1f3ce - 1f3cd - 1f3c5 - 1f3c6 - 1f3cf - 1f3d0 - 1f3d1 - 1f3d2 - 1f3d3 - 1f3f8 - 1f3af - 1f3ae - 1f579 - 1f3b2 - 2660 - 2665 - 2666 - 2663 - 1f0cf - 1f004 - 1f3b4 - - - 1f30d - 1f30e - 1f30f - 1f310 - 1f5fa - 1f3d4 - 26f0 - 1f30b - 1f5fb - 1f3d5 - 1f3d6 - 1f3dc - 1f3dd - 1f3de - 1f3df - 1f3db - 1f3d7 - 1f3d8 - 1f3d9 - 1f3da - 1f3e0 - 1f3e1 - 26ea - 1f54b - 1f54c - 1f54d - 26e9 - 1f3e2 - 1f3e3 - 1f3e4 - 1f3e5 - 1f3e6 - 1f3e8 - 1f3e9 - 1f3ea - 1f3eb - 1f3ec - 1f3ed - 1f3ef - 1f3f0 - 1f492 - 1f5fc - 1f5fd - 1f5fe - 26f2 - 26fa - 1f301 - 1f303 - 1f304 - 1f305 - 1f306 - 1f307 - 1f309 - 2668 - 1f30c - 1f3a0 - 1f3a1 - 1f3a2 - 1f488 - 1f3aa - 1f3ad - 1f5bc - 1f3a8 - 1f3b0 - 1f682 - 1f683 - 1f684 - 1f685 - 1f686 - 1f687 - 1f688 - 1f689 - 1f68a - 1f69d - 1f69e - 1f68b - 1f68c - 1f68d - 1f68e - 1f68f - 1f690 - 1f691 - 1f692 - 1f693 - 1f694 - 1f695 - 1f696 - 1f697 - 1f698 - 1f699 - 1f69a - 1f69b - 1f69c - 1f6b2 - 26fd - 1f6e3 - 1f6e4 - 1f6a8 - 1f6a5 - 1f6a6 - 1f6a7 - 2693 - 26f5 - 1f6a3 - 1f6a4 - 1f6f3 - 26f4 - 1f6e5 - 1f6a2 - 2708 - 1f6e9 - 1f6eb - 1f6ec - 1f4ba - 1f681 - 1f69f - 1f6a0 - 1f6a1 - 1f680 - 1f6f0 - 1f6ce - 1f6aa - 1f6cc - 1f6cf - 1f6cb - 1f6bd - 1f6bf - 1f6c0 - 1f6c1 - 231b - 23f3 - 231a - 23f0 - 23f1 - 23f2 - 1f570 - 1f55b - 1f567 - 1f550 - 1f55c - 1f551 - 1f55d - 1f552 - 1f55e - 1f553 - 1f55f - 1f554 - 1f560 - 1f555 - 1f561 - 1f556 - 1f562 - 1f557 - 1f563 - 1f558 - 1f564 - 1f559 - 1f565 - 1f55a - 1f566 - 1f311 - 1f312 - 1f313 - 1f314 - 1f315 - 1f316 - 1f317 - 1f318 - 1f319 - 1f31a - 1f31b - 1f31c - 1f321 - 2600 - 1f31d - 1f31e - 2b50 - 1f31f - 1f320 - 2601 - 26c5 - 26c8 - 1f324 - 1f325 - 1f326 - 1f327 - 1f328 - 1f329 - 1f32a - 1f32b - 1f32c - 1f300 - 1f308 - 1f302 - 2602 - 2614 - 26f1 - 26a1 - 2744 - 2603 - 26c4 - 2604 - 1f525 - 1f4a7 - 1f30a - - - 1f1e6,1f1e8 - 1f1e6,1f1e9 - 1f1e6,1f1ea - 1f1e6,1f1eb - 1f1e6,1f1ec - 1f1e6,1f1ee - 1f1e6,1f1f1 - 1f1e6,1f1f2 - 1f1e6,1f1f4 - 1f1e6,1f1f6 - 1f1e6,1f1f7 - 1f1e6,1f1f8 - 1f1e6,1f1f9 - 1f1e6,1f1fa - 1f1e6,1f1fc - 1f1e6,1f1fd - 1f1e6,1f1ff - 1f1e7,1f1e6 - 1f1e7,1f1e7 - 1f1e7,1f1e9 - 1f1e7,1f1ea - 1f1e7,1f1eb - 1f1e7,1f1ec - 1f1e7,1f1ed - 1f1e7,1f1ee - 1f1e7,1f1ef - 1f1e7,1f1f1 - 1f1e7,1f1f2 - 1f1e7,1f1f3 - 1f1e7,1f1f4 - 1f1e7,1f1f6 - 1f1e7,1f1f7 - 1f1e7,1f1f8 - 1f1e7,1f1f9 - 1f1e7,1f1fb - 1f1e7,1f1fc - 1f1e7,1f1fe - 1f1e7,1f1ff - 1f1e8,1f1e6 - 1f1e8,1f1e8 - 1f1e8,1f1e9 - 1f1e8,1f1eb - 1f1e8,1f1ec - 1f1e8,1f1ed - 1f1e8,1f1ee - 1f1e8,1f1f0 - 1f1e8,1f1f1 - 1f1e8,1f1f2 - 1f1e8,1f1f3 - 1f1e8,1f1f4 - 1f1e8,1f1f5 - 1f1e8,1f1f7 - 1f1e8,1f1fa - 1f1e8,1f1fb - 1f1e8,1f1fc - 1f1e8,1f1fd - 1f1e8,1f1fe - 1f1e8,1f1ff - 1f1e9,1f1ea - 1f1e9,1f1ec - 1f1e9,1f1ef - 1f1e9,1f1f0 - 1f1e9,1f1f2 - 1f1e9,1f1f4 - 1f1e9,1f1ff - 1f1ea,1f1e6 - 1f1ea,1f1e8 - 1f1ea,1f1ea - 1f1ea,1f1ec - 1f1ea,1f1ed - 1f1ea,1f1f7 - 1f1ea,1f1f8 - 1f1ea,1f1f9 - 1f1ea,1f1fa - 1f1eb,1f1ee - 1f1eb,1f1ef - 1f1eb,1f1f0 - 1f1eb,1f1f2 - 1f1eb,1f1f4 - 1f1eb,1f1f7 - 1f1ec,1f1e6 - 1f1ec,1f1e7 - 1f1ec,1f1e9 - 1f1ec,1f1ea - 1f1ec,1f1eb - 1f1ec,1f1ec - 1f1ec,1f1ed - 1f1ec,1f1ee - 1f1ec,1f1f1 - 1f1ec,1f1f2 - 1f1ec,1f1f3 - 1f1ec,1f1f5 - 1f1ec,1f1f6 - 1f1ec,1f1f7 - 1f1ec,1f1f8 - 1f1ec,1f1f9 - 1f1ec,1f1fa - 1f1ec,1f1fc - 1f1ec,1f1fe - 1f1ed,1f1f0 - 1f1ed,1f1f2 - 1f1ed,1f1f3 - 1f1ed,1f1f7 - 1f1ed,1f1f9 - 1f1ed,1f1fa - 1f1ee,1f1e8 - 1f1ee,1f1e9 - 1f1ee,1f1ea - 1f1ee,1f1f1 - 1f1ee,1f1f2 - 1f1ee,1f1f3 - 1f1ee,1f1f4 - 1f1ee,1f1f6 - 1f1ee,1f1f7 - 1f1ee,1f1f8 - 1f1ee,1f1f9 - 1f1ef,1f1ea - 1f1ef,1f1f2 - 1f1ef,1f1f4 - 1f1ef,1f1f5 - 1f1f0,1f1ea - 1f1f0,1f1ec - 1f1f0,1f1ed - 1f1f0,1f1ee - 1f1f0,1f1f2 - 1f1f0,1f1f3 - 1f1f0,1f1f5 - 1f1f0,1f1f7 - 1f1f0,1f1fc - 1f1f0,1f1fe - 1f1f0,1f1ff - 1f1f1,1f1e6 - 1f1f1,1f1e7 - 1f1f1,1f1e8 - 1f1f1,1f1ee - 1f1f1,1f1f0 - 1f1f1,1f1f7 - 1f1f1,1f1f8 - 1f1f1,1f1f9 - 1f1f1,1f1fa - 1f1f1,1f1fb - 1f1f1,1f1fe - 1f1f2,1f1e6 - 1f1f2,1f1e8 - 1f1f2,1f1e9 - 1f1f2,1f1ea - 1f1f2,1f1eb - 1f1f2,1f1ec - 1f1f2,1f1ed - 1f1f2,1f1f0 - 1f1f2,1f1f1 - 1f1f2,1f1f2 - 1f1f2,1f1f3 - 1f1f2,1f1f4 - 1f1f2,1f1f5 - 1f1f2,1f1f6 - 1f1f2,1f1f7 - 1f1f2,1f1f8 - 1f1f2,1f1f9 - 1f1f2,1f1fa - 1f1f2,1f1fb - 1f1f2,1f1fc - 1f1f2,1f1fd - 1f1f2,1f1fe - 1f1f2,1f1ff - 1f1f3,1f1e6 - 1f1f3,1f1e8 - 1f1f3,1f1ea - 1f1f3,1f1eb - 1f1f3,1f1ec - 1f1f3,1f1ee - 1f1f3,1f1f1 - 1f1f3,1f1f4 - 1f1f3,1f1f5 - 1f1f3,1f1f7 - 1f1f3,1f1fa - 1f1f3,1f1ff - 1f1f4,1f1f2 - 1f1f5,1f1e6 - 1f1f5,1f1ea - 1f1f5,1f1eb - 1f1f5,1f1ec - 1f1f5,1f1ed - 1f1f5,1f1f0 - 1f1f5,1f1f1 - 1f1f5,1f1f2 - 1f1f5,1f1f3 - 1f1f5,1f1f7 - 1f1f5,1f1f8 - 1f1f5,1f1f9 - 1f1f5,1f1fc - 1f1f5,1f1fe - 1f1f6,1f1e6 - 1f1f7,1f1ea - 1f1f7,1f1f4 - 1f1f7,1f1f8 - 1f1f7,1f1fa - 1f1f7,1f1fc - 1f1f8,1f1e6 - 1f1f8,1f1e7 - 1f1f8,1f1e8 - 1f1f8,1f1e9 - 1f1f8,1f1ea - 1f1f8,1f1ec - 1f1f8,1f1ed - 1f1f8,1f1ee - 1f1f8,1f1ef - 1f1f8,1f1f0 - 1f1f8,1f1f1 - 1f1f8,1f1f2 - 1f1f8,1f1f3 - 1f1f8,1f1f4 - 1f1f8,1f1f7 - 1f1f8,1f1f8 - 1f1f8,1f1f9 - 1f1f8,1f1fb - 1f1f8,1f1fd - 1f1f8,1f1fe - 1f1f8,1f1ff - 1f1f9,1f1e6 - 1f1f9,1f1e8 - 1f1f9,1f1e9 - 1f1f9,1f1eb - 1f1f9,1f1ec - 1f1f9,1f1ed - 1f1f9,1f1ef - 1f1f9,1f1f0 - 1f1f9,1f1f1 - 1f1f9,1f1f2 - 1f1f9,1f1f3 - 1f1f9,1f1f4 - 1f1f9,1f1f7 - 1f1f9,1f1f9 - 1f1f9,1f1fb - 1f1f9,1f1fc - 1f1f9,1f1ff - 1f1fa,1f1e6 - 1f1fa,1f1ec - 1f1fa,1f1f2 - 1f1fa,1f1f8 - 1f1fa,1f1fe - 1f1fa,1f1ff - 1f1fb,1f1e6 - 1f1fb,1f1e8 - 1f1fb,1f1ea - 1f1fb,1f1ec - 1f1fb,1f1ee - 1f1fb,1f1f3 - 1f1fb,1f1fa - 1f1fc,1f1eb - 1f1fc,1f1f8 - 1f1fd,1f1f0 - 1f1fe,1f1ea - 1f1fe,1f1f9 - 1f1ff,1f1e6 - 1f1ff,1f1f2 - 1f1ff,1f1fc - - diff --git a/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java b/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java index 024c62b14..2c0cb2a38 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/TestBriarApplication.java @@ -4,6 +4,9 @@ import android.app.Application; import android.content.SharedPreferences; import android.preference.PreferenceManager; +import com.vanniktech.emoji.EmojiManager; +import com.vanniktech.emoji.google.GoogleEmojiProvider; + import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.briar.BriarCoreModule; @@ -41,6 +44,7 @@ public class TestBriarApplication extends Application BrambleCoreModule.initEagerSingletons(applicationComponent); BriarCoreModule.initEagerSingletons(applicationComponent); AndroidEagerSingletons.initEagerSingletons(applicationComponent); + EmojiManager.install(new GoogleEmojiProvider()); } @Override diff --git a/briar-android/witness.gradle b/briar-android/witness.gradle index 8fe1e3e98..e262ffb0c 100644 --- a/briar-android/witness.gradle +++ b/briar-android/witness.gradle @@ -63,7 +63,6 @@ dependencyVerification { 'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59', 'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1', 'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b', - 'com.github.bumptech.glide:glide:3.8.0:glide-3.8.0.jar:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655', 'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.0:accessibility-test-framework-2.0.jar:cdf16ef8f5b8023d003ce3cc1b0d51bda737762e2dab2fedf43d1c4292353f7f', 'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.1:accessibility-test-framework-2.1.jar:7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd', 'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed', @@ -83,13 +82,14 @@ dependencyVerification { 'com.google.zxing:core:3.3.0:core-3.3.0.jar:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d', 'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439', 'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab', - 'com.jpardogo.materialtabstrip:library:1.1.0:library-1.1.0.aar:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311', 'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e', 'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0', 'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce', 'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4', 'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038', 'com.thoughtworks.xstream:xstream:1.4.8:xstream-1.4.8.jar:a219a1abf948400b669d08be73a6f9209fb720d237e5ff74c223bffe5f9df93d', + 'com.vanniktech:emoji-google:0.5.1:emoji-google-0.5.1.aar:5f4a88e1a3bb5f694ddccf2e49dc9ccc44431f1d4f980bc453c178f57869dea0', + 'com.vanniktech:emoji:0.5.1:emoji-0.5.1.aar:d55f44e04e31895647d62c33c34a8d501995e9e1b5c5f5cee6cbb8630eeb37f7', 'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86', 'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f', 'de.hdodenhof:circleimageview:2.2.0:circleimageview-2.2.0.aar:bc34761dcd5036229ac1ffed6b5b1bef722ad5b097a2c8bba1c5ed2cd4b5c82b',