summaryrefslogtreecommitdiffhomepage
path: root/app
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-06-05 01:49:54 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-06-05 02:02:09 +0200
commit27072972ab944467bf7286afe4bfd89a4b795753 (patch)
tree54f8cba070fe72a4ba96d61bade23f434a894f98 /app
parentd56e95c576ebcc9c070a41e1c13fb78951ef63b1 (diff)
DarkMode: move to shared preferences listener
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/com/wireguard/android/Application.java10
-rw-r--r--app/src/main/java/com/wireguard/android/activity/BaseActivity.java46
-rw-r--r--app/src/main/java/com/wireguard/android/activity/SettingsActivity.java44
-rw-r--r--app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java76
-rw-r--r--app/src/main/java/com/wireguard/android/util/Topic.java109
5 files changed, 79 insertions, 206 deletions
diff --git a/app/src/main/java/com/wireguard/android/Application.java b/app/src/main/java/com/wireguard/android/Application.java
index b8562606..74cb07cf 100644
--- a/app/src/main/java/com/wireguard/android/Application.java
+++ b/app/src/main/java/com/wireguard/android/Application.java
@@ -23,7 +23,6 @@ import com.wireguard.android.model.TunnelManager;
import com.wireguard.android.util.AsyncWorker;
import com.wireguard.android.util.RootShell;
import com.wireguard.android.util.ToolsInstaller;
-import com.wireguard.android.util.Topic;
import java.io.File;
import java.util.concurrent.Executor;
@@ -68,8 +67,6 @@ public class Application extends android.app.Application {
ToolsInstaller getToolsInstaller();
TunnelManager getTunnelManager();
-
- Topic getThemeChangeTopic();
}
@Qualifier
@@ -121,13 +118,6 @@ public class Application extends android.app.Application {
@ApplicationScope
@Provides
- public static Topic getThemeChangeTopic() {
- return new Topic();
- }
-
-
- @ApplicationScope
- @Provides
public static Executor getExecutor() {
return AsyncTask.SERIAL_EXECUTOR;
}
diff --git a/app/src/main/java/com/wireguard/android/activity/BaseActivity.java b/app/src/main/java/com/wireguard/android/activity/BaseActivity.java
index 2ebb6e90..a44035f9 100644
--- a/app/src/main/java/com/wireguard/android/activity/BaseActivity.java
+++ b/app/src/main/java/com/wireguard/android/activity/BaseActivity.java
@@ -11,24 +11,19 @@ import android.databinding.CallbackRegistry;
import android.databinding.CallbackRegistry.NotifierCallback;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
import com.wireguard.android.Application;
import com.wireguard.android.backend.GoBackend;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.model.TunnelManager;
-import com.wireguard.android.util.Topic;
-import java.lang.reflect.Field;
import java.util.Objects;
/**
* Base class for activities that need to remember the currently-selected tunnel.
*/
-public abstract class BaseActivity extends AppCompatActivity implements Topic.Subscriber {
- private static final String TAG = "WireGuard/" + BaseActivity.class.getSimpleName();
-
+public abstract class BaseActivity extends ThemeChangeAwareActivity {
private static final String KEY_SELECTED_TUNNEL = "selected_tunnel";
private final SelectionChangeRegistry selectionChangeRegistry = new SelectionChangeRegistry();
@@ -45,8 +40,6 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Su
@Override
protected void onCreate(final Bundle savedInstanceState) {
- subscribeTopics();
-
// Restore the saved tunnel if there is one; otherwise grab it from the arguments.
String savedTunnelName = null;
if (savedInstanceState != null)
@@ -70,12 +63,6 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Su
}
@Override
- protected void onDestroy() {
- unsubscribeTopics();
- super.onDestroy();
- }
-
- @Override
protected void onSaveInstanceState(final Bundle outState) {
if (selectedTunnel != null)
outState.putString(KEY_SELECTED_TUNNEL, selectedTunnel.getName());
@@ -118,35 +105,4 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Su
super(new SelectionChangeNotifier());
}
}
-
- @Override
- public void onTopicPublished(final Topic topic) {
- if (topic == Application.getComponent().getThemeChangeTopic()) {
- try {
- Field f;
- Object o = getResources();
- try {
- f = o.getClass().getDeclaredField("mResourcesImpl");
- f.setAccessible(true);
- o = f.get(o);
- } catch (final Exception ignored) { }
- f = o.getClass().getDeclaredField("mDrawableCache");
- f.setAccessible(true);
- o = f.get(o);
- try {
- o.getClass().getMethod("onConfigurationChange", int.class).invoke(o, -1);
- } catch (final Exception ignored) {
- o.getClass().getMethod("clear").invoke(o);
- }
- } catch (final Exception e) {
- Log.e(TAG, "Failed to flush drawable cache", e);
- }
- recreate();
- }
- }
-
- @Override
- public Topic[] getSubscription() {
- return new Topic[] { Application.getComponent().getThemeChangeTopic() };
- }
}
diff --git a/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java b/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java
index d7238b96..cfc9f3ef 100644
--- a/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java
+++ b/app/src/main/java/com/wireguard/android/activity/SettingsActivity.java
@@ -21,7 +21,6 @@ import android.view.MenuItem;
import com.wireguard.android.Application;
import com.wireguard.android.R;
import com.wireguard.android.backend.WgQuickBackend;
-import com.wireguard.android.util.Topic;
import java.util.ArrayList;
import java.util.Arrays;
@@ -33,7 +32,7 @@ import java.util.Map;
* Interface for changing application-global persistent settings.
*/
-public class SettingsActivity extends AppCompatActivity implements Topic.Subscriber {
+public class SettingsActivity extends ThemeChangeAwareActivity {
private final Map<Integer, PermissionRequestCallback> permissionRequestCallbacks = new HashMap<>();
private int permissionRequestCounter;
@@ -59,7 +58,6 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- subscribeTopics();
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, new SettingsFragment())
@@ -68,12 +66,6 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
}
@Override
- protected void onDestroy() {
- unsubscribeTopics();
- super.onDestroy();
- }
-
- @Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
@@ -99,18 +91,7 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
void done(String[] permissions, int[] grantResults);
}
- @Override
- public void onTopicPublished(final Topic topic) {
- if (topic == Application.getComponent().getThemeChangeTopic())
- recreate();
- }
-
- @Override
- public Topic[] getSubscription() {
- return new Topic[] { Application.getComponent().getThemeChangeTopic() };
- }
-
- public static class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
+ public static class SettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(final Bundle savedInstanceState, final String key) {
addPreferencesFromResource(R.xml.preferences);
@@ -121,26 +102,5 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
getPreferenceScreen().removePreference(pref);
}
}
-
- @Override
- public void onResume() {
- super.onResume();
- getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
- }
-
- @Override
- public void onPause() {
- getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
- super.onPause();
- }
-
- @Override
- public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
- if ("dark_theme".equals(key)) {
- AppCompatDelegate.setDefaultNightMode(
- sharedPreferences.getBoolean(key, false) ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
- Application.getComponent().getThemeChangeTopic().publish(false);
- }
- }
}
}
diff --git a/app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java b/app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java
new file mode 100644
index 00000000..250cf0a7
--- /dev/null
+++ b/app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+package com.wireguard.android.activity;
+
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.app.AppCompatDelegate;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+
+public abstract class ThemeChangeAwareActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "WireGuard/" + ThemeChangeAwareActivity.class.getSimpleName();
+
+ private static Resources lastResources;
+ private static boolean lastDarkMode;
+ private static synchronized void invalidateDrawableCache(final Resources resources, final boolean darkMode) {
+ if (resources == lastResources && darkMode == lastDarkMode)
+ return;
+
+ try {
+ Field f;
+ Object o = resources;
+ try {
+ f = o.getClass().getDeclaredField("mResourcesImpl");
+ f.setAccessible(true);
+ o = f.get(o);
+ } catch (final Exception ignored) { }
+ f = o.getClass().getDeclaredField("mDrawableCache");
+ f.setAccessible(true);
+ o = f.get(o);
+ try {
+ o.getClass().getMethod("onConfigurationChange", int.class).invoke(o, -1);
+ } catch (final Exception ignored) {
+ o.getClass().getMethod("clear").invoke(o);
+ }
+ } catch (final Exception e) {
+ Log.e(TAG, "Failed to flush drawable cache", e);
+ }
+
+ lastResources = resources;
+ lastDarkMode = darkMode;
+ }
+
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
+ super.onDestroy();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
+ if ("dark_theme".equals(key)) {
+ final boolean darkMode = sharedPreferences.getBoolean(key, false);
+ AppCompatDelegate.setDefaultNightMode(
+ sharedPreferences.getBoolean(key, false) ?
+ AppCompatDelegate.MODE_NIGHT_YES :
+ AppCompatDelegate.MODE_NIGHT_NO);
+ invalidateDrawableCache(getResources(), darkMode);
+ recreate();
+ }
+ }
+}
diff --git a/app/src/main/java/com/wireguard/android/util/Topic.java b/app/src/main/java/com/wireguard/android/util/Topic.java
deleted file mode 100644
index 6d8080cf..00000000
--- a/app/src/main/java/com/wireguard/android/util/Topic.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright © 2017 John Wu <topjohnwu@gmail.com>
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-package com.wireguard.android.util;
-
-import java.lang.ref.WeakReference;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-
-public class Topic {
-
- private static final int NON_INIT = 0;
- private static final int PENDING = 1;
- private static final int PUBLISHED = 2;
-
- private int state = NON_INIT;
- private List<WeakReference<Subscriber>> subscribers;
- private Object[] results;
-
- public Topic() {
- subscribers = new SyncArrayList<>();
- }
-
- public synchronized void subscribe(final Subscriber sub) {
- subscribers.add(new WeakReference<>(sub));
- }
-
- public synchronized void unsubscribe() {
- subscribers = new SyncArrayList<>();
- }
-
- public synchronized void unsubscribe(final Subscriber sub) {
- List<WeakReference<Subscriber>> subs = subscribers;
- subscribers = new ArrayList<>();
- for (final WeakReference<Subscriber> subscriber : subs) {
- if (subscriber.get() != null && subscriber.get() != sub)
- subscribers.add(subscriber);
- }
- }
-
- public void reset() {
- state = NON_INIT;
- results = null;
- }
-
- public boolean isPublished() {
- return state == PUBLISHED;
- }
-
- public void publish() {
- publish(true);
- }
-
- public void publish(boolean record, Object... results) {
- if (record)
- state = PUBLISHED;
- this.results = results;
- // Snapshot
- List<WeakReference<Subscriber>> subs = subscribers;
- for (final WeakReference<Subscriber> subscriber : subs) {
- if (subscriber != null && subscriber.get() != null)
- subscriber.get().onTopicPublished(this);
- }
- }
-
- public Object[] getResults() {
- return results;
- }
-
- public boolean isPending() {
- return state == PENDING;
- }
-
- public void setPending() {
- state = PENDING;
- }
-
- public interface Subscriber {
- default void subscribeTopics() {
- for (final Topic topic : getSubscription()) {
- if (topic.isPublished()) {
- onTopicPublished(topic);
- }
- topic.subscribe(this);
- }
- }
- default void unsubscribeTopics() {
- for (final Topic event : getSubscription()) {
- event.unsubscribe(this);
- }
- }
- void onTopicPublished(Topic topic);
- Topic[] getSubscription();
- }
-
- private static class SyncArrayList<E> extends ArrayList<E> {
- @Override
- public synchronized boolean add(final E e) {
- return super.add(e);
- }
- }
-}