Skip to content

Commit

Permalink
plusonelabs#28 Show, which Theme is being configured. Allow to switch…
Browse files Browse the repository at this point in the history
… "Dark theme" during changes of settings.
  • Loading branch information
yvolk committed Sep 18, 2020
1 parent 3f02fc2 commit 5c8567e
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import static org.andstatus.todoagenda.prefs.InstanceSettings.PREF_DAY_HEADER_ALIGNMENT;
import static org.andstatus.todoagenda.prefs.InstanceSettings.PREF_DAY_HEADER_DATE_FORMAT;
import static org.andstatus.todoagenda.prefs.InstanceSettings.PREF_DAY_HEADER_DATE_FORMAT_DEFAULT;
import static org.andstatus.todoagenda.prefs.InstanceSettings.PREF_DIFFERENT_COLORS_FOR_DARK;
import static org.andstatus.todoagenda.prefs.InstanceSettings.PREF_ENTRY_DATE_FORMAT;
import static org.andstatus.todoagenda.prefs.InstanceSettings.PREF_ENTRY_DATE_FORMAT_DEFAULT;
import static org.andstatus.todoagenda.prefs.InstanceSettings.PREF_EVENTS_ENDED;
Expand Down Expand Up @@ -75,6 +74,8 @@
import static org.andstatus.todoagenda.util.StringUtil.isEmpty;

