diff --git a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java index 8126bd2c5..e2ac2c20d 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java @@ -18,40 +18,43 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment { private static final boolean CAPTIONING_SETTINGS_ACCESSIBLE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - /** - * Theme that was applied when the settings was opened (or recreated after a theme change). - */ - private String startThemeKey; - private final Preference.OnPreferenceChangeListener themePreferenceChange - = new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(final Preference preference, final Object newValue) { - defaultPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, true).apply(); - defaultPreferences.edit() - .putString(getString(R.string.theme_key), newValue.toString()).apply(); - - if (!newValue.equals(startThemeKey) && getActivity() != null) { - // If it's not the current theme - ActivityCompat.recreate(requireActivity()); - } - - return false; - } - }; private String captionSettingsKey; @Override public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); + final String themeKey = getString(R.string.theme_key); - startThemeKey = defaultPreferences + // the key of the active theme when settings were opened (or recreated after theme change) + final String startThemeKey = defaultPreferences .getString(themeKey, getString(R.string.default_theme_value)); - findPreference(themeKey).setOnPreferenceChangeListener(themePreferenceChange); + final String autoDeviceThemeKey = getString(R.string.auto_device_theme_key); + findPreference(themeKey).setOnPreferenceChangeListener((preference, newValue) -> { + if (newValue.toString().equals(autoDeviceThemeKey)) { + Toast.makeText(getContext(), getString(R.string.select_night_theme_toast), + Toast.LENGTH_LONG).show(); + } + + applyThemeChange(startThemeKey, themeKey, newValue); + return false; + }); + + final String nightThemeKey = getString(R.string.night_theme_key); + if (startThemeKey.equals(autoDeviceThemeKey)) { + final String startNightThemeKey = defaultPreferences + .getString(nightThemeKey, getString(R.string.default_night_theme_value)); + + findPreference(nightThemeKey).setOnPreferenceChangeListener((preference, newValue) -> { + applyThemeChange(startNightThemeKey, nightThemeKey, newValue); + return false; + }); + } else { + removePreference(nightThemeKey); + } captionSettingsKey = getString(R.string.caption_settings_key); if (!CAPTIONING_SETTINGS_ACCESSIBLE) { - final Preference captionSettings = findPreference(captionSettingsKey); - getPreferenceScreen().removePreference(captionSettings); + removePreference(captionSettingsKey); } } @@ -72,4 +75,23 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment { return super.onPreferenceTreeClick(preference); } + + private void removePreference(final String preferenceKey) { + final Preference preference = findPreference(preferenceKey); + if (preference != null) { + getPreferenceScreen().removePreference(preference); + } + } + + private void applyThemeChange(final String beginningThemeKey, + final String themeKey, + final Object newValue) { + defaultPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, true).apply(); + defaultPreferences.edit().putString(themeKey, newValue.toString()).apply(); + + if (!newValue.equals(beginningThemeKey) && getActivity() != null) { + // if it's not the current theme + ActivityCompat.recreate(getActivity()); + } + } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 4de166a55..c445928c4 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -48,7 +48,7 @@ public class SettingsActivity extends AppCompatActivity @Override protected void onCreate(final Bundle savedInstanceBundle) { - setTheme(ThemeHelper.getSettingsThemeStyle(this)); + ThemeHelper.setTheme(this); assureCorrectAppLanguage(this); super.onCreate(savedInstanceBundle); diff --git a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java index 5ac4de84c..0c890dddc 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java @@ -21,9 +21,10 @@ package org.schabi.newpipe.util; import android.app.Activity; import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; import android.content.res.TypedArray; import android.util.TypedValue; -import android.view.ContextThemeWrapper; import androidx.annotation.AttrRes; import androidx.annotation.Nullable; @@ -39,7 +40,8 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; public final class ThemeHelper { - private ThemeHelper() { } + private ThemeHelper() { + } /** * Apply the selected theme (on NewPipe settings) in the context @@ -70,31 +72,12 @@ public final class ThemeHelper { * @return whether the light theme is selected */ public static boolean isLightThemeSelected(final Context context) { - return getSelectedThemeString(context).equals(context.getResources() - .getString(R.string.light_theme_key)); - } + final String selectedThemeKey = getSelectedThemeKey(context); + final Resources res = context.getResources(); - - /** - * Create and return a wrapped context with the default selected theme set. - * - * @param baseContext the base context for the wrapper - * @return a wrapped-styled context - */ - public static Context getThemedContext(final Context baseContext) { - return new ContextThemeWrapper(baseContext, getThemeForService(baseContext, -1)); - } - - /** - * Return the selected theme without being styled to any service. - * See {@link #getThemeForService(Context, int)}. - * - * @param context context to get the selected theme - * @return the selected style (the default one) - */ - @StyleRes - public static int getDefaultTheme(final Context context) { - return getThemeForService(context, -1); + return selectedThemeKey.equals(res.getString(R.string.light_theme_key)) + || (selectedThemeKey.equals(res.getString(R.string.auto_device_theme_key)) + && !isDeviceDarkThemeEnabled(context)); } /** @@ -130,71 +113,60 @@ public final class ThemeHelper { */ @StyleRes public static int getThemeForService(final Context context, final int serviceId) { - final String lightTheme = context.getResources().getString(R.string.light_theme_key); - final String darkTheme = context.getResources().getString(R.string.dark_theme_key); - final String blackTheme = context.getResources().getString(R.string.black_theme_key); + final Resources res = context.getResources(); + final String lightThemeKey = res.getString(R.string.light_theme_key); + final String blackThemeKey = res.getString(R.string.black_theme_key); + final String automaticDeviceThemeKey = res.getString(R.string.auto_device_theme_key); - final String selectedTheme = getSelectedThemeString(context); + final String selectedThemeKey = getSelectedThemeKey(context); - int defaultTheme = R.style.DarkTheme; - if (selectedTheme.equals(lightTheme)) { - defaultTheme = R.style.LightTheme; - } else if (selectedTheme.equals(blackTheme)) { - defaultTheme = R.style.BlackTheme; - } else if (selectedTheme.equals(darkTheme)) { - defaultTheme = R.style.DarkTheme; + int baseTheme = R.style.DarkTheme; // default to dark theme + if (selectedThemeKey.equals(lightThemeKey)) { + baseTheme = R.style.LightTheme; + } else if (selectedThemeKey.equals(blackThemeKey)) { + baseTheme = R.style.BlackTheme; + } else if (selectedThemeKey.equals(automaticDeviceThemeKey)) { + + if (isDeviceDarkThemeEnabled(context)) { + // use the dark theme variant preferred by the user + final String selectedNightThemeKey = getSelectedNightThemeKey(context); + if (selectedNightThemeKey.equals(blackThemeKey)) { + baseTheme = R.style.BlackTheme; + } else { + baseTheme = R.style.DarkTheme; + } + } else { + // there is only one day theme + baseTheme = R.style.LightTheme; + } } if (serviceId <= -1) { - return defaultTheme; + return baseTheme; } final StreamingService service; try { service = NewPipe.getService(serviceId); } catch (final ExtractionException ignored) { - return defaultTheme; + return baseTheme; } - String themeName = "DarkTheme"; - if (selectedTheme.equals(lightTheme)) { + String themeName = "DarkTheme"; // default + if (baseTheme == R.style.LightTheme) { themeName = "LightTheme"; - } else if (selectedTheme.equals(blackTheme)) { + } else if (baseTheme == R.style.BlackTheme) { themeName = "BlackTheme"; - } else if (selectedTheme.equals(darkTheme)) { - themeName = "DarkTheme"; } themeName += "." + service.getServiceInfo().getName(); - final int resourceId = context - .getResources() + final int resourceId = context.getResources() .getIdentifier(themeName, "style", context.getPackageName()); if (resourceId > 0) { return resourceId; } - - return defaultTheme; - } - - @StyleRes - public static int getSettingsThemeStyle(final Context context) { - final String lightTheme = context.getResources().getString(R.string.light_theme_key); - final String darkTheme = context.getResources().getString(R.string.dark_theme_key); - final String blackTheme = context.getResources().getString(R.string.black_theme_key); - - final String selectedTheme = getSelectedThemeString(context); - - if (selectedTheme.equals(lightTheme)) { - return R.style.LightSettingsTheme; - } else if (selectedTheme.equals(blackTheme)) { - return R.style.BlackSettingsTheme; - } else if (selectedTheme.equals(darkTheme)) { - return R.style.DarkSettingsTheme; - } else { - // Fallback - return R.style.DarkSettingsTheme; - } + return baseTheme; } /** @@ -229,18 +201,27 @@ public final class ThemeHelper { return value.data; } - private static String getSelectedThemeString(final Context context) { + private static String getSelectedThemeKey(final Context context) { final String themeKey = context.getString(R.string.theme_key); final String defaultTheme = context.getResources().getString(R.string.default_theme_value); return PreferenceManager.getDefaultSharedPreferences(context) .getString(themeKey, defaultTheme); } + private static String getSelectedNightThemeKey(final Context context) { + final String nightThemeKey = context.getString(R.string.night_theme_key); + final String defaultNightTheme = context.getResources() + .getString(R.string.default_night_theme_value); + return PreferenceManager.getDefaultSharedPreferences(context) + .getString(nightThemeKey, defaultNightTheme); + } + /** * Sets the title to the activity, if the activity is an {@link AppCompatActivity} and has an * action bar. + * * @param activity the activity to set the title of - * @param title the title to set to the activity + * @param title the title to set to the activity */ public static void setTitleToAppCompatActivity(@Nullable final Activity activity, final CharSequence title) { @@ -251,4 +232,27 @@ public final class ThemeHelper { } } } + + /** + * Get the device theme + *

+ * It will return true if the device 's theme is dark, false otherwise. + *

+ * From https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#java + * + * @param context the context to use + * @return true:dark theme, false:light or unknown + */ + public static boolean isDeviceDarkThemeEnabled(final Context context) { + final int deviceTheme = context.getResources().getConfiguration().uiMode + & Configuration.UI_MODE_NIGHT_MASK; + switch (deviceTheme) { + case Configuration.UI_MODE_NIGHT_YES: + return true; + case Configuration.UI_MODE_NIGHT_UNDEFINED: + case Configuration.UI_MODE_NIGHT_NO: + default: + return false; + } + } } diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 38e83b662..2f2a9622c 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -23,6 +23,7 @@ Etoso Malluma Luma + Nigra Elŝuti Ligilo ne subtenita Preferata enhavlingvo @@ -90,7 +91,6 @@ Montri pli altajn rezoluciojn Nur kelkaj aparatoj povas ludi 2K / 4K filmetojn Defaŭlta fomato de filmeto - Nigra Memoru ŝprucfenestran grandecon kaj pozicion Memoru lastan grandecon kaj pozicion de ŝprucfenestro Uzi rapide, ne precizan serĉon diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 86f4fe09c..6020f8cb1 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -41,8 +41,10 @@ Utiliser Tor (Expérimental) Forcer la redirection du trafic de téléchargement via Tor pour plus de confidentialité (les flux vidéos ne sont pas encore pris en charge). Thème + Thème nuit Sombre Clair + Noir Apparence Erreur réseau Dossier de téléchargement audio @@ -103,7 +105,6 @@ Veuillez définir ultérieurement un dossier de téléchargement dans les paramètres Impossible de charger l’image L’application a planté - Noir Tout Chaîne Défi reCAPTCHA @@ -669,4 +670,7 @@ Ce contenu n\'est disponible que pour les abonnés, il ne peut donc pas être diffusé en continu ni téléchargé par NewPipe. Cette vidéo n\'est disponible que pour les membres de YouTube Music Premium, elle ne peut donc pas être diffusée en continu ni téléchargée par NewPipe. Ce contenu est privé, il ne peut donc pas être diffusé en continu ni téléchargé par NewPipe. + Automatique (thème de l\'appareil) + Choisissez votre thème nuit favori — %s + Vous pouvez chosir votre thème nuit favori \ No newline at end of file diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 0958fce26..9044c65aa 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -176,19 +176,32 @@ theme + night_theme light_theme dark_theme black_theme + auto_device_theme @string/dark_theme_key + @string/dark_theme_key @string/light_theme_key @string/dark_theme_key @string/black_theme_key + @string/auto_device_theme_key @string/light_theme_title @string/dark_theme_title @string/black_theme_title + @string/auto_device_theme_title + + + @string/dark_theme_key + @string/black_theme_key + + + @string/dark_theme_title + @string/black_theme_title diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9fb15e463..99702dab0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -79,6 +79,7 @@ Default audio format Default video format Theme + Night Theme Light Dark Black @@ -709,4 +710,7 @@ This content is only available to users who have paid, so it cannot be streamed or downloaded by NewPipe. Featured Radio + Automatic (device theme) + Select your favorite night theme — %s + You can select your favorite night theme below diff --git a/app/src/main/res/xml/appearance_settings.xml b/app/src/main/res/xml/appearance_settings.xml index 7f30d2091..e5afef805 100644 --- a/app/src/main/res/xml/appearance_settings.xml +++ b/app/src/main/res/xml/appearance_settings.xml @@ -12,6 +12,15 @@ android:title="@string/theme_title" app:iconSpaceReserved="false" /> + +