diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java index 909b7a5a2..b790bc005 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java @@ -3,14 +3,22 @@ package de.test.antennapod.ui; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; - import androidx.annotation.StringRes; import androidx.preference.PreferenceManager; import androidx.test.espresso.matcher.RootMatchers; import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; - +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.PreferenceActivity; +import de.danoeh.antennapod.core.storage.APCleanupAlgorithm; +import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm; +import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm; +import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm; import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithmFactory; +import de.danoeh.antennapod.core.storage.ExceptFavoriteCleanupAlgorithm; +import de.danoeh.antennapod.storage.preferences.UserPreferences; +import de.danoeh.antennapod.storage.preferences.UserPreferences.EnqueueLocation; +import de.test.antennapod.EspressoTestUtils; import org.awaitility.Awaitility; import org.junit.Before; import org.junit.Rule; @@ -19,17 +27,6 @@ import org.junit.Test; import java.util.Arrays; import java.util.concurrent.TimeUnit; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.PreferenceActivity; -import de.danoeh.antennapod.storage.preferences.UserPreferences; -import de.danoeh.antennapod.storage.preferences.UserPreferences.EnqueueLocation; -import de.danoeh.antennapod.core.storage.APCleanupAlgorithm; -import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm; -import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm; -import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm; -import de.danoeh.antennapod.core.storage.ExceptFavoriteCleanupAlgorithm; -import de.test.antennapod.EspressoTestUtils; - import static androidx.test.espresso.Espresso.onData; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; @@ -77,22 +74,6 @@ public class PreferencesTest { UserPreferences.init(activityTestRule.getActivity()); } - @Test - public void testSwitchTheme() { - final UserPreferences.ThemePreference theme = UserPreferences.getTheme(); - int otherThemeText; - if (theme == UserPreferences.ThemePreference.DARK) { - otherThemeText = R.string.pref_theme_title_light; - } else { - otherThemeText = R.string.pref_theme_title_dark; - } - clickPreference(R.string.user_interface_label); - clickPreference(R.string.pref_set_theme_title); - onView(withText(otherThemeText)).perform(click()); - Awaitility.await().atMost(1000, MILLISECONDS) - .until(() -> UserPreferences.getTheme() != theme); - } - @Test public void testEnablePersistentPlaybackControls() { final boolean persistNotify = UserPreferences.isPersistNotify(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java index caf555964..66f592af2 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/UserInterfacePreferencesFragment.java @@ -5,18 +5,19 @@ import android.os.Build; import android.os.Bundle; import android.widget.ListView; import androidx.appcompat.app.AlertDialog; -import com.google.android.material.snackbar.Snackbar; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; import androidx.core.app.ActivityCompat; +import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.snackbar.Snackbar; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.PreferenceActivity; -import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.dialog.DrawerPreferencesDialog; import de.danoeh.antennapod.dialog.FeedSortDialog; import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; +import de.danoeh.antennapod.storage.preferences.UserPreferences; import org.greenrobot.eventbus.EventBus; import java.util.List; @@ -37,22 +38,16 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat { } private void setupInterfaceScreen() { - findPreference(UserPreferences.PREF_THEME) - .setOnPreferenceChangeListener( - (preference, newValue) -> { - ActivityCompat.recreate(getActivity()); - return true; - }); - + Preference.OnPreferenceChangeListener restartApp = (preference, newValue) -> { + ActivityCompat.recreate(getActivity()); + return true; + }; + findPreference(UserPreferences.PREF_THEME).setOnPreferenceChangeListener(restartApp); + findPreference(UserPreferences.PREF_THEME_BLACK).setOnPreferenceChangeListener(restartApp); + findPreference(UserPreferences.PREF_TINTED_COLORS).setOnPreferenceChangeListener(restartApp); if (Build.VERSION.SDK_INT < 31) { findPreference(UserPreferences.PREF_TINTED_COLORS).setVisible(false); } - findPreference(UserPreferences.PREF_TINTED_COLORS) - .setOnPreferenceChangeListener( - (preference, newValue) -> { - ActivityCompat.recreate(getActivity()); - return true; - }); findPreference(UserPreferences.PREF_SHOW_TIME_LEFT) .setOnPreferenceChangeListener( diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java index e093c067d..79d06de59 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceUpgrader.java @@ -133,5 +133,13 @@ public class PreferenceUpgrader { "" + UserPreferences.EPISODE_CACHE_SIZE_UNLIMITED).apply(); } } + if (oldVersion < 3010000) { + if (prefs.getString(UserPreferences.PREF_THEME, "system").equals("2")) { + prefs.edit() + .putString(UserPreferences.PREF_THEME, "1") + .putBoolean(UserPreferences.PREF_THEME_BLACK, true) + .apply(); + } + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/ThemePreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/ThemePreference.java new file mode 100644 index 000000000..30cbeb523 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/preferences/ThemePreference.java @@ -0,0 +1,53 @@ +package de.danoeh.antennapod.preferences; + +import android.content.Context; +import android.util.AttributeSet; +import androidx.cardview.widget.CardView; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; +import com.google.android.material.elevation.SurfaceColors; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.databinding.ThemePreferenceBinding; +import de.danoeh.antennapod.storage.preferences.UserPreferences; + +public class ThemePreference extends Preference { + ThemePreferenceBinding viewBinding; + + public ThemePreference(Context context) { + super(context); + setLayoutResource(R.layout.theme_preference); + } + + public ThemePreference(Context context, AttributeSet attrs) { + super(context, attrs); + setLayoutResource(R.layout.theme_preference); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + viewBinding = ThemePreferenceBinding.bind(holder.itemView); + updateUi(); + } + + void updateThemeCard(CardView card, UserPreferences.ThemePreference theme) { + float density = getContext().getResources().getDisplayMetrics().density; + int surfaceColor = SurfaceColors.getColorForElevation(getContext(), 1 * density); + int surfaceColorActive = SurfaceColors.getColorForElevation(getContext(), 32 * density); + UserPreferences.ThemePreference activeTheme = UserPreferences.getTheme(); + card.setCardBackgroundColor(theme == activeTheme ? surfaceColorActive : surfaceColor); + card.setOnClickListener(v -> { + UserPreferences.setTheme(theme); + if (getOnPreferenceChangeListener() != null) { + getOnPreferenceChangeListener().onPreferenceChange(this, UserPreferences.getTheme()); + } + updateUi(); + }); + } + + void updateUi() { + updateThemeCard(viewBinding.themeSystemCard, UserPreferences.ThemePreference.SYSTEM); + updateThemeCard(viewBinding.themeLightCard, UserPreferences.ThemePreference.LIGHT); + updateThemeCard(viewBinding.themeDarkCard, UserPreferences.ThemePreference.DARK); + } +} diff --git a/app/src/main/res/drawable-nodpi/theme_preview_dark.png b/app/src/main/res/drawable-nodpi/theme_preview_dark.png new file mode 100644 index 000000000..b4e1e0376 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/theme_preview_dark.png differ diff --git a/app/src/main/res/drawable-nodpi/theme_preview_light.png b/app/src/main/res/drawable-nodpi/theme_preview_light.png new file mode 100644 index 000000000..39ef47b4f Binary files /dev/null and b/app/src/main/res/drawable-nodpi/theme_preview_light.png differ diff --git a/app/src/main/res/drawable-nodpi/theme_preview_system.png b/app/src/main/res/drawable-nodpi/theme_preview_system.png new file mode 100644 index 000000000..cc6403a98 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/theme_preview_system.png differ diff --git a/app/src/main/res/layout/theme_preference.xml b/app/src/main/res/layout/theme_preference.xml new file mode 100644 index 000000000..32a7ed1e8 --- /dev/null +++ b/app/src/main/res/layout/theme_preference.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/xml/preferences_user_interface.xml b/app/src/main/res/xml/preferences_user_interface.xml index f11b89be7..ed3f5777a 100644 --- a/app/src/main/res/xml/preferences_user_interface.xml +++ b/app/src/main/res/xml/preferences_user_interface.xml @@ -4,13 +4,13 @@ xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch"> - + + -2 - - @string/pref_theme_title_use_system - @string/pref_theme_title_light - @string/pref_theme_title_dark - @string/pref_theme_title_trueblack - - - - system - 0 - 1 - 2 - - @string/home_label @string/queue_label diff --git a/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UserPreferences.java b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UserPreferences.java index 8d9b099fc..c7758d40e 100644 --- a/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UserPreferences.java +++ b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UserPreferences.java @@ -48,6 +48,7 @@ public class UserPreferences { // User Interface public static final String PREF_THEME = "prefTheme"; + public static final String PREF_THEME_BLACK = "prefThemeBlack"; public static final String PREF_TINTED_COLORS = "prefTintedColors"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder"; @@ -159,19 +160,35 @@ public class UserPreferences { LIGHT, DARK, BLACK, SYSTEM } + public static void setTheme(ThemePreference theme) { + switch (theme) { + case LIGHT: + prefs.edit().putString(PREF_THEME, "0").apply(); + break; + case DARK: + prefs.edit().putString(PREF_THEME, "1").apply(); + break; + default: + prefs.edit().putString(PREF_THEME, "system").apply(); + break; + } + } + public static ThemePreference getTheme() { switch (prefs.getString(PREF_THEME, "system")) { case "0": return ThemePreference.LIGHT; case "1": return ThemePreference.DARK; - case "2": - return ThemePreference.BLACK; default: return ThemePreference.SYSTEM; } } + public static boolean getIsBlackTheme() { + return prefs.getBoolean(PREF_THEME_BLACK, false); + } + public static boolean getIsThemeColorTinted() { return Build.VERSION.SDK_INT >= 31 && prefs.getBoolean(PREF_TINTED_COLORS, false); } diff --git a/ui/i18n/src/main/res/values/strings.xml b/ui/i18n/src/main/res/values/strings.xml index 40015630f..db91c43ae 100644 --- a/ui/i18n/src/main/res/values/strings.xml +++ b/ui/i18n/src/main/res/values/strings.xml @@ -432,8 +432,9 @@ Streaming User Interface Appearance, Subscriptions, Lockscreen - Select Theme - Use Tinted Colors + Full Black + Use full black for the dark theme + Tinted Colors Tint app colors based on the background image Set Navigation Drawer items Change which items appear in the navigation drawer. @@ -441,7 +442,6 @@ Change the order of your subscriptions Set Subscription Counter Change the information displayed by the subscription counter. Also affects the sorting of subscriptions if \'Subscription Order\' is set to \'Counter\'. - Change the appearance of AntennaPod. Automatic Download Configure the automatic download of episodes. Enable Wi-Fi filter @@ -455,10 +455,9 @@ Use the episode specific cover in lists whenever available. If unchecked, the app will always use the podcast cover image. Show Remaining Time Display remaining time of episodes when checked. If unchecked, display total duration of episodes. - Use system theme + Automatic Light Dark - Black (AMOLED ready) Unlimited Customize the speeds available for variable speed playback The speed to use when starting audio playback for episodes in this podcast