Extra toggle for full black theme (#6328)

This commit is contained in:
ByteHamster 2023-02-18 14:51:55 +01:00 committed by GitHub
parent caf49c5da8
commit 997860fe52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 240 additions and 75 deletions

View File

@ -3,14 +3,22 @@ package de.test.antennapod.ui;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Resources; import android.content.res.Resources;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.test.espresso.matcher.RootMatchers; import androidx.test.espresso.matcher.RootMatchers;
import androidx.test.filters.LargeTest; import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule; 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.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.awaitility.Awaitility;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
@ -19,17 +27,6 @@ import org.junit.Test;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.TimeUnit; 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.onData;
import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.click;
@ -77,22 +74,6 @@ public class PreferencesTest {
UserPreferences.init(activityTestRule.getActivity()); 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 @Test
public void testEnablePersistentPlaybackControls() { public void testEnablePersistentPlaybackControls() {
final boolean persistNotify = UserPreferences.isPersistNotify(); final boolean persistNotify = UserPreferences.isPersistNotify();

View File

@ -5,18 +5,19 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.widget.ListView; import android.widget.ListView;
import androidx.appcompat.app.AlertDialog; 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.core.app.ActivityCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; 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.R;
import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.dialog.DrawerPreferencesDialog; import de.danoeh.antennapod.dialog.DrawerPreferencesDialog;
import de.danoeh.antennapod.dialog.FeedSortDialog; import de.danoeh.antennapod.dialog.FeedSortDialog;
import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog; import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog;
import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import java.util.List; import java.util.List;
@ -37,22 +38,16 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
} }
private void setupInterfaceScreen() { private void setupInterfaceScreen() {
findPreference(UserPreferences.PREF_THEME) Preference.OnPreferenceChangeListener restartApp = (preference, newValue) -> {
.setOnPreferenceChangeListener(
(preference, newValue) -> {
ActivityCompat.recreate(getActivity()); ActivityCompat.recreate(getActivity());
return true; 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) { if (Build.VERSION.SDK_INT < 31) {
findPreference(UserPreferences.PREF_TINTED_COLORS).setVisible(false); 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) findPreference(UserPreferences.PREF_SHOW_TIME_LEFT)
.setOnPreferenceChangeListener( .setOnPreferenceChangeListener(

View File

@ -133,5 +133,13 @@ public class PreferenceUpgrader {
"" + UserPreferences.EPISODE_CACHE_SIZE_UNLIMITED).apply(); "" + 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();
}
}
} }
} }

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="?android:attr/windowBackground"
android:gravity="top"
android:padding="8dp">
<androidx.cardview.widget.CardView
android:id="@+id/themeSystemCard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
android:layout_weight="1"
app:cardElevation="0dp"
app:cardCornerRadius="16dp"
app:contentPadding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/theme_preview_system" />
<TextView
android:id="@+id/themeSystemRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/pref_theme_title_automatic"
android:clickable="false" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/themeLightCard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
android:layout_weight="1"
app:cardElevation="0dp"
app:cardCornerRadius="16dp"
app:contentPadding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/theme_preview_light" />
<TextView
android:id="@+id/themeLightRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/pref_theme_title_light"
android:clickable="false" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/themeDarkCard"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
android:layout_weight="1"
app:cardElevation="0dp"
app:cardCornerRadius="16dp"
app:contentPadding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/theme_preview_dark" />
<TextView
android:id="@+id/themeDarkCardRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/pref_theme_title_dark"
android:clickable="false" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>

View File

@ -4,13 +4,13 @@
xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch"> xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch">
<PreferenceCategory android:title="@string/appearance"> <PreferenceCategory android:title="@string/appearance">
<de.danoeh.antennapod.preferences.MaterialListPreference <de.danoeh.antennapod.preferences.ThemePreference
android:entryValues="@array/theme_values" android:key="prefTheme" />
android:entries="@array/theme_options" <SwitchPreferenceCompat
android:title="@string/pref_set_theme_title" android:title="@string/pref_black_theme_title"
android:key="prefTheme" android:key="prefThemeBlack"
android:summary="@string/pref_set_theme_sum" android:summary="@string/pref_black_theme_message"
android:defaultValue="system"/> android:defaultValue="false" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:title="@string/pref_tinted_theme_title" android:title="@string/pref_tinted_theme_title"
android:key="prefTintedColors" android:key="prefTintedColors"

View File

@ -59,12 +59,15 @@ public abstract class ThemeSwitcher {
if (theme == UserPreferences.ThemePreference.SYSTEM) { if (theme == UserPreferences.ThemePreference.SYSTEM) {
int nightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; int nightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (nightMode == Configuration.UI_MODE_NIGHT_YES) { if (nightMode == Configuration.UI_MODE_NIGHT_YES) {
return UserPreferences.ThemePreference.DARK; theme = UserPreferences.ThemePreference.DARK;
} else { } else {
return UserPreferences.ThemePreference.LIGHT; theme = UserPreferences.ThemePreference.LIGHT;
} }
} }
if (theme == UserPreferences.ThemePreference.DARK && UserPreferences.getIsBlackTheme()) {
theme = UserPreferences.ThemePreference.BLACK;
}
return theme; return theme;
} }
} }

View File

@ -135,20 +135,6 @@
<item>-2</item> <item>-2</item>
</string-array> </string-array>
<string-array name="theme_options">
<item>@string/pref_theme_title_use_system</item>
<item>@string/pref_theme_title_light</item>
<item>@string/pref_theme_title_dark</item>
<item>@string/pref_theme_title_trueblack</item>
</string-array>
<string-array name="theme_values">
<item>system</item>
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
<string-array name="nav_drawer_titles"> <string-array name="nav_drawer_titles">
<item>@string/home_label</item> <item>@string/home_label</item>
<item>@string/queue_label</item> <item>@string/queue_label</item>

View File

@ -48,6 +48,7 @@ public class UserPreferences {
// User Interface // User Interface
public static final String PREF_THEME = "prefTheme"; 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_TINTED_COLORS = "prefTintedColors";
public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems";
public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder"; public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder";
@ -159,19 +160,35 @@ public class UserPreferences {
LIGHT, DARK, BLACK, SYSTEM 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() { public static ThemePreference getTheme() {
switch (prefs.getString(PREF_THEME, "system")) { switch (prefs.getString(PREF_THEME, "system")) {
case "0": case "0":
return ThemePreference.LIGHT; return ThemePreference.LIGHT;
case "1": case "1":
return ThemePreference.DARK; return ThemePreference.DARK;
case "2":
return ThemePreference.BLACK;
default: default:
return ThemePreference.SYSTEM; return ThemePreference.SYSTEM;
} }
} }
public static boolean getIsBlackTheme() {
return prefs.getBoolean(PREF_THEME_BLACK, false);
}
public static boolean getIsThemeColorTinted() { public static boolean getIsThemeColorTinted() {
return Build.VERSION.SDK_INT >= 31 && prefs.getBoolean(PREF_TINTED_COLORS, false); return Build.VERSION.SDK_INT >= 31 && prefs.getBoolean(PREF_TINTED_COLORS, false);
} }

View File

@ -432,8 +432,9 @@
<string name="pref_mobileUpdate_streaming">Streaming</string> <string name="pref_mobileUpdate_streaming">Streaming</string>
<string name="user_interface_label">User Interface</string> <string name="user_interface_label">User Interface</string>
<string name="user_interface_sum">Appearance, Subscriptions, Lockscreen</string> <string name="user_interface_sum">Appearance, Subscriptions, Lockscreen</string>
<string name="pref_set_theme_title">Select Theme</string> <string name="pref_black_theme_title">Full Black</string>
<string name="pref_tinted_theme_title">Use Tinted Colors</string> <string name="pref_black_theme_message">Use full black for the dark theme</string>
<string name="pref_tinted_theme_title">Tinted Colors</string>
<string name="pref_tinted_theme_message">Tint app colors based on the background image</string> <string name="pref_tinted_theme_message">Tint app colors based on the background image</string>
<string name="pref_nav_drawer_items_title">Set Navigation Drawer items</string> <string name="pref_nav_drawer_items_title">Set Navigation Drawer items</string>
<string name="pref_nav_drawer_items_sum">Change which items appear in the navigation drawer.</string> <string name="pref_nav_drawer_items_sum">Change which items appear in the navigation drawer.</string>
@ -441,7 +442,6 @@
<string name="pref_nav_drawer_feed_order_sum">Change the order of your subscriptions</string> <string name="pref_nav_drawer_feed_order_sum">Change the order of your subscriptions</string>
<string name="pref_nav_drawer_feed_counter_title">Set Subscription Counter</string> <string name="pref_nav_drawer_feed_counter_title">Set Subscription Counter</string>
<string name="pref_nav_drawer_feed_counter_sum">Change the information displayed by the subscription counter. Also affects the sorting of subscriptions if \'Subscription Order\' is set to \'Counter\'.</string> <string name="pref_nav_drawer_feed_counter_sum">Change the information displayed by the subscription counter. Also affects the sorting of subscriptions if \'Subscription Order\' is set to \'Counter\'.</string>
<string name="pref_set_theme_sum">Change the appearance of AntennaPod.</string>
<string name="pref_automatic_download_title">Automatic Download</string> <string name="pref_automatic_download_title">Automatic Download</string>
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string> <string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
<string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string> <string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string>
@ -455,10 +455,9 @@
<string name="pref_episode_cover_summary">Use the episode specific cover in lists whenever available. If unchecked, the app will always use the podcast cover image.</string> <string name="pref_episode_cover_summary">Use the episode specific cover in lists whenever available. If unchecked, the app will always use the podcast cover image.</string>
<string name="pref_show_remain_time_title">Show Remaining Time</string> <string name="pref_show_remain_time_title">Show Remaining Time</string>
<string name="pref_show_remain_time_summary">Display remaining time of episodes when checked. If unchecked, display total duration of episodes.</string> <string name="pref_show_remain_time_summary">Display remaining time of episodes when checked. If unchecked, display total duration of episodes.</string>
<string name="pref_theme_title_use_system">Use system theme</string> <string name="pref_theme_title_automatic">Automatic</string>
<string name="pref_theme_title_light">Light</string> <string name="pref_theme_title_light">Light</string>
<string name="pref_theme_title_dark">Dark</string> <string name="pref_theme_title_dark">Dark</string>
<string name="pref_theme_title_trueblack">Black (AMOLED ready)</string>
<string name="pref_episode_cache_unlimited">Unlimited</string> <string name="pref_episode_cache_unlimited">Unlimited</string>
<string name="pref_playback_speed_sum">Customize the speeds available for variable speed playback</string> <string name="pref_playback_speed_sum">Customize the speeds available for variable speed playback</string>
<string name="pref_feed_playback_speed_sum">The speed to use when starting audio playback for episodes in this podcast</string> <string name="pref_feed_playback_speed_sum">The speed to use when starting audio playback for episodes in this podcast</string>