Add dynamic widget theme

pull/2807/head
Alex Baker 2 years ago
parent 3d92ca78dd
commit 041dce8617

@ -140,8 +140,12 @@ public class AndroidUtilities {
return !atLeastOreo(); return !atLeastOreo();
} }
public static boolean preS() {
return !atLeastS();
}
public static boolean preTiramisu() { public static boolean preTiramisu() {
return VERSION.SDK_INT < VERSION_CODES.TIRAMISU; return !atLeastTiramisu();
} }
public static boolean preUpsideDownCake() { public static boolean preUpsideDownCake() {

@ -12,7 +12,6 @@ import org.tasks.data.CaldavDao
import org.tasks.extensions.Context.openUri import org.tasks.extensions.Context.openUri
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import timber.log.Timber import timber.log.Timber
import java.util.*
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -59,6 +58,7 @@ class Inventory @Inject constructor(
var hasPro = false var hasPro = false
get() { get() {
@Suppress("KotlinConstantConditions")
return BuildConfig.FLAVOR == "generic" return BuildConfig.FLAVOR == "generic"
|| (BuildConfig.DEBUG && preferences.getBoolean(R.string.p_debug_pro, false)) || (BuildConfig.DEBUG && preferences.getBoolean(R.string.p_debug_pro, false))
|| hasTasksAccount || hasTasksAccount

@ -14,6 +14,7 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.todoroo.andlib.utility.AndroidUtilities.preS
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.tasks.R import org.tasks.R
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
@ -58,9 +59,9 @@ class ThemePickerDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
selected = savedInstanceState?.getInt(EXTRA_SELECTED) ?: requireArguments().getInt(EXTRA_SELECTED) selected = savedInstanceState?.getInt(EXTRA_SELECTED) ?: requireArguments().getInt(EXTRA_SELECTED)
widget = arguments?.getBoolean(EXTRA_WIDGET) ?: false widget = arguments?.getBoolean(EXTRA_WIDGET) ?: false
val themes = resources.getStringArray( val themes = resources
if (widget) R.array.widget_themes else R.array.base_theme_names .getStringArray(if (widget) R.array.widget_themes else R.array.base_theme_names)
) .let { if (widget && (preS() || !inventory.hasPro)) it.dropLast(1).toTypedArray() else it }
adapter = object : ArrayAdapter<String>(requireActivity(), R.layout.simple_list_item_single_choice, themes) { adapter = object : ArrayAdapter<String>(requireActivity(), R.layout.simple_list_item_single_choice, themes) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {

@ -200,8 +200,10 @@ class WidgetSettings : InjectingPreferenceFragment() {
} }
private fun updateTheme() { private fun updateTheme() {
val index = widgetPreferences.themeIndex
val widgetNames = resources.getStringArray(R.array.widget_themes) val widgetNames = resources.getStringArray(R.array.widget_themes)
findPreference(R.string.p_widget_theme).summary = widgetNames[widgetPreferences.themeIndex] findPreference(R.string.p_widget_theme).summary = widgetNames[index]
findPreference(R.string.p_widget_color_v2).isVisible = index != 4
} }
private fun updateColor() { private fun updateColor() {

@ -9,7 +9,6 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.annotation.ColorInt
import com.todoroo.andlib.utility.AndroidUtilities.atLeastS import com.todoroo.andlib.utility.AndroidUtilities.atLeastS
import com.todoroo.astrid.api.Filter import com.todoroo.astrid.api.Filter
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -75,15 +74,14 @@ class TasksWidget : AppWidgetProvider() {
} else { } else {
setViewVisibility(R.id.widget_header, View.GONE) setViewVisibility(R.id.widget_header, View.GONE)
} }
val bgColor = getBackgroundColor(widgetPreferences.themeIndex)
setBackgroundColor( setBackgroundColor(
viewId = R.id.list_view, viewId = R.id.list_view,
color = bgColor, color = settings.backgroundColor,
opacity = widgetPreferences.rowOpacity, opacity = widgetPreferences.rowOpacity,
) )
setBackgroundColor( setBackgroundColor(
viewId = R.id.empty_view, viewId = R.id.empty_view,
color = bgColor, color = settings.backgroundColor,
opacity = widgetPreferences.footerOpacity, opacity = widgetPreferences.footerOpacity,
) )
setOnClickPendingIntent(R.id.empty_view, getOpenListIntent(context, filter, id)) setOnClickPendingIntent(R.id.empty_view, getOpenListIntent(context, filter, id))
@ -168,17 +166,6 @@ class TasksWidget : AppWidgetProvider() {
} }
} }
@ColorInt
private fun getBackgroundColor(themeIndex: Int): Int {
val background: Int = when (themeIndex) {
1 -> android.R.color.black
2 -> R.color.md_background_dark
3 -> R.color.widget_background_follow_system
else -> android.R.color.white
}
return context.getColor(background)
}
private fun getPendingIntentTemplate(context: Context): PendingIntent = private fun getPendingIntentTemplate(context: Context): PendingIntent =
PendingIntent.getActivity( PendingIntent.getActivity(
context, context,

@ -18,7 +18,6 @@ import org.tasks.data.TaskContainer
import org.tasks.data.TaskDao import org.tasks.data.TaskDao
import org.tasks.data.TaskListQuery.getQuery import org.tasks.data.TaskListQuery.getQuery
import org.tasks.date.DateTimeUtils import org.tasks.date.DateTimeUtils
import org.tasks.extensions.Context.isNightMode
import org.tasks.extensions.setBackgroundResource import org.tasks.extensions.setBackgroundResource
import org.tasks.extensions.setColorFilter import org.tasks.extensions.setColorFilter
import org.tasks.extensions.setMaxLines import org.tasks.extensions.setMaxLines
@ -56,16 +55,11 @@ internal class TasksWidgetViewFactory(
|| (filter.supportsManualSort() && widgetPreferences.isManualSort) || (filter.supportsManualSort() && widgetPreferences.isManualSort)
|| (filter is AstridOrderingFilter && widgetPreferences.isAstridSort) || (filter is AstridOrderingFilter && widgetPreferences.isAstridSort)
private var tasks = SectionedDataSource() private var tasks = SectionedDataSource()
private val isDark = when (widgetPreferences.themeIndex) { private val onSurface = context.getColor(if (settings.isDark) R.color.white_87 else R.color.black_87)
0 -> false private val onSurfaceVariant = context.getColor(if (settings.isDark) R.color.white_60 else R.color.black_60)
3 -> context.isNightMode
else -> true
}
private val onSurface = context.getColor(if (isDark) R.color.white_87 else R.color.black_87)
private val onSurfaceVariant = context.getColor(if (isDark) R.color.white_60 else R.color.black_60)
init { init {
chipProvider.isDark = isDark chipProvider.isDark = settings.isDark
} }
override fun onCreate() {} override fun onCreate() {}
@ -134,7 +128,7 @@ internal class TasksWidgetViewFactory(
section.headerColor( section.headerColor(
context, context,
settings.groupMode, settings.groupMode,
if (isDark) R.color.white_60 else R.color.black_60 if (settings.isDark) R.color.white_60 else R.color.black_60
) )
) )
if (!settings.showDividers) { if (!settings.showDividers) {

@ -1,11 +1,13 @@
package org.tasks.widget package org.tasks.widget
import android.content.Context import android.content.Context
import androidx.core.content.ContextCompat
import com.google.common.base.Joiner import com.google.common.base.Joiner
import com.google.common.base.Splitter import com.google.common.base.Splitter
import com.todoroo.astrid.core.SortHelper import com.todoroo.astrid.core.SortHelper
import com.todoroo.astrid.service.Upgrader.Companion.getLegacyColor import com.todoroo.astrid.service.Upgrader.Companion.getLegacyColor
import org.tasks.R import org.tasks.R
import org.tasks.extensions.Context.isNightMode
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.preferences.QueryPreferences import org.tasks.preferences.QueryPreferences
import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED import org.tasks.tasklist.SectionedDataSource.Companion.HEADER_COMPLETED
@ -23,8 +25,10 @@ class WidgetPreferences(
val showSettings: Boolean, val showSettings: Boolean,
val showMenu: Boolean, val showMenu: Boolean,
val color: Int, val color: Int,
val backgroundColor: Int,
val headerOpacity: Int, val headerOpacity: Int,
val headerSpacing: Int, val headerSpacing: Int,
val isDark: Boolean,
) )
data class WidgetRowSettings( data class WidgetRowSettings(
@ -44,6 +48,7 @@ class WidgetPreferences(
val compact: Boolean, val compact: Boolean,
val groupMode: Int, val groupMode: Int,
val dueDatePosition: Int, val dueDatePosition: Int,
val isDark: Boolean,
) { ) {
val showDueDates get() = dueDatePosition != 2 val showDueDates get() = dueDatePosition != 2
val endDueDate get() = dueDatePosition != 1 val endDueDate get() = dueDatePosition != 1
@ -55,8 +60,10 @@ class WidgetPreferences(
showSettings = getBoolean(R.string.p_widget_show_settings, true), showSettings = getBoolean(R.string.p_widget_show_settings, true),
showMenu = getBoolean(R.string.p_widget_show_menu, true), showMenu = getBoolean(R.string.p_widget_show_menu, true),
color = color, color = color,
backgroundColor = backgroundColor,
headerOpacity = getAlphaValue(R.string.p_widget_header_opacity), headerOpacity = getAlphaValue(R.string.p_widget_header_opacity),
headerSpacing = getSpacing(R.string.p_widget_header_spacing), headerSpacing = getSpacing(R.string.p_widget_header_spacing),
isDark = isDark,
) )
fun getWidgetListSettings() = WidgetRowSettings( fun getWidgetListSettings() = WidgetRowSettings(
@ -76,10 +83,28 @@ class WidgetPreferences(
compact = getBoolean(R.string.p_widget_compact, false), compact = getBoolean(R.string.p_widget_compact, false),
groupMode = groupMode, groupMode = groupMode,
dueDatePosition = dueDatePosition, dueDatePosition = dueDatePosition,
isDark = isDark,
) )
val dueDatePosition: Int get() = getIntegerFromString(R.string.p_widget_due_date_position) val dueDatePosition: Int get() = getIntegerFromString(R.string.p_widget_due_date_position)
private val isDark: Boolean
get() = when (themeIndex) {
0 -> false
3, 4 -> context.isNightMode
else -> true
}
private val backgroundColor: Int
get() = context.getColor(
when (themeIndex) {
1 -> android.R.color.black
2 -> R.color.md_background_dark
3, 4 -> R.color.widget_background_follow_system
else -> android.R.color.white
}
)
var collapsed: Set<Long> var collapsed: Set<Long>
get() { get() {
val value = getString(R.string.p_widget_collapsed) val value = getString(R.string.p_widget_collapsed)
@ -113,6 +138,16 @@ class WidgetPreferences(
get() = getInt(R.string.p_widget_theme, 3) get() = getInt(R.string.p_widget_theme, 3)
val color: Int val color: Int
get() { get() {
if (themeIndex == 4) {
return ContextCompat.getColor(
context,
if (isDark) {
com.google.android.material.R.color.m3_sys_color_dynamic_dark_primary
} else {
com.google.android.material.R.color.m3_sys_color_dynamic_light_primary
}
)
}
var color = getInt(R.string.p_widget_color_v2, 0) var color = getInt(R.string.p_widget_color_v2, 0)
if (color != 0) { if (color != 0) {
return color return color

@ -27,6 +27,7 @@
<item>@string/theme_black</item> <item>@string/theme_black</item>
<item>@string/theme_dark</item> <item>@string/theme_dark</item>
<item>@string/theme_system_default</item> <item>@string/theme_system_default</item>
<item>@string/theme_dynamic</item>
</string-array> </string-array>
<string-array name="EPr_default_urgency"> <string-array name="EPr_default_urgency">

@ -389,6 +389,7 @@ File %1$s contained %2$s.\n\n
<string name="theme_wallpaper">Wallpaper</string> <string name="theme_wallpaper">Wallpaper</string>
<string name="theme_day_night">Day/Night</string> <string name="theme_day_night">Day/Night</string>
<string name="theme_system_default">System default</string> <string name="theme_system_default">System default</string>
<string name="theme_dynamic">Dynamic</string>
<string name="language">Language</string> <string name="language">Language</string>
<string name="restart_required">Restart Tasks for this change to take effect</string> <string name="restart_required">Restart Tasks for this change to take effect</string>
<string name="restart_now">Restart now</string> <string name="restart_now">Restart now</string>

Loading…
Cancel
Save