Fix incorrect restarting and theming when system changes night mode.

This commit is contained in:
Cody Henthorne 2020-11-13 14:39:00 -05:00 committed by GitHub
parent 2a193ef455
commit 4ecfee292e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 18 deletions

View file

@ -12,10 +12,13 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.ConfigurationUtil;
import org.thoughtcrime.securesms.util.ContextUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.WindowUtil;
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
@ -75,17 +78,20 @@ public abstract class BaseActivity extends AppCompatActivity {
}
@Override
protected void attachBaseContext(Context newBase) {
protected void attachBaseContext(@NonNull Context newBase) {
super.attachBaseContext(newBase);
Configuration configuration = new Configuration();
configuration.uiMode = (configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | getDelegate().getLocalNightMode();
Configuration configuration = new Configuration(newBase.getResources().getConfiguration());
int appCompatNightMode = getDelegate().getLocalNightMode() != AppCompatDelegate.MODE_NIGHT_UNSPECIFIED ? getDelegate().getLocalNightMode()
: AppCompatDelegate.getDefaultNightMode();
configuration.uiMode = (configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | mapNightModeToConfigurationUiMode(newBase, appCompatNightMode);
applyOverrideConfiguration(configuration);
}
@Override
public void applyOverrideConfiguration(Configuration overrideConfiguration) {
public void applyOverrideConfiguration(@NonNull Configuration overrideConfiguration) {
DynamicLanguageContextWrapper.prepareOverrideConfiguration(this, overrideConfiguration);
super.applyOverrideConfiguration(overrideConfiguration);
}
@ -97,4 +103,13 @@ public abstract class BaseActivity extends AppCompatActivity {
public final @NonNull ActionBar requireSupportActionBar() {
return Objects.requireNonNull(getSupportActionBar());
}
private static int mapNightModeToConfigurationUiMode(@NonNull Context context, @AppCompatDelegate.NightMode int appCompatNightMode) {
if (appCompatNightMode == AppCompatDelegate.MODE_NIGHT_YES) {
return Configuration.UI_MODE_NIGHT_YES;
} else if (appCompatNightMode == AppCompatDelegate.MODE_NIGHT_NO) {
return Configuration.UI_MODE_NIGHT_NO;
}
return ConfigurationUtil.getNightModeConfiguration(context.getApplicationContext());
}
}

View file

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.content.res.Configuration;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -50,7 +51,7 @@ public class CachedInflater {
@MainThread
@SuppressWarnings("unchecked")
public <V extends View> V inflate(@LayoutRes int layoutRes, @Nullable ViewGroup parent, boolean attachToRoot) {
View cached = ViewCache.getInstance().pull(layoutRes, ContextUtil.getNightModeConfiguration(context));
View cached = ViewCache.getInstance().pull(layoutRes, context.getResources().getConfiguration());
if (cached != null) {
if (parent != null && attachToRoot) {
parent.addView(cached);
@ -84,9 +85,9 @@ public class CachedInflater {
private final Map<Integer, List<View>> cache = new HashMap<>();
private long lastClearTime;
private int nightModeConfiguration;
private long lastClearTime;
private int nightModeConfiguration;
private float fontScale;
static ViewCache getInstance() {
return INSTANCE;
@ -94,10 +95,14 @@ public class CachedInflater {
@MainThread
void cacheUntilLimit(@NonNull Context context, @LayoutRes int layoutRes, @Nullable ViewGroup parent, int limit) {
int currentNightModeConfiguration = ContextUtil.getNightModeConfiguration(context);
if (nightModeConfiguration != currentNightModeConfiguration) {
Configuration configuration = context.getResources().getConfiguration();
int currentNightModeConfiguration = ConfigurationUtil.getNightModeConfiguration(configuration);
float currentFontScale = ConfigurationUtil.getFontScale(configuration);
if (nightModeConfiguration != currentNightModeConfiguration || fontScale != currentFontScale) {
clear();
nightModeConfiguration = currentNightModeConfiguration;
fontScale = currentFontScale;
}
AsyncLayoutInflater inflater = new AsyncLayoutInflater(context);
@ -125,8 +130,8 @@ public class CachedInflater {
}
@MainThread
@Nullable View pull(@LayoutRes int layoutRes, int nightModeConfiguration) {
if (this.nightModeConfiguration != nightModeConfiguration) {
@Nullable View pull(@LayoutRes int layoutRes, @NonNull Configuration configuration) {
if (this.nightModeConfiguration != ConfigurationUtil.getNightModeConfiguration(configuration) || this.fontScale != ConfigurationUtil.getFontScale(configuration)) {
clear();
return null;
}

View file

@ -0,0 +1,23 @@
package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
public final class ConfigurationUtil {
private ConfigurationUtil() {}
public static int getNightModeConfiguration(@NonNull Context context) {
return getNightModeConfiguration(context.getResources().getConfiguration());
}
public static int getNightModeConfiguration(@NonNull Configuration configuration) {
return configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
}
public static float getFontScale(@NonNull Configuration configuration) {
return configuration.fontScale;
}
}

View file

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import androidx.annotation.DrawableRes;
@ -17,7 +16,4 @@ public final class ContextUtil {
return Objects.requireNonNull(ContextCompat.getDrawable(context, drawable));
}
public static int getNightModeConfiguration(@NonNull Context context) {
return context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
}
}

View file

@ -10,9 +10,12 @@ import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatDelegate;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.logging.Log;
public class DynamicTheme {
private static final String TAG = Log.tag(DynamicTheme.class);
public static final String DARK = "dark";
public static final String LIGHT = "light";
public static final String SYSTEM = "system";
@ -24,18 +27,20 @@ public class DynamicTheme {
public void onCreate(@NonNull Activity activity) {
int previousGlobalConfiguration = globalNightModeConfiguration;
onCreateNightModeConfiguration = ContextUtil.getNightModeConfiguration(activity);
onCreateNightModeConfiguration = ConfigurationUtil.getNightModeConfiguration(activity);
globalNightModeConfiguration = onCreateNightModeConfiguration;
activity.setTheme(getTheme());
if (previousGlobalConfiguration != globalNightModeConfiguration) {
Log.d(TAG, "Previous night mode has changed previous: " + previousGlobalConfiguration + " now: " + globalNightModeConfiguration);
CachedInflater.from(activity).clear();
}
}
public void onResume(@NonNull Activity activity) {
if (onCreateNightModeConfiguration != ContextUtil.getNightModeConfiguration(activity)) {
if (onCreateNightModeConfiguration != ConfigurationUtil.getNightModeConfiguration(activity)) {
Log.d(TAG, "Create configuration different from current previous: " + onCreateNightModeConfiguration + " now: " + ConfigurationUtil.getNightModeConfiguration(activity));
CachedInflater.from(activity).clear();
}
}
@ -52,10 +57,13 @@ public class DynamicTheme {
String theme = TextSecurePreferences.getTheme(context);
if (theme.equals(SYSTEM)) {
Log.d(TAG, "Setting to follow system expecting: " + ConfigurationUtil.getNightModeConfiguration(context.getApplicationContext()));
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
} else if (DynamicTheme.isDarkTheme(context)) {
Log.d(TAG, "Setting to always night");
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
Log.d(TAG, "Setting to always day");
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}