public class ApplicationPreferences {
static final String PREF_DIFFERENT_COLORS_FOR_DARK = "differentColorsForDark";
private static final String PREF_COLOR_THEME_TYPE = "colorThemeType";

private ApplicationPreferences() {
// prohibit instantiation
Expand All @@ -91,10 +92,18 @@ public static void fromInstanceSettings(Context context, Integer widgetId) {
setEventsEnded(context, settings.getEventsEnded());
setFillAllDayEvents(context, settings.getFillAllDayEvents());
setHideBasedOnKeywords(context, settings.getHideBasedOnKeywords());
setInt(context, PREF_WIDGET_HEADER_BACKGROUND_COLOR, settings.colors().getWidgetHeaderBackgroundColor());
setInt(context, PREF_PAST_EVENTS_BACKGROUND_COLOR, settings.colors().getPastEventsBackgroundColor());
setInt(context, PREF_TODAYS_EVENTS_BACKGROUND_COLOR, settings.colors().getTodaysEventsBackgroundColor());
setInt(context, PREF_EVENTS_BACKGROUND_COLOR, settings.colors().getEventsBackgroundColor());

ThemeColors colors = settings.colors();
setString(context, PREF_COLOR_THEME_TYPE, colors.colorThemeType.value);
setBoolean(context, PREF_DIFFERENT_COLORS_FOR_DARK, colors.colorThemeType != ColorThemeType.SINGLE);
setInt(context, PREF_WIDGET_HEADER_BACKGROUND_COLOR, colors.getWidgetHeaderBackgroundColor());
setInt(context, PREF_PAST_EVENTS_BACKGROUND_COLOR, colors.getPastEventsBackgroundColor());
setInt(context, PREF_TODAYS_EVENTS_BACKGROUND_COLOR, colors.getTodaysEventsBackgroundColor());
setInt(context, PREF_EVENTS_BACKGROUND_COLOR, colors.getEventsBackgroundColor());
for (Map.Entry<TextShadingPref, TextShading> entry: colors.shadings.entrySet()) {
setString(context, entry.getKey().preferenceName, entry.getValue().name());
}

setShowDaysWithoutEvents(context, settings.getShowDaysWithoutEvents());
setShowDayHeaders(context, settings.getShowDayHeaders());
setDateFormat(context, PREF_DAY_HEADER_DATE_FORMAT, settings.getDayHeaderDateFormat());
Expand All @@ -119,9 +128,6 @@ public static void fromInstanceSettings(Context context, Integer widgetId) {
setString(context, PREF_FILTER_MODE, settings.getFilterMode().value);
setBoolean(context, PREF_INDICATE_ALERTS, settings.getIndicateAlerts());
setBoolean(context, PREF_INDICATE_RECURRING, settings.getIndicateRecurring());
for (Map.Entry<TextShadingPref, TextShading> entry: settings.colors().shadings.entrySet()) {
setString(context, entry.getKey().preferenceName, entry.getValue().name());
}
setBoolean(context, PREF_COMPACT_LAYOUT, settings.isCompactLayout());
setString(context, PREF_WIDGET_HEADER_LAYOUT, settings.getWidgetHeaderLayout().value);
setString(context, PREF_TEXT_SIZE_SCALE, settings.getTextSizeScale().preferenceValue);
Expand Down Expand Up @@ -202,6 +208,14 @@ public static boolean areDifferentColorsForDark(Context context) {
return getBoolean(context, PREF_DIFFERENT_COLORS_FOR_DARK, false);
}

static ColorThemeType getEditingColorThemeType(Context context) {
return getColorThemeType(context).fromEditor(context, areDifferentColorsForDark(context));
}

public static ColorThemeType getColorThemeType(Context context) {
return ColorThemeType.fromValue(getString(context, PREF_COLOR_THEME_TYPE, ""));
}

public static int getWidgetHeaderBackgroundColor(Context context) {
return getInt(context, PREF_WIDGET_HEADER_BACKGROUND_COLOR,
PREF_WIDGET_HEADER_BACKGROUND_COLOR_DEFAULT);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.andstatus.todoagenda.prefs;

import android.app.Activity;
import android.content.Context;
import android.os.Build;

import androidx.annotation.StringRes;

import org.andstatus.todoagenda.R;

import static org.andstatus.todoagenda.prefs.InstanceSettings.isDarkThemeOn;

/**
* See https://github.com/andstatus/todoagenda/issues/48
* @author [email protected]
*/
public enum ColorThemeType {
SINGLE("single", R.string.appearance_group_color_title),
DARK("dark", R.string.colors_dark),
LIGHT("light", R.string.colors_light),
NONE("none", R.string.no_title);

private final static ColorThemeType defaultValue = SINGLE;

public final String value;
@StringRes
public final int titleResId;

ColorThemeType(String value, int titleResId) {
this.value = value;
this.titleResId = titleResId;
}

public boolean isValid() {
return this != NONE;
}

public static ColorThemeType fromValue(String value) {
for (ColorThemeType item : ColorThemeType.values()) {
if (item.value.equals(value)) {
return item;
}
}
return defaultValue;
}

/** See https://developer.android.com/guide/topics/ui/look-and-feel/darktheme */
public static boolean canHaveDifferentColorsForDark() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
}

public ColorThemeType fromEditor(Context context, boolean differentColorsForDark) {
if (differentColorsForDark && canHaveDifferentColorsForDark()) {
if (this == ColorThemeType.DARK || this == ColorThemeType.SINGLE && isDarkThemeOn(context)) {
return ColorThemeType.DARK;
} else {
return ColorThemeType.LIGHT;
}
} else {
if (this == ColorThemeType.LIGHT || this == ColorThemeType.SINGLE) {
return ColorThemeType.SINGLE;
} else {
return ColorThemeType.NONE;
}
}
}

public ColorThemeType setTitle(Activity activity) {
if (activity != null) {
activity.setTitle(titleResId);
}
return this;
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.andstatus.todoagenda.prefs;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;

import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
Expand All @@ -12,11 +14,13 @@
import com.rarepebble.colorpicker.ColorPreference;
import com.rarepebble.colorpicker.ColorPreferenceDialog;

import org.andstatus.todoagenda.MainActivity;
import org.andstatus.todoagenda.R;
import org.andstatus.todoagenda.TextShading;
import org.andstatus.todoagenda.widget.TimeSection;

import static org.andstatus.todoagenda.WidgetConfigurationActivity.FRAGMENT_TAG;
import static org.andstatus.todoagenda.prefs.ApplicationPreferences.PREF_DIFFERENT_COLORS_FOR_DARK;

/** AndroidX version created by [email protected]
* based on this answer: https://stackoverflow.com/a/53290775/297710
Expand All @@ -27,27 +31,39 @@ public class ColorsPreferencesFragment extends PreferenceFragmentCompat

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setTitle();
addPreferencesFromResource(R.xml.preferences_colors);
removeUnavailablePreferences();
}

private void setTitle() {
ApplicationPreferences.getEditingColorThemeType(getActivity()).setTitle(getActivity());
}

@Override
public void onResume() {
super.onResume();
setTitle();
removeUnavailablePreferences();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
showShadings();
}

private void removeUnavailablePreferences() {
if (!InstanceSettings.canHaveDifferentColorsForDark()) {
Context context = getActivity();
if (context == null) return;

ColorThemeType colorThemeType = ApplicationPreferences.getColorThemeType(context);
if (!ColorThemeType.canHaveDifferentColorsForDark() ||
colorThemeType == ColorThemeType.LIGHT ||
colorThemeType == ColorThemeType.SINGLE && !InstanceSettings.isDarkThemeOn(context)) {
PreferenceScreen screen = getPreferenceScreen();
Preference preference = findPreference(InstanceSettings.PREF_DIFFERENT_COLORS_FOR_DARK);
Preference preference = findPreference(PREF_DIFFERENT_COLORS_FOR_DARK);
if (screen != null && preference != null) {
screen.removePreference(preference);
}
}
if (ApplicationPreferences.noPastEvents(getActivity())) {
if (ApplicationPreferences.noPastEvents(context)) {
PreferenceScreen screen = getPreferenceScreen();
Preference preference = findPreference(TimeSection.PAST.preferenceCategoryKey);
if (screen != null && preference != null) {
Expand All @@ -70,6 +86,17 @@ public void onPause() {

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (PREF_DIFFERENT_COLORS_FOR_DARK.equals(key)){
FragmentActivity activity = getActivity();
if (activity != null) {
if (ApplicationPreferences.getEditingColorThemeType(activity) == ColorThemeType.NONE) {
activity.startActivity(MainActivity.intentToConfigure(activity, ApplicationPreferences.getWidgetId(activity)));
activity.finish();
return;
};
setTitle();
}
}
showShadings();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;
Expand Down Expand Up @@ -87,9 +86,7 @@ public class InstanceSettings {

// ----------------------------------------------------------------------------------
// Colors
static final String PREF_DIFFERENT_COLORS_FOR_DARK = "differentColorsForDark";
private ThemeColors defaultColors;
private boolean differentColorsForDark = false;
static final String PREF_DARK_THEME = "darkTheme";
private ThemeColors darkColors = ThemeColors.EMPTY;

Expand Down Expand Up @@ -207,11 +204,12 @@ private InstanceSettings setFromJson(JSONObject json) {
hideBasedOnKeywords = json.getString(PREF_HIDE_BASED_ON_KEYWORDS);
}

defaultColors = ThemeColors.fromJson(context, json);
differentColorsForDark = canHaveDifferentColorsForDark() && json.has(PREF_DARK_THEME);
if (differentColorsForDark) {
darkColors = ThemeColors.fromJson(context, json.getJSONObject(PREF_DARK_THEME));
}
boolean differentColorsForDark = ColorThemeType.canHaveDifferentColorsForDark() && json.has(PREF_DARK_THEME);
defaultColors = ThemeColors.fromJson(context,
differentColorsForDark ? ColorThemeType.LIGHT : ColorThemeType.SINGLE, json);
darkColors = differentColorsForDark
? ThemeColors.fromJson(context, ColorThemeType.DARK, json.getJSONObject(PREF_DARK_THEME))
: ThemeColors.EMPTY;

if (json.has(PREF_SHOW_DAYS_WITHOUT_EVENTS)) {
showDaysWithoutEvents = json.getBoolean(PREF_SHOW_DAYS_WITHOUT_EVENTS);
Expand Down Expand Up @@ -334,18 +332,25 @@ private InstanceSettings setFromApplicationPreferences(InstanceSettings settings
fillAllDayEvents = ApplicationPreferences.getFillAllDayEvents(context);
hideBasedOnKeywords = ApplicationPreferences.getHideBasedOnKeywords(context);

differentColorsForDark = canHaveDifferentColorsForDark() && ApplicationPreferences.areDifferentColorsForDark(context);
if (differentColorsForDark) {
if (isDarkThemeCurrent()) {
defaultColors = settingsStored.defaultColors;
darkColors = new ThemeColors(context).setFromApplicationPreferences();
} else {
defaultColors = new ThemeColors(context).setFromApplicationPreferences();
darkColors = settingsStored.darkColors;
}
} else {
defaultColors = new ThemeColors(context).setFromApplicationPreferences();
darkColors = ThemeColors.EMPTY;
switch (ApplicationPreferences.getEditingColorThemeType(context)) {
case DARK:
darkColors = new ThemeColors(context, ColorThemeType.DARK).setFromApplicationPreferences();
defaultColors = settingsStored.defaultColors.copy(context, ColorThemeType.LIGHT);
break;
case LIGHT:
darkColors = settingsStored.darkColors.isEmpty()
? settingsStored.defaultColors.copy(context, ColorThemeType.DARK)
: settingsStored.darkColors.copy(context, ColorThemeType.DARK);
defaultColors = new ThemeColors(context, ColorThemeType.LIGHT).setFromApplicationPreferences();
break;
case SINGLE:
darkColors = ThemeColors.EMPTY;
defaultColors = new ThemeColors(context, ColorThemeType.SINGLE).setFromApplicationPreferences();
break;
case NONE:
darkColors = ThemeColors.EMPTY;
defaultColors = settingsStored.defaultColors.copy(context, ColorThemeType.SINGLE);
break;
}

showDaysWithoutEvents = ApplicationPreferences.getShowDaysWithoutEvents(context);
Expand Down Expand Up @@ -396,7 +401,7 @@ public InstanceSettings(Context context, int widgetId, String proposedInstanceNa
this.context = context;
this.widgetId = widgetId;
widgetInstanceName = AllSettings.uniqueInstanceName(context, widgetId, proposedInstanceName);
defaultColors = new ThemeColors(context);
defaultColors = context == null ? ThemeColors.EMPTY : new ThemeColors(context, ColorThemeType.SINGLE);
}

public boolean isEmpty() {
Expand Down Expand Up @@ -433,7 +438,7 @@ public JSONObject toJson() {
json.put(PREF_HIDE_BASED_ON_KEYWORDS, hideBasedOnKeywords);

defaultColors.toJson(json);
if (differentColorsForDark) {
if (!darkColors.isEmpty()) {
json.put(PREF_DARK_THEME, darkColors.toJson(new JSONObject()));
}

Expand Down Expand Up @@ -532,19 +537,12 @@ public String getHideBasedOnKeywords() {
}

public ThemeColors colors() {
return isDarkThemeCurrent() && darkColors != ThemeColors.EMPTY
return !darkColors.isEmpty() && isDarkThemeOn(context)
? darkColors
: defaultColors;
}

/** See https://developer.android.com/guide/topics/ui/look-and-feel/darktheme */
public static boolean canHaveDifferentColorsForDark() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
}

private boolean isDarkThemeCurrent() {
if (!differentColorsForDark) return false;

public static boolean isDarkThemeOn(Context context) {
Configuration configuration = context.getApplicationContext().getResources().getConfiguration();
int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
return currentNightMode == Configuration.UI_MODE_NIGHT_YES;
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/org/andstatus/todoagenda/prefs/RootFragment.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.andstatus.todoagenda.prefs;

import android.content.Context;
import android.os.Bundle;

import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;

import org.andstatus.todoagenda.R;
Expand All @@ -15,10 +17,22 @@ public void onResume() {
super.onResume();
Optional.ofNullable(getActivity())
.ifPresent(a -> a.setTitle(ApplicationPreferences.getWidgetInstanceName(a)));
setTitles();
}

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_root);
setTitles();
}

private void setTitles() {
Context context = getContext();
Preference preference = findPreference("ColorsPreferencesFragment");
if (context != null && preference != null) {
ColorThemeType themeType = ApplicationPreferences.getEditingColorThemeType(context);
preference.setTitle(themeType.titleResId);
preference.setVisible(themeType.isValid());
}
}
}
Loading

0 comments on commit 5c8567e

Please sign in to comment.