Quellcode durchsuchen

DarkMode: move to shared preferences listener

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
master
Jason A. Donenfeld vor 6 Jahren
Ursprung
Commit
27072972ab
5 geänderte Dateien mit 79 neuen und 206 gelöschten Zeilen
  1. +0
    -10
      app/src/main/java/com/wireguard/android/Application.java
  2. +1
    -45
      app/src/main/java/com/wireguard/android/activity/BaseActivity.java
  3. +2
    -42
      app/src/main/java/com/wireguard/android/activity/SettingsActivity.java
  4. +76
    -0
      app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java
  5. +0
    -109
      app/src/main/java/com/wireguard/android/util/Topic.java

+ 0
- 10
app/src/main/java/com/wireguard/android/Application.java Datei anzeigen

@@ -23,7 +23,6 @@ import com.wireguard.android.model.TunnelManager;
import com.wireguard.android.util.AsyncWorker; import com.wireguard.android.util.AsyncWorker;
import com.wireguard.android.util.RootShell; import com.wireguard.android.util.RootShell;
import com.wireguard.android.util.ToolsInstaller; import com.wireguard.android.util.ToolsInstaller;
import com.wireguard.android.util.Topic;


import java.io.File; import java.io.File;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -68,8 +67,6 @@ public class Application extends android.app.Application {
ToolsInstaller getToolsInstaller(); ToolsInstaller getToolsInstaller();


TunnelManager getTunnelManager(); TunnelManager getTunnelManager();

Topic getThemeChangeTopic();
} }


@Qualifier @Qualifier
@@ -119,13 +116,6 @@ public class Application extends android.app.Application {
return new FileConfigStore(context); return new FileConfigStore(context);
} }


@ApplicationScope
@Provides
public static Topic getThemeChangeTopic() {
return new Topic();
}


@ApplicationScope @ApplicationScope
@Provides @Provides
public static Executor getExecutor() { public static Executor getExecutor() {


+ 1
- 45
app/src/main/java/com/wireguard/android/activity/BaseActivity.java Datei anzeigen

@@ -11,24 +11,19 @@ import android.databinding.CallbackRegistry;
import android.databinding.CallbackRegistry.NotifierCallback; import android.databinding.CallbackRegistry.NotifierCallback;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.util.Log;


import com.wireguard.android.Application; import com.wireguard.android.Application;
import com.wireguard.android.backend.GoBackend; import com.wireguard.android.backend.GoBackend;
import com.wireguard.android.model.Tunnel; import com.wireguard.android.model.Tunnel;
import com.wireguard.android.model.TunnelManager; import com.wireguard.android.model.TunnelManager;
import com.wireguard.android.util.Topic;


import java.lang.reflect.Field;
import java.util.Objects; import java.util.Objects;


/** /**
* Base class for activities that need to remember the currently-selected tunnel. * 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 static final String KEY_SELECTED_TUNNEL = "selected_tunnel";


private final SelectionChangeRegistry selectionChangeRegistry = new SelectionChangeRegistry(); private final SelectionChangeRegistry selectionChangeRegistry = new SelectionChangeRegistry();
@@ -45,8 +40,6 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Su


@Override @Override
protected void onCreate(final Bundle savedInstanceState) { protected void onCreate(final Bundle savedInstanceState) {
subscribeTopics();

// Restore the saved tunnel if there is one; otherwise grab it from the arguments. // Restore the saved tunnel if there is one; otherwise grab it from the arguments.
String savedTunnelName = null; String savedTunnelName = null;
if (savedInstanceState != null) if (savedInstanceState != null)
@@ -69,12 +62,6 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Su
} }
} }


@Override
protected void onDestroy() {
unsubscribeTopics();
super.onDestroy();
}

@Override @Override
protected void onSaveInstanceState(final Bundle outState) { protected void onSaveInstanceState(final Bundle outState) {
if (selectedTunnel != null) if (selectedTunnel != null)
@@ -118,35 +105,4 @@ public abstract class BaseActivity extends AppCompatActivity implements Topic.Su
super(new SelectionChangeNotifier()); 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() };
}
} }

+ 2
- 42
app/src/main/java/com/wireguard/android/activity/SettingsActivity.java Datei anzeigen

@@ -21,7 +21,6 @@ import android.view.MenuItem;
import com.wireguard.android.Application; import com.wireguard.android.Application;
import com.wireguard.android.R; import com.wireguard.android.R;
import com.wireguard.android.backend.WgQuickBackend; import com.wireguard.android.backend.WgQuickBackend;
import com.wireguard.android.util.Topic;


import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -33,7 +32,7 @@ import java.util.Map;
* Interface for changing application-global persistent settings. * 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 final Map<Integer, PermissionRequestCallback> permissionRequestCallbacks = new HashMap<>();
private int permissionRequestCounter; private int permissionRequestCounter;


@@ -59,7 +58,6 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
@Override @Override
protected void onCreate(final Bundle savedInstanceState) { protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
subscribeTopics();
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) { if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, new SettingsFragment()) .add(android.R.id.content, new SettingsFragment())
@@ -67,12 +65,6 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
} }
} }


@Override
protected void onDestroy() {
unsubscribeTopics();
super.onDestroy();
}

@Override @Override
public boolean onOptionsItemSelected(final MenuItem item) { public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
@@ -99,18 +91,7 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
void done(String[] permissions, int[] grantResults); 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 @Override
public void onCreatePreferences(final Bundle savedInstanceState, final String key) { public void onCreatePreferences(final Bundle savedInstanceState, final String key) {
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
@@ -121,26 +102,5 @@ public class SettingsActivity extends AppCompatActivity implements Topic.Subscri
getPreferenceScreen().removePreference(pref); 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);
}
}
} }
} }

+ 76
- 0
app/src/main/java/com/wireguard/android/activity/ThemeChangeAwareActivity.java Datei anzeigen

@@ -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();
}
}
}

+ 0
- 109
app/src/main/java/com/wireguard/android/util/Topic.java Datei anzeigen

@@ -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);
}
}
}

Laden…
Abbrechen
Speichern