Add basic implementation to support "System default" in dark mode settings

This commit is contained in:
Christoph Loy 2020-02-24 21:37:51 +01:00
parent 8f7ab6d824
commit 79e630b999
No known key found for this signature in database
GPG key ID: 9179970615A6E7C9
13 changed files with 132 additions and 25 deletions

View file

@ -0,0 +1,64 @@
package it.niedermann.owncloud.notes.android;
import androidx.appcompat.app.AppCompatDelegate;
import java.util.NoSuchElementException;
/**
* Possible values of the Dark Mode Setting.
* <p>
* The Dark Mode Setting can be stored in {@link android.content.SharedPreferences} as String by using {@link DarkModeSetting#name()} and received via {@link DarkModeSetting#valueOf(String)}.
* <p>
* Additionally, the equivalent {@link AppCompatDelegate}-Mode can be received via {@link #getModeId()}. To convert a {@link AppCompatDelegate}-Mode to a {@link DarkModeSetting}, use {@link #fromModeID(int)}
*
* @see AppCompatDelegate#MODE_NIGHT_YES
* @see AppCompatDelegate#MODE_NIGHT_NO
* @see AppCompatDelegate#MODE_NIGHT_FOLLOW_SYSTEM
*/
public enum DarkModeSetting {
/**
* Always use light mode.
*/
LIGHT(AppCompatDelegate.MODE_NIGHT_NO),
/**
* Always use dark mode.
*/
DARK(AppCompatDelegate.MODE_NIGHT_YES),
/**
* Follow the global system setting for dark mode.
*/
SYSTEM_DEFAULT(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
private final int modeId;
DarkModeSetting(int modeId) {
this.modeId = modeId;
}
public int getModeId() {
return modeId;
}
/**
* Returns the instance of {@link DarkModeSetting} that corresponds to the ModeID of {@link AppCompatDelegate}
* <p>
* Possible ModeIDs are:
* <ul>
* <li>{@link AppCompatDelegate#MODE_NIGHT_YES}</li>
* <li>{@link AppCompatDelegate#MODE_NIGHT_NO}</li>
* <li>{@link AppCompatDelegate#MODE_NIGHT_FOLLOW_SYSTEM}</li>
* </ul>
*
* @param id One of the {@link AppCompatDelegate}-Night-Modes
* @return An instance of {@link DarkModeSetting}
*/
public static DarkModeSetting fromModeID(int id) {
for (DarkModeSetting value : DarkModeSetting.values()) {
if (value.modeId == id) {
return value;
}
}
throw new NoSuchElementException("No NightMode with ID " + id + " found");
}
}

View file

@ -59,7 +59,7 @@ public class SelectSingleNoteActivity extends NotesListViewActivity {
sp.putLong(SingleNoteWidget.WIDGET_KEY + appWidgetId, noteID);
sp.putLong(SingleNoteWidget.ACCOUNT_ID_KEY + appWidgetId, note.getAccountId());
sp.putBoolean(SingleNoteWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext()));
sp.putString(SingleNoteWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext()).name());
sp.apply();
Intent updateIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null,

View file

@ -13,8 +13,10 @@ import android.util.Log;
import android.widget.RemoteViews;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.DarkModeSetting;
import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.android.activity.NotesListViewActivity;
import it.niedermann.owncloud.notes.util.Notes;
public class NoteListWidget extends AppWidgetProvider {
private static final String TAG = NoteListWidget.class.getSimpleName();
@ -28,7 +30,7 @@ public class NoteListWidget extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds) {
RemoteViews views;
boolean darkTheme;
String darkTheme;
for (int appWidgetId : appWidgetIds) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
@ -40,7 +42,7 @@ public class NoteListWidget extends AppWidgetProvider {
}
String category = sp.getString(NoteListWidget.WIDGET_CATEGORY_KEY + appWidgetId, null);
darkTheme = sp.getBoolean(NoteListWidget.DARK_THEME_KEY + appWidgetId, false);
darkTheme = sp.getString(NoteListWidget.DARK_THEME_KEY + appWidgetId, DarkModeSetting.SYSTEM_DEFAULT.name());
Intent serviceIntent = new Intent(context, NoteListWidgetService.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
@ -70,7 +72,7 @@ public class NoteListWidget extends AppWidgetProvider {
(new Intent(context, EditNoteActivity.class)),
PendingIntent.FLAG_UPDATE_CURRENT);
if (darkTheme) {
if (Notes.isDarkThemeActive(context, DarkModeSetting.valueOf(darkTheme))) {
views = new RemoteViews(context.getPackageName(), R.layout.widget_note_list_dark);
views.setTextViewText(R.id.widget_note_list_title_tv_dark, getWidgetTitle(context, displayMode, category));
views.setOnClickPendingIntent(R.id.widget_note_header_icon_dark, openAppI);

View file

@ -100,7 +100,7 @@ public class NoteListWidgetConfiguration extends AppCompatActivity {
}
sp.putLong(NoteListWidget.ACCOUNT_ID_KEY + appWidgetId, localAccount.getId());
sp.putBoolean(NoteListWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext()));
sp.putString(NoteListWidget.DARK_THEME_KEY + appWidgetId, Notes.getAppTheme(getApplicationContext()).name());
sp.apply();
Intent updateIntent = new Intent( AppWidgetManager.ACTION_APPWIDGET_UPDATE, null,

View file

@ -13,9 +13,11 @@ import android.widget.RemoteViewsService;
import java.util.List;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.DarkModeSetting;
import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.util.Notes;
public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFactory {
private final Context context;
@ -32,7 +34,9 @@ public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFact
AppWidgetManager.INVALID_APPWIDGET_ID);
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this.context);
displayMode = sp.getInt(NoteListWidget.WIDGET_MODE_KEY + appWidgetId, -1);
darkTheme = sp.getBoolean(NoteListWidget.DARK_THEME_KEY + appWidgetId, false);
String themeName = sp.getString(NoteListWidget.DARK_THEME_KEY + appWidgetId, DarkModeSetting.SYSTEM_DEFAULT.name());
DarkModeSetting theme = DarkModeSetting.valueOf(themeName);
darkTheme = Notes.isDarkThemeActive(context, theme);
category = sp.getString(NoteListWidget.WIDGET_CATEGORY_KEY + appWidgetId, "");
accountId = sp.getLong(NoteListWidget.ACCOUNT_ID_KEY + appWidgetId, -1);
}

View file

@ -12,8 +12,10 @@ import android.preference.PreferenceManager;
import android.widget.RemoteViews;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.DarkModeSetting;
import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.android.fragment.BaseNoteFragment;
import it.niedermann.owncloud.notes.util.Notes;
public class SingleNoteWidget extends AppWidgetProvider {
@ -32,7 +34,8 @@ public class SingleNoteWidget extends AppWidgetProvider {
return;
}
boolean darkTheme = sp.getBoolean(DARK_THEME_KEY + appWidgetId, false);
String darkThemeName = sp.getString(DARK_THEME_KEY + appWidgetId, DarkModeSetting.SYSTEM_DEFAULT.name());
DarkModeSetting darkTheme = DarkModeSetting.valueOf(darkThemeName);
templateIntent.putExtra(BaseNoteFragment.PARAM_ACCOUNT_ID, sp.getLong(ACCOUNT_ID_KEY + appWidgetId, -1));
PendingIntent templatePendingIntent = PendingIntent.getActivity(context, appWidgetId, templateIntent,
@ -44,7 +47,7 @@ public class SingleNoteWidget extends AppWidgetProvider {
RemoteViews views;
if (darkTheme) {
if (Notes.isDarkThemeActive(context, darkTheme)) {
views = new RemoteViews(context.getPackageName(), R.layout.widget_single_note_dark);
views.setPendingIntentTemplate(R.id.single_note_widget_lv_dark, templatePendingIntent);
views.setRemoteAdapter(R.id.single_note_widget_lv_dark, serviceIntent);

View file

@ -14,10 +14,12 @@ import com.yydcdut.markdown.MarkdownProcessor;
import com.yydcdut.markdown.syntax.text.TextFactory;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.DarkModeSetting;
import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
import it.niedermann.owncloud.notes.util.MarkDownUtil;
import it.niedermann.owncloud.notes.util.Notes;
public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFactory {
@ -28,7 +30,7 @@ public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFa
private NoteSQLiteOpenHelper db;
private DBNote note;
private final SharedPreferences sp;
private static Boolean darkTheme;
private static boolean darkModeActive;
private static final String TAG = SingleNoteWidget.class.getSimpleName();
@ -37,10 +39,11 @@ public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFa
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
sp = PreferenceManager.getDefaultSharedPreferences(this.context);
darkTheme = sp.getBoolean(SingleNoteWidget.DARK_THEME_KEY + appWidgetId, false);
String themeName = sp.getString(SingleNoteWidget.DARK_THEME_KEY + appWidgetId, DarkModeSetting.SYSTEM_DEFAULT.name());
darkModeActive = Notes.isDarkThemeActive(context, DarkModeSetting.valueOf(themeName));
markdownProcessor = new MarkdownProcessor(this.context);
markdownProcessor.factory(TextFactory.create());
markdownProcessor.config(MarkDownUtil.getMarkDownConfiguration(this.context, darkTheme).build());
markdownProcessor.config(MarkDownUtil.getMarkDownConfiguration(this.context, darkModeActive).build());
}
@Override
@ -101,7 +104,7 @@ public class SingleNoteWidgetFactory implements RemoteViewsService.RemoteViewsFa
extras.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, note.getAccountId());
fillInIntent.putExtras(extras);
fillInIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
if (darkTheme) {
if (darkModeActive) {
note_content = new RemoteViews(context.getPackageName(), R.layout.widget_single_note_content_dark);
note_content.setOnClickFillInIntent(R.id.single_note_content_tv_dark, fillInIntent);
note_content.setTextViewText(R.id.single_note_content_tv_dark, markdownProcessor.parse(note.getContent()));

View file

@ -10,6 +10,7 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.DarkModeSetting;
import it.niedermann.owncloud.notes.persistence.SyncWorker;
import it.niedermann.owncloud.notes.util.Notes;
@ -26,10 +27,10 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences);
final SwitchPreference themePref = findPreference(getString(R.string.pref_key_theme));
final ListPreference themePref = findPreference(getString(R.string.pref_key_theme));
assert themePref != null;
themePref.setOnPreferenceChangeListener((preference, newValue) -> {
Notes.setAppTheme((Boolean) newValue);
Notes.setAppTheme(DarkModeSetting.valueOf((String) newValue));
getActivity().setResult(Activity.RESULT_OK);
getActivity().recreate();
return true;

View file

@ -36,7 +36,7 @@ public class MarkDownUtil {
* @return RxMDConfiguration
*/
public static Builder getMarkDownConfiguration(Context context) {
return getMarkDownConfiguration(context, Notes.getAppTheme(context));
return getMarkDownConfiguration(context, Notes.isDarkThemeActive(context));
}
public static Builder getMarkDownConfiguration(Context context, Boolean darkTheme) {

View file

@ -3,9 +3,13 @@ package it.niedermann.owncloud.notes.util;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.preference.PreferenceManager;
import androidx.appcompat.app.AppCompatDelegate;
import it.niedermann.owncloud.notes.android.DarkModeSetting;
public class Notes extends Application {
private static final String DARK_THEME = "darkTheme";
@ -15,16 +19,26 @@ public class Notes extends Application {
super.onCreate();
}
public static void setAppTheme(Boolean darkTheme) {
if (darkTheme) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
public static void setAppTheme(DarkModeSetting setting) {
AppCompatDelegate.setDefaultNightMode(setting.getModeId());
}
public static DarkModeSetting getAppTheme(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String mode = prefs.getString(DARK_THEME, DarkModeSetting.SYSTEM_DEFAULT.name());
return DarkModeSetting.valueOf(mode);
}
public static boolean isDarkThemeActive(Context context, DarkModeSetting setting) {
if (setting == DarkModeSetting.SYSTEM_DEFAULT) {
return isDarkThemeActive(context);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
return setting == DarkModeSetting.DARK;
}
}
public static boolean getAppTheme(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(DARK_THEME, false);
public static boolean isDarkThemeActive(Context context) {
int uiMode = context.getResources().getConfiguration().uiMode;
return (uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
}
}

View file

@ -10,6 +10,11 @@
<item>@string/pref_value_font_size_medium</item>
<item>@string/pref_value_font_size_large</item>
</string-array>
<string-array name="darkMode_values">
<item>@string/pref_value_theme_light</item>
<item>@string/pref_value_theme_dark</item>
<item>@string/pref_value_theme_system_default</item>
</string-array>
<string-array name="sync_values">
<item>@string/pref_value_sync_off</item>
<item>@string/pref_value_sync_15_minutes</item>

View file

@ -125,8 +125,10 @@
<string name="pref_value_sync_15_minutes" translatable="false">15_minutes</string>
<string name="pref_value_sync_1_hour" translatable="false">1_hour</string>
<string name="pref_value_sync_6_hours" translatable="false">6_hours</string>
<string name="pref_value_theme_light" translatable="false">LIGHT</string>
<string name="pref_value_theme_dark" translatable="false">DARK</string>
<string name="pref_value_theme_system_default" translatable="false">SYSTEM_DEFAULT</string>
<!-- These values should not be translateable. They should be migrated at some point. -->
<string name="pref_value_theme_light">Light</string>
<string name="pref_value_font_normal">Normal</string>
<string name="pref_value_wifi_and_mobile">Sync on Wi-Fi and mobile data</string>
@ -179,6 +181,12 @@
<item>6 hours</item>
</string-array>
<string-array name="darkmode_entries">
<item>Light</item>
<item>Dark</item>
<item>System Default</item>
</string-array>
<!-- Plurals -->
<plurals name="ab_selected">
<item quantity="one">%d selected</item>

View file

@ -11,8 +11,11 @@
android:summary="%s"
android:title="@string/settings_note_mode" />
<SwitchPreference
android:defaultValue="@string/pref_value_theme_light"
<ListPreference
android:defaultValue="@string/pref_value_theme_system_default"
android:entries="@array/darkmode_entries"
android:entryValues="@array/darkMode_values"
android:summary="%s"
android:icon="@drawable/ic_brightness_2_grey_24dp"
android:key="@string/pref_key_theme"
android:layout="@layout/item_pref"