Fix emoji on odd densities and add internal pref to force built-in.
This commit is contained in:
parent
6c2adfeec2
commit
efc3e7b25d
7 changed files with 68 additions and 11 deletions
|
@ -2,19 +2,18 @@ package org.thoughtcrime.securesms.emoji
|
|||
|
||||
import android.net.Uri
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.emoji.Emoji
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel
|
||||
import org.thoughtcrime.securesms.components.emoji.StaticEmojiPageModel
|
||||
import org.thoughtcrime.securesms.components.emoji.parsing.EmojiDrawInfo
|
||||
import org.thoughtcrime.securesms.components.emoji.parsing.EmojiTree
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader
|
||||
import org.thoughtcrime.securesms.util.ScreenDensity
|
||||
import java.io.InputStream
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* The entry point for the application to request Emoji data for custom emojis.
|
||||
|
@ -88,27 +87,27 @@ class EmojiSource(
|
|||
}
|
||||
|
||||
private fun loadRemoteBasedEmojis(): EmojiSource? {
|
||||
if (SignalStore.internalValues().forceBuiltInEmoji()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val context = ApplicationDependencies.getApplication()
|
||||
val version = EmojiFiles.Version.readVersion(context) ?: return null
|
||||
val emojiData = EmojiFiles.getLatestEmojiData(context, version)
|
||||
val density = ScreenDensity.xhdpiRelativeDensityScaleFactor(version.density)
|
||||
|
||||
return emojiData?.let {
|
||||
val decodeScale = min(1f, context.resources.getDimension(R.dimen.emoji_drawer_size) / it.metrics.rawHeight)
|
||||
|
||||
EmojiSource(decodeScale * density, it) { uri: Uri -> EmojiPageReference(DecryptableStreamUriLoader.DecryptableUri(uri)) }
|
||||
EmojiSource(density, it) { uri: Uri -> EmojiPageReference(DecryptableStreamUriLoader.DecryptableUri(uri)) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadAssetBasedEmojis(): EmojiSource {
|
||||
val context = ApplicationDependencies.getApplication()
|
||||
val emojiData: InputStream = ApplicationDependencies.getApplication().assets.open("emoji/emoji_data.json")
|
||||
|
||||
emojiData.use {
|
||||
val parsedData: ParsedEmojiData = EmojiJsonParser.parse(it, ::getAssetsUri).getOrThrow()
|
||||
val decodeScale = min(1f, context.resources.getDimension(R.dimen.emoji_drawer_size) / parsedData.metrics.rawHeight)
|
||||
return EmojiSource(
|
||||
decodeScale * ScreenDensity.xhdpiRelativeDensityScaleFactor("xhdpi"),
|
||||
ScreenDensity.xhdpiRelativeDensityScaleFactor("xhdpi"),
|
||||
parsedData.copy(
|
||||
displayPages = parsedData.displayPages + PAGE_EMOTICONS,
|
||||
dataPages = parsedData.dataPages + PAGE_EMOTICONS
|
||||
|
|
|
@ -17,6 +17,7 @@ public final class InternalValues extends SignalStoreValues {
|
|||
public static final String GV2_DISABLE_AUTOMIGRATE_NOTIFICATION = "internal.gv2.disable_automigrate_notification";
|
||||
public static final String RECIPIENT_DETAILS = "internal.recipient_details";
|
||||
public static final String FORCE_CENSORSHIP = "internal.force_censorship";
|
||||
public static final String FORCE_BUILT_IN_EMOJI = "internal.force_built_in_emoji";
|
||||
|
||||
InternalValues(KeyValueStore store) {
|
||||
super(store);
|
||||
|
@ -80,6 +81,13 @@ public final class InternalValues extends SignalStoreValues {
|
|||
return FeatureFlags.internalUser() && getBoolean(FORCE_CENSORSHIP, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the app to behave as if it is in a country where Signal is censored.
|
||||
*/
|
||||
public synchronized boolean forceBuiltInEmoji() {
|
||||
return FeatureFlags.internalUser() && getBoolean(FORCE_BUILT_IN_EMOJI, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable initiating a GV1->GV2 auto-migration. You can still recognize a group has been
|
||||
* auto-migrated.
|
||||
|
|
|
@ -14,6 +14,8 @@ import com.google.android.gms.common.ConnectionResult;
|
|||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiFiles;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||
import org.thoughtcrime.securesms.util.AppSignatureUtil;
|
||||
import org.thoughtcrime.securesms.util.ByteUnit;
|
||||
import org.thoughtcrime.securesms.util.CensorshipUtil;
|
||||
|
@ -66,6 +68,7 @@ public class LogSectionSystemInfo implements LogSection {
|
|||
builder.append("Linked Devices: ").append(TextSecurePreferences.isMultiDevice(context)).append("\n");
|
||||
builder.append("First Version : ").append(TextSecurePreferences.getFirstInstallVersion(context)).append("\n");
|
||||
builder.append("Days Installed: ").append(VersionTracker.getDaysSinceFirstInstalled(context)).append("\n");
|
||||
builder.append("Emoji Version : ").append(getEmojiVersionString(context)).append("\n");
|
||||
builder.append("App : ");
|
||||
try {
|
||||
builder.append(pm.getApplicationLabel(pm.getApplicationInfo(context.getPackageName(), 0)))
|
||||
|
@ -146,4 +149,14 @@ public class LogSectionSystemInfo implements LogSection {
|
|||
int result = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
|
||||
return result == ConnectionResult.SUCCESS ? "true" : "false (" + result + ")";
|
||||
}
|
||||
|
||||
private static String getEmojiVersionString(@NonNull Context context) {
|
||||
EmojiFiles.Version version = EmojiFiles.Version.readVersion(context);
|
||||
|
||||
if (version == null) {
|
||||
return "None";
|
||||
} else {
|
||||
return version.getVersion() + " (" + version.getDensity() + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
|||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiFiles;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
|
||||
import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob;
|
||||
import org.thoughtcrime.securesms.jobs.RemoteConfigRefreshJob;
|
||||
|
@ -49,6 +51,7 @@ public class InternalOptionsPreferenceFragment extends CorrectedPreferenceFragme
|
|||
initializeSwitchPreference(preferenceDataStore, InternalValues.GV2_DISABLE_AUTOMIGRATE_INITIATION, SignalStore.internalValues().disableGv1AutoMigrateInitiation());
|
||||
initializeSwitchPreference(preferenceDataStore, InternalValues.GV2_DISABLE_AUTOMIGRATE_NOTIFICATION, SignalStore.internalValues().disableGv1AutoMigrateNotification());
|
||||
initializeSwitchPreference(preferenceDataStore, InternalValues.FORCE_CENSORSHIP, SignalStore.internalValues().forcedCensorship());
|
||||
initializeSwitchPreference(preferenceDataStore, InternalValues.FORCE_BUILT_IN_EMOJI, SignalStore.internalValues().forceBuiltInEmoji());
|
||||
|
||||
findPreference("pref_copy_payments_data").setOnPreferenceClickListener(preference -> {
|
||||
new AlertDialog.Builder(getContext())
|
||||
|
@ -122,5 +125,21 @@ public class InternalOptionsPreferenceFragment extends CorrectedPreferenceFragme
|
|||
super.onResume();
|
||||
//noinspection ConstantConditions
|
||||
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__internal_preferences);
|
||||
|
||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(),
|
||||
() -> EmojiFiles.Version.readVersion(requireContext()),
|
||||
version -> {
|
||||
if (version != null) {
|
||||
findPreference(InternalValues.FORCE_BUILT_IN_EMOJI).setSummary(getString(R.string.preferences__internal_current_version_d_at_density_s, version.getVersion(), version.getDensity()));
|
||||
} else {
|
||||
findPreference(InternalValues.FORCE_BUILT_IN_EMOJI).setSummary(getString(R.string.preferences__internal_current_version_builtin));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
SignalExecutors.BOUNDED.execute(EmojiSource::refresh);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2418,6 +2418,10 @@
|
|||
<string name="preferences__internal_force_censorship" translatable="false">Force censorship</string>
|
||||
<string name="preferences__internal_force_censorship_description" translatable="false">Force the app to behave as if it is in a country where Signal is censored.</string>
|
||||
<string name="preferences__internal_conversations_and_shortcuts" translatable="false">Conversations and Shortcuts</string>
|
||||
<string name="preferences__internal_emoji" translatable="false">Emoji</string>
|
||||
<string name="preferences__internal_use_built_in_emoji_set" translatable="false">Use built-in emoji set.</string>
|
||||
<string name="preferences__internal_current_version_builtin" translatable="false">Current version: Built-In</string>
|
||||
<string name="preferences__internal_current_version_d_at_density_s" translatable="false">Current version: %1$d at density %2$s</string>
|
||||
<string name="preferences__internal_delete_all_dynamic_shortcuts" translatable="false">Delete all dynamic shortcuts</string>
|
||||
<string name="preferences__internal_click_to_delete_all_dynamic_shortcuts" translatable="false">Click to delete all dynamic shortcuts</string>
|
||||
<string name="preferences__internal_disable_profile_sharing" translatable="false">Disable Profile Sharing</string>
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
android:title="@string/preferences__internal_display">
|
||||
|
||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||
android:key="internal.recipient_details"
|
||||
android:defaultValue="false"
|
||||
android:key="internal.recipient_details"
|
||||
android:summary="@string/preferences__internal_user_details_description"
|
||||
android:title="@string/preferences__internal_user_details" />
|
||||
|
||||
|
@ -124,4 +124,13 @@
|
|||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/preferences__internal_emoji">
|
||||
|
||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="internal.force_built_in_emoji"
|
||||
android:title="@string/preferences__internal_use_built_in_emoji_set" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
|
@ -19,6 +19,8 @@ import org.robolectric.annotation.Config;
|
|||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||
import org.thoughtcrime.securesms.keyvalue.InternalValues;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
@ -31,7 +33,7 @@ import static org.mockito.Mockito.mock;
|
|||
@RunWith(ParameterizedRobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE, application = Application.class)
|
||||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "androidx.*" })
|
||||
@PrepareForTest({ApplicationDependencies.class, AttachmentSecretProvider.class})
|
||||
@PrepareForTest({ApplicationDependencies.class, AttachmentSecretProvider.class, SignalStore.class, InternalValues.class})
|
||||
public class EmojiUtilTest_isEmoji {
|
||||
|
||||
public @Rule PowerMockRule rule = new PowerMockRule();
|
||||
|
@ -68,13 +70,16 @@ public class EmojiUtilTest_isEmoji {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void isEmoji() {
|
||||
public void isEmoji() throws Exception {
|
||||
Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
PowerMockito.mockStatic(ApplicationDependencies.class);
|
||||
PowerMockito.when(ApplicationDependencies.getApplication()).thenReturn((Application) context);
|
||||
PowerMockito.mockStatic(AttachmentSecretProvider.class);
|
||||
PowerMockito.when(AttachmentSecretProvider.getInstance(any())).thenThrow(IOException.class);
|
||||
PowerMockito.whenNew(SignalStore.class).withAnyArguments().thenReturn(null);
|
||||
PowerMockito.mockStatic(SignalStore.class);
|
||||
PowerMockito.when(SignalStore.internalValues()).thenReturn(PowerMockito.mock(InternalValues.class));
|
||||
EmojiSource.refresh();
|
||||
|
||||
assertEquals(output, EmojiUtil.isEmoji(context, input));
|
||||
|
|
Loading…
Add table
Reference in a new issue