Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/main/java/com/nextcloud/client/preferences/AppPreferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,42 @@
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.utils.FileSortOrder;

import androidx.annotation.Nullable;

/**
* This interface provides single point of entry for access to all application
* preferences and allows clients to subscribe for specific configuration
* changes.
*/
public interface AppPreferences {

/**
* Preferences listener. Callbacks should be invoked on main thread.
*
* Miantainers should extend this interface with callbacks for specific
* events.
*/
interface Listener {
default void onDarkThemeEnabledChanged(boolean enabled) {
/* default empty implementation */
};
}

/**
* Registers preferences listener. It no-ops if listener
* is already registered.
*
* @param listener application preferences listener
*/
void addListener(@Nullable Listener listener);

/**
* Unregister listener. It no-ops if listener is not registered.
*
* @param listener application preferences listener
*/
void removeListener(@Nullable Listener listener);

void setKeysReInitEnabled();
boolean isKeysReInitEnabled();

Expand Down Expand Up @@ -239,6 +273,18 @@ public interface AppPreferences {
*/
int getUploaderBehaviour();

/**
* Enable dark theme.
*
* This is reactive property. Listeners will be invoked if registered.
*
* @param enabled true to turn dark theme on, false to turn it off
*/
void setDarkThemeEnabled(boolean enabled);

/**
* @return true if application uses dark UI theme, false otherwise
*/
boolean isDarkThemeEnabled();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,29 @@
import com.owncloud.android.ui.activity.SettingsActivity;
import com.owncloud.android.utils.FileSortOrder;

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import androidx.annotation.Nullable;

import static com.owncloud.android.ui.fragment.OCFileListFragment.FOLDER_LAYOUT_LIST;

/**
* Helper to simplify reading of Preferences all around the app
* Implementation of application-wide preferences using {@link SharedPreferences}.
*
* Users should not use this class directly. Please use {@link AppPreferences} interafce
* instead.
*/
public final class AppPreferencesImpl implements AppPreferences {

/**
* Constant to access value of last path selected by the user to upload a file shared from other app.
* Value handled by the app without direct access in the UI.
*/
public static final String AUTO_PREF__LAST_SEEN_VERSION_CODE = "lastSeenVersionCode";
public static final String STORAGE_PATH = "storage_path";
public static final float DEFAULT_GRID_COLUMN = 4.0f;

private static final String AUTO_PREF__LAST_UPLOAD_PATH = "last_upload_path";
private static final String AUTO_PREF__UPLOAD_FROM_LOCAL_LAST_PATH = "upload_from_local_last_path";
private static final String AUTO_PREF__UPLOAD_FILE_EXTENSION_MAP_URL = "prefs_upload_file_extension_map_url";
Expand All @@ -68,7 +78,7 @@ public final class AppPreferencesImpl implements AppPreferences {
private static final String PREF__AUTO_UPLOAD_INIT = "autoUploadInit";
private static final String PREF__FOLDER_SORT_ORDER = "folder_sort_order";
private static final String PREF__FOLDER_LAYOUT = "folder_layout";
public static final String PREF__THEME = "darkTheme";
static final String PREF__DARK_THEME_ENABLED = "dark_theme_enabled";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will likely chance when @tobiasKaminsky pushes his PR to the repo adding a 3rd option for the theme values (dark, light, system)

Copy link
Collaborator Author

@ezaquarii ezaquarii Nov 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be interesting. I wild guess that the change will be based on the SharedPreferences code that I just removed and the preference will become some kind of enum instead of boolean?

I'm fine with resolving conflicts on my side, let's just make sure we don't have to do a complete rewrite. (-:

Is there any public branch I could potentially try?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any public branch I could potentially try?

Don't know, I just saw this earlier this evening, which is why I mentioned @tobiasKaminsky here --> #4757 (comment)


private static final String PREF__LOCK_TIMESTAMP = "lock_timestamp";
private static final String PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS = "show_media_scan_notifications";
Expand All @@ -81,7 +91,54 @@ public final class AppPreferencesImpl implements AppPreferences {
private final Context context;
private final SharedPreferences preferences;
private final CurrentAccountProvider currentAccountProvider;
private final ListenerRegistry listeners;

/**
* Adapter delegating raw {@link SharedPreferences.OnSharedPreferenceChangeListener} calls
* with key-value pairs to respective {@link com.nextcloud.client.preferences.AppPreferences.Listener} method.
*/
static class ListenerRegistry implements SharedPreferences.OnSharedPreferenceChangeListener {
private final AppPreferences preferences;
private final Set<Listener> listeners;

ListenerRegistry(AppPreferences preferences) {
this.preferences = preferences;
this.listeners = new CopyOnWriteArraySet<>();
}

void add(@Nullable final Listener listener) {
if (listener != null) {
listeners.add(listener);
}
}

void remove(@Nullable final Listener listener) {
if (listener != null) {
listeners.remove(listener);
}
}

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(PREF__DARK_THEME_ENABLED.equals(key)) {
boolean enabled = preferences.isDarkThemeEnabled();
for(Listener l : listeners) {
l.onDarkThemeEnabledChanged(enabled);
}
}
}
}

/**
* This is a temporary workaround to access app preferences in places that cannot use
* dependency injection yet. Use injected component via {@link AppPreferences} interface.
*
* WARNING: this creates new instance! it does not return app-wide singleton
*
* @param context Context used to create shared preferences
* @return New instance of app preferences component
*/
@Deprecated
public static AppPreferences fromContext(Context context) {
final CurrentAccountProvider currentAccountProvider = UserAccountManagerImpl.fromContext(context);
final SharedPreferences prefs = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
Expand All @@ -92,6 +149,18 @@ public static AppPreferences fromContext(Context context) {
this.context = appContext;
this.preferences = preferences;
this.currentAccountProvider = currentAccountProvider;
this.listeners = new ListenerRegistry(this);
this.preferences.registerOnSharedPreferenceChangeListener(listeners);
}

@Override
public void addListener(@Nullable AppPreferences.Listener listener) {
this.listeners.add(listener);
}

@Override
public void removeListener(@Nullable AppPreferences.Listener listener) {
this.listeners.remove(listener);
}

@Override
Expand Down Expand Up @@ -342,9 +411,14 @@ public int getUploaderBehaviour() {
return preferences.getInt(AUTO_PREF__UPLOADER_BEHAVIOR, 1);
}

@Override
public void setDarkThemeEnabled(boolean enabled) {
preferences.edit().putBoolean(PREF__DARK_THEME_ENABLED, enabled).apply();
}

@Override
public boolean isDarkThemeEnabled() {
return preferences.getBoolean(PREF__THEME, false);
return preferences.getBoolean(PREF__DARK_THEME_ENABLED, false);
}

@Override
Expand Down
29 changes: 15 additions & 14 deletions src/main/java/com/owncloud/android/ui/activity/BaseActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
Expand All @@ -28,9 +29,7 @@
/**
* Base activity with common behaviour for activities dealing with ownCloud {@link Account}s .
*/
public abstract class BaseActivity
extends AppCompatActivity
implements Injectable, SharedPreferences.OnSharedPreferenceChangeListener {
public abstract class BaseActivity extends AppCompatActivity implements Injectable {

private static final String TAG = BaseActivity.class.getSimpleName();

Expand All @@ -56,7 +55,14 @@ public abstract class BaseActivity
private boolean paused;

@Inject UserAccountManager accountManager;
@Inject SharedPreferences sharedPreferences;
@Inject AppPreferences preferences;

private AppPreferences.Listener onPreferencesChanged = new AppPreferences.Listener() {
@Override
public void onDarkThemeEnabledChanged(boolean enabled) {
BaseActivity.this.onThemeSettingsChanged();
}
};

public UserAccountManager getUserAccountManager() {
return accountManager;
Expand All @@ -65,13 +71,13 @@ public UserAccountManager getUserAccountManager() {
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
preferences.addListener(onPreferencesChanged);
}

@Override
protected void onDestroy() {
super.onDestroy();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
preferences.removeListener(onPreferencesChanged);
}

@Override
Expand Down Expand Up @@ -122,17 +128,12 @@ protected void onRestart() {
Log_OC.v(TAG, "onRestart() end");
}

@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if (!AppPreferencesImpl.PREF__THEME.equals(key)) {
return;
}

private void onThemeSettingsChanged() {
if(paused) {
themeChangePending = true;
return;
} else {
recreate();
}
recreate();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -692,13 +692,13 @@ private void setupGeneralCategory(int accentColor) {

loadStoragePath();

SwitchPreference themePref = (SwitchPreference) findPreference(AppPreferencesImpl.PREF__THEME);

themePref.setSummary(preferences.isDarkThemeEnabled() ?
getString(R.string.prefs_value_theme_dark) : getString(R.string.prefs_value_theme_light));
SwitchPreference themePref = (SwitchPreference) findPreference("dark_theme_enabled");
boolean darkThemeEnabled = preferences.isDarkThemeEnabled();
int summaryResId = darkThemeEnabled ? R.string.prefs_value_theme_dark : R.string.prefs_value_theme_light;
themePref.setSummary(summaryResId);
themePref.setOnPreferenceChangeListener((preference, newValue) -> {
MainApp.setAppTheme((Boolean) newValue);

boolean enabled = (Boolean)newValue;
MainApp.setAppTheme(enabled);
return true;
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,46 @@

package com.owncloud.android.ui.activity;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;

import com.nextcloud.client.preferences.AppPreferences;

import javax.inject.Inject;

import androidx.annotation.Nullable;

public class ThemedPreferenceActivity
extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
public class ThemedPreferenceActivity extends PreferenceActivity {

/**
* Tracks whether the activity should be recreate()'d after a theme change
*/
private boolean themeChangePending;
private boolean paused;

@Inject SharedPreferences sharedPreferences;
@Inject AppPreferences preferences;

private AppPreferences.Listener onThemeChangedListener = new AppPreferences.Listener() {
@Override
public void onDarkThemeEnabledChanged(boolean enabled) {
if(paused) {
themeChangePending = true;
return;
}
recreate();
}
};

@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
preferences.addListener(onThemeChangedListener);
}

@Override
protected void onDestroy() {
super.onDestroy();
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
preferences.removeListener(onThemeChangedListener);
}

@Override
Expand All @@ -67,14 +77,4 @@ protected void onResume() {
recreate();
}
}

@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if(paused) {
themeChangePending = true;
return;
}

recreate();
}
}
3 changes: 2 additions & 1 deletion src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
android:title="@string/prefs_storage_path"
android:key="storage_path"/>
<com.owncloud.android.ui.ThemeableSwitchPreference
android:id="@+id/dark_theme_preference"
android:defaultValue="@string/prefs_value_theme_light"
android:key="darkTheme"
android:key="dark_theme_enabled"
android:summary="%s"
android:title="@string/prefs_theme_title"
android:theme="@style/SwitchPreference"/>
Expand Down
Loading