NewPipe/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java

259 lines
9.6 KiB
Java
Raw Normal View History

/*
* Copyright 2018 Mauricio Colli <mauriciocolli@outlook.com>
* ThemeHelper.java is part of NewPipe
*
* License: GPL-3.0+
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2017-02-27 12:55:15 +01:00
package org.schabi.newpipe.util;
import android.app.Activity;
2017-02-27 12:55:15 +01:00
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
2018-01-23 01:40:00 +01:00
import android.content.res.TypedArray;
import android.util.TypedValue;
2019-10-04 14:59:08 +02:00
import androidx.annotation.AttrRes;
import androidx.annotation.Nullable;
2019-10-04 14:59:08 +02:00
import androidx.annotation.StyleRes;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
2019-10-04 14:59:08 +02:00
import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager;
2017-02-27 12:55:15 +01:00
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
2017-02-27 12:55:15 +01:00
public final class ThemeHelper {
private ThemeHelper() {
}
2017-02-27 12:55:15 +01:00
/**
* Apply the selected theme (on NewPipe settings) in the context
* with the default style (see {@link #setTheme(Context, int)}).
*
2017-04-26 21:32:20 +02:00
* @param context context that the theme will be applied
*/
public static void setTheme(final Context context) {
setTheme(context, -1);
}
/**
* Apply the selected theme (on NewPipe settings) in the context,
* themed according with the styles defined for the service .
*
* @param context context that the theme will be applied
* @param serviceId the theme will be styled to the service with this id,
* pass -1 to get the default style
*/
public static void setTheme(final Context context, final int serviceId) {
context.setTheme(getThemeForService(context, serviceId));
2017-04-26 21:32:20 +02:00
}
/**
* Return true if the selected theme (on NewPipe settings) is the Light theme.
2017-04-26 21:32:20 +02:00
*
* @param context context to get the preference
* @return whether the light theme is selected
2017-04-26 21:32:20 +02:00
*/
public static boolean isLightThemeSelected(final Context context) {
2021-03-18 12:35:53 +01:00
final String selectedThemeKey = getSelectedThemeKey(context);
final Resources res = context.getResources();
2021-03-18 12:35:53 +01:00
return selectedThemeKey.equals(res.getString(R.string.light_theme_key))
|| (selectedThemeKey.equals(res.getString(R.string.auto_device_theme_key))
&& !isDeviceDarkThemeEnabled(context));
}
/**
* Return a dialog theme styled according to the (default) selected theme.
*
* @param context context to get the selected theme
* @return the dialog style (the default one)
*/
@StyleRes
public static int getDialogTheme(final Context context) {
return isLightThemeSelected(context) ? R.style.LightDialogTheme : R.style.DarkDialogTheme;
}
/**
* Return a min-width dialog theme styled according to the (default) selected theme.
*
* @param context context to get the selected theme
* @return the dialog style (the default one)
*/
@StyleRes
public static int getMinWidthDialogTheme(final Context context) {
return isLightThemeSelected(context) ? R.style.LightDialogMinWidthTheme
: R.style.DarkDialogMinWidthTheme;
}
/**
* Return the selected theme styled according to the serviceId.
*
* @param context context to get the selected theme
* @param serviceId return a theme styled to this service,
* -1 to get the default
* @return the selected style (styled)
*/
2018-01-23 01:40:00 +01:00
@StyleRes
public static int getThemeForService(final Context context, final int serviceId) {
final Resources res = context.getResources();
2021-03-18 12:35:53 +01:00
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);
2018-01-23 01:40:00 +01:00
2021-03-18 12:35:53 +01:00
final String selectedThemeKey = getSelectedThemeKey(context);
2018-01-23 01:40:00 +01:00
2021-03-18 12:35:53 +01:00
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)) {
2021-03-18 12:35:53 +01:00
// use the dark theme variant preferred by the user
final String selectedNightThemeKey = getSelectedNightThemeKey(context);
if (selectedNightThemeKey.equals(blackThemeKey)) {
baseTheme = R.style.BlackTheme;
} else {
2021-03-18 12:35:53 +01:00
baseTheme = R.style.DarkTheme;
}
} else {
// there is only one day theme
2021-03-18 12:35:53 +01:00
baseTheme = R.style.LightTheme;
}
}
if (serviceId <= -1) {
2021-03-18 12:35:53 +01:00
return baseTheme;
}
final StreamingService service;
try {
service = NewPipe.getService(serviceId);
2020-08-16 10:24:58 +02:00
} catch (final ExtractionException ignored) {
2021-03-18 12:35:53 +01:00
return baseTheme;
}
2021-03-18 12:35:53 +01:00
String themeName = "DarkTheme"; // default
if (baseTheme == R.style.LightTheme) {
themeName = "LightTheme";
2021-03-18 12:35:53 +01:00
} else if (baseTheme == R.style.BlackTheme) {
themeName = "BlackTheme";
}
themeName += "." + service.getServiceInfo().getName();
2021-03-18 12:35:53 +01:00
final int resourceId = context.getResources()
2018-12-23 22:41:42 +01:00
.getIdentifier(themeName, "style", context.getPackageName());
if (resourceId > 0) {
return resourceId;
}
2021-03-18 12:35:53 +01:00
return baseTheme;
}
2018-01-23 01:40:00 +01:00
/**
2020-03-26 01:50:32 +01:00
* Get a resource id from a resource styled according to the context's theme.
*
* @param context Android app context
* @param attr attribute reference of the resource
* @return resource ID
2018-01-23 01:40:00 +01:00
*/
public static int resolveResourceIdFromAttr(final Context context, @AttrRes final int attr) {
2020-08-16 10:24:58 +02:00
final TypedArray a = context.getTheme().obtainStyledAttributes(new int[]{attr});
final int attributeResourceId = a.getResourceId(0, 0);
2018-01-23 01:40:00 +01:00
a.recycle();
return attributeResourceId;
}
/**
2020-03-26 01:50:32 +01:00
* Get a color from an attr styled according to the context's theme.
*
* @param context Android app context
* @param attrColor attribute reference of the resource
* @return the color
*/
public static int resolveColorFromAttr(final Context context, @AttrRes final int attrColor) {
final TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(attrColor, value, true);
if (value.resourceId != 0) {
return ContextCompat.getColor(context, value.resourceId);
}
return value.data;
}
2021-03-18 12:35:53 +01:00
private static String getSelectedThemeKey(final Context context) {
2020-08-16 10:24:58 +02:00
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);
}
2021-03-18 12:35:53 +01:00
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
*/
public static void setTitleToAppCompatActivity(@Nullable final Activity activity,
final CharSequence title) {
if (activity instanceof AppCompatActivity) {
final ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(title);
}
}
}
/**
* Get the device theme
* <p>
* It will return true if the device 's theme is dark, false otherwise.
* <p>
* 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;
}
}
2017-02-27 12:55:15 +01:00
}