New material icon picker

pull/2952/head
Alex Baker 1 year ago
parent 282042538c
commit 7d52d58f3d

@ -51,8 +51,8 @@ android {
defaultConfig { defaultConfig {
testApplicationId = "org.tasks.test" testApplicationId = "org.tasks.test"
applicationId = "org.tasks" applicationId = "org.tasks"
versionCode = 131005 versionCode = 131100
versionName = "13.10" versionName = "13.11"
targetSdk = libs.versions.android.targetSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt()
minSdk = libs.versions.android.minSdk.get().toInt() minSdk = libs.versions.android.minSdk.get().toInt()
testInstrumentationRunner = "org.tasks.TestRunner" testInstrumentationRunner = "org.tasks.TestRunner"
@ -183,6 +183,8 @@ dependencies {
implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.room) implementation(libs.androidx.room)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.iconics)
implementation(libs.iconics.material.design)
implementation(libs.markwon) implementation(libs.markwon)
implementation(libs.markwon.editor) implementation(libs.markwon.editor)
implementation(libs.markwon.linkify) implementation(libs.markwon.linkify)

3
app/proguard.pro vendored

@ -54,3 +54,6 @@
-dontwarn org.joda.convert.FromString -dontwarn org.joda.convert.FromString
-dontwarn org.joda.convert.ToString -dontwarn org.joda.convert.ToString
-dontwarn org.json.JSONString -dontwarn org.json.JSONString
# material icons
-keep class androidx.compose.material.icons.outlined.**

@ -214,6 +214,13 @@
android:taskAffinity="" android:taskAffinity=""
android:theme="@style/TranslucentDialog"/> android:theme="@style/TranslucentDialog"/>
<activity
android:name=".compose.IconPickerActivity"
android:excludeFromRecents="true"
android:exported="true"
android:taskAffinity=""
android:theme="@style/TranslucentDialog" />
<activity <activity
android:name=".activities.CameraActivity" android:name=".activities.CameraActivity"
android:theme="@style/TranslucentDialog"/> android:theme="@style/TranslucentDialog"/>

@ -8,9 +8,6 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.todoroo.astrid.activity.MainActivity.Companion.LOAD_FILTER import com.todoroo.astrid.activity.MainActivity.Companion.LOAD_FILTER
import com.todoroo.astrid.activity.MainActivity.Companion.OPEN_FILTER import com.todoroo.astrid.activity.MainActivity.Companion.OPEN_FILTER
import com.todoroo.astrid.api.CustomFilter
import org.tasks.filters.GtasksFilter
import org.tasks.filters.TagFilter
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@ -22,7 +19,6 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R
import org.tasks.Tasks.Companion.IS_GENERIC import org.tasks.Tasks.Companion.IS_GENERIC
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.compose.drawer.DrawerItem import org.tasks.compose.drawer.DrawerItem
@ -35,11 +31,10 @@ import org.tasks.filters.CaldavFilter
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.FilterProvider import org.tasks.filters.FilterProvider
import org.tasks.filters.NavigationDrawerSubheader import org.tasks.filters.NavigationDrawerSubheader
import org.tasks.filters.PlaceFilter import org.tasks.filters.getIcon
import org.tasks.preferences.DefaultFilterProvider import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -135,7 +130,7 @@ class MainActivityViewModel @Inject constructor(
is Filter -> is Filter ->
DrawerItem.Filter( DrawerItem.Filter(
title = item.title ?: "", title = item.title ?: "",
icon = getIcon(item), icon = item.getIcon(inventory),
color = getColor(item), color = getColor(item),
count = item.count.takeIf { it != NO_COUNT } ?: try { count = item.count.takeIf { it != NO_COUNT } ?: try {
taskDao.count(item) taskDao.count(item)
@ -166,7 +161,7 @@ class MainActivityViewModel @Inject constructor(
.map { item -> .map { item ->
DrawerItem.Filter( DrawerItem.Filter(
title = item.title ?: "", title = item.title ?: "",
icon = getIcon(item), icon = item.getIcon(inventory),
color = getColor(item), color = getColor(item),
count = item.count.takeIf { it != NO_COUNT } ?: try { count = item.count.takeIf { it != NO_COUNT } ?: try {
taskDao.count(item) taskDao.count(item)
@ -192,24 +187,6 @@ class MainActivityViewModel @Inject constructor(
return 0 return 0
} }
private fun getIcon(filter: Filter): Int {
if (filter.icon < 1000 || filter.icon == CustomIcons.PLACE || inventory.hasPro) {
val icon = CustomIcons.getIconResId(filter.icon)
if (icon != null) {
return icon
}
}
return when (filter) {
is TagFilter -> R.drawable.ic_outline_label_24px
is GtasksFilter,
is CaldavFilter -> R.drawable.ic_list_24px
is CustomFilter -> R.drawable.ic_outline_filter_list_24px
is PlaceFilter -> R.drawable.ic_outline_place_24px
else -> filter.icon
}
}
fun toggleCollapsed(subheader: NavigationDrawerSubheader) = viewModelScope.launch { fun toggleCollapsed(subheader: NavigationDrawerSubheader) = viewModelScope.launch {
val collapsed = !subheader.isCollapsed val collapsed = !subheader.isCollapsed
when (subheader.subheaderType) { when (subheader.subheaderType) {

@ -5,21 +5,23 @@ import android.view.View
import android.widget.CheckedTextView import android.widget.CheckedTextView
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.ui.graphics.Color
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.tasks.filters.CaldavFilter import kotlinx.coroutines.flow.MutableStateFlow
import com.todoroo.astrid.api.CustomFilter import kotlinx.coroutines.flow.update
import org.tasks.filters.GtasksFilter
import org.tasks.filters.TagFilter
import org.tasks.R import org.tasks.R
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.compose.components.imageVectorByName
import org.tasks.databinding.FilterAdapterRowBinding import org.tasks.databinding.FilterAdapterRowBinding
import org.tasks.extensions.formatNumber import org.tasks.extensions.formatNumber
import org.tasks.filters.CaldavFilter
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.PlaceFilter import org.tasks.filters.getIcon
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons.getIconResId
import org.tasks.themes.DrawableUtil
import java.util.Locale import java.util.Locale
class FilterViewHolder internal constructor( class FilterViewHolder internal constructor(
@ -34,9 +36,10 @@ class FilterViewHolder internal constructor(
private val row: View private val row: View
private val text: CheckedTextView private val text: CheckedTextView
private val icon: ImageView
private val size: TextView private val size: TextView
private val shareIndicator: ImageView private val shareIndicator: ImageView
private val icon = MutableStateFlow<String?>(null)
private val color = MutableStateFlow(0)
lateinit var filter: Filter lateinit var filter: Filter
@ -44,7 +47,15 @@ class FilterViewHolder internal constructor(
FilterAdapterRowBinding.bind(itemView).let { FilterAdapterRowBinding.bind(itemView).let {
row = it.row row = it.row
text = it.text text = it.text
icon = it.icon it.icon.setContent {
val label = icon.collectAsStateWithLifecycle().value
val tint = color.collectAsStateWithLifecycle().value
Icon(
imageVector = imageVectorByName(label!!)!!,
contentDescription = label,
tint = if (tint == 0) MaterialTheme.colorScheme.onSurface else Color(tint),
)
}
size = it.size size = it.size
shareIndicator = it.shareIndicator shareIndicator = it.shareIndicator
} }
@ -64,9 +75,8 @@ class FilterViewHolder internal constructor(
} else { } else {
text.isChecked = selected text.isChecked = selected
} }
val icon = getIcon(filter) icon.update { filter.getIcon(inventory) }
this.icon.setImageDrawable(DrawableUtil.getWrapped(context, icon)) color.update { getColor(filter) }
this.icon.drawable.setTint(getColor(filter))
text.text = filter.title text.text = filter.title
if (count == null || count == 0) { if (count == null || count == 0) {
size.visibility = View.INVISIBLE size.visibility = View.INVISIBLE
@ -97,21 +107,4 @@ class FilterViewHolder internal constructor(
} }
return context.getColor(R.color.text_primary) return context.getColor(R.color.text_primary)
} }
}
private fun getIcon(filter: Filter): Int {
if (filter.icon < 1000 || inventory.hasPro) {
val icon = getIconResId(filter.icon)
if (icon != null) {
return icon
}
}
return when (filter) {
is TagFilter -> R.drawable.ic_outline_label_24px
is GtasksFilter,
is CaldavFilter -> R.drawable.ic_list_24px
is CustomFilter -> R.drawable.ic_outline_filter_list_24px
is PlaceFilter -> R.drawable.ic_outline_place_24px
else -> filter.icon
}
}
}

@ -3,7 +3,7 @@ package com.todoroo.astrid.api
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.FilterListItem import org.tasks.filters.FilterListItem
import org.tasks.themes.CustomIcons import org.tasks.themes.TasksIcons
@Parcelize @Parcelize
data class CustomFilter( data class CustomFilter(
@ -25,8 +25,10 @@ data class CustomFilter(
val id: Long val id: Long
get() = filter.id get() = filter.id
override val icon: Int
get() = filter.icon ?: CustomIcons.FILTER override val icon: String
get() = filter.icon ?: TasksIcons.FILTER_LIST
override val tint: Int override val tint: Int
get() = filter.color ?: 0 get() = filter.color ?: 0

@ -27,6 +27,7 @@ import org.tasks.filters.SnoozedFilter
import org.tasks.filters.TimerFilter import org.tasks.filters.TimerFilter
import org.tasks.filters.TodayFilter import org.tasks.filters.TodayFilter
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.themes.TasksIcons
import javax.inject.Inject import javax.inject.Inject
class BuiltInFilterExposer @Inject constructor( class BuiltInFilterExposer @Inject constructor(
@ -73,14 +74,14 @@ class BuiltInFilterExposer @Inject constructor(
.join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID))) .join(Join.left(CaldavTask.TABLE, CaldavTask.TASK.eq(Task.ID)))
.where(CaldavTask.ID.eq(null)) .where(CaldavTask.ID.eq(null))
.toString(), .toString(),
icon = R.drawable.ic_outline_cloud_off_24px, icon = TasksIcons.CLOUD_OFF,
) )
fun getDeleted() = fun getDeleted() =
FilterImpl( FilterImpl(
title = "Deleted", title = "Deleted",
sql = QueryTemplate().where(Task.DELETION_DATE.gt(0)).toString(), sql = QueryTemplate().where(Task.DELETION_DATE.gt(0)).toString(),
icon = R.drawable.ic_outline_delete_24px, icon = TasksIcons.DELETE,
) )
fun getMissingListFilter() = fun getMissingListFilter() =
@ -96,7 +97,7 @@ class BuiltInFilterExposer @Inject constructor(
) )
.where(and(CaldavTask.ID.gt(0), CaldavCalendar.UUID.eq(null))) .where(and(CaldavTask.ID.gt(0), CaldavCalendar.UUID.eq(null)))
.toString(), .toString(),
icon = R.drawable.ic_outline_cloud_off_24px, icon = TasksIcons.CLOUD_OFF,
) )
fun getMissingAccountFilter() = fun getMissingAccountFilter() =
@ -114,28 +115,28 @@ class BuiltInFilterExposer @Inject constructor(
) )
.where(and(CaldavTask.ID.gt(0), CaldavAccount.UUID.eq(null))) .where(and(CaldavTask.ID.gt(0), CaldavAccount.UUID.eq(null)))
.toString(), .toString(),
icon = R.drawable.ic_outline_cloud_off_24px, icon = TasksIcons.CLOUD_OFF,
) )
fun getNoTitleFilter() = fun getNoTitleFilter() =
FilterImpl( FilterImpl(
title = "No title", title = "No title",
sql = QueryTemplate().where(or(Task.TITLE.eq(null), Task.TITLE.eq(""))).toString(), sql = QueryTemplate().where(or(Task.TITLE.eq(null), Task.TITLE.eq(""))).toString(),
icon = R.drawable.ic_outline_clear_24px, icon = TasksIcons.CLEAR,
) )
fun getNoCreateDateFilter() = fun getNoCreateDateFilter() =
FilterImpl( FilterImpl(
title = "No create time", title = "No create time",
sql = QueryTemplate().where(Task.CREATION_DATE.eq(0)).toString(), sql = QueryTemplate().where(Task.CREATION_DATE.eq(0)).toString(),
icon = R.drawable.ic_outline_add_24px, icon = TasksIcons.ADD,
) )
fun getNoModificationDateFilter() = fun getNoModificationDateFilter() =
FilterImpl( FilterImpl(
title = "No modify time", title = "No modify time",
sql = QueryTemplate().where(Task.MODIFICATION_DATE.eq(0)).toString(), sql = QueryTemplate().where(Task.MODIFICATION_DATE.eq(0)).toString(),
icon = R.drawable.ic_outline_edit_24px, icon = TasksIcons.EDIT,
) )
fun getRecentlyModifiedFilter(r: Resources) = fun getRecentlyModifiedFilter(r: Resources) =

@ -0,0 +1,253 @@
@file:Suppress("ClassName")
package com.todoroo.astrid.service
import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.FilterDao
import org.tasks.data.dao.LocationDao
import org.tasks.data.dao.TagDataDao
import org.tasks.themes.TasksIcons
import org.tasks.themes.TasksIcons.ALL_INBOX
import org.tasks.themes.TasksIcons.CLEAR
import org.tasks.themes.TasksIcons.CLOUD
import org.tasks.themes.TasksIcons.DELETE
import org.tasks.themes.TasksIcons.EDIT
import org.tasks.themes.TasksIcons.FILTER_LIST
import org.tasks.themes.TasksIcons.HISTORY
import org.tasks.themes.TasksIcons.LABEL
import org.tasks.themes.TasksIcons.LABEL_OFF
import org.tasks.themes.TasksIcons.NOTIFICATIONS
import org.tasks.themes.TasksIcons.PENDING_ACTIONS
import org.tasks.themes.TasksIcons.PLACE
import org.tasks.themes.TasksIcons.TIMER
import org.tasks.themes.TasksIcons.TODAY
import javax.inject.Inject
class Upgrade_13_11 @Inject constructor(
private val locationDao: LocationDao,
private val filterDao: FilterDao,
private val tagDataDao: TagDataDao,
private val caldavDao: CaldavDao,
) {
internal suspend fun migrateIcons() {
locationDao.getPlaces().forEach {
locationDao.update(it.copy(icon = it.icon.migrateLegacyIcon()))
}
filterDao.getFilters().forEach {
filterDao.update(it.copy(icon = it.icon.migrateLegacyIcon()))
}
tagDataDao.getAll().forEach {
tagDataDao.update(it.copy(icon = it.icon.migrateLegacyIcon()))
}
caldavDao.getCalendars().forEach {
caldavDao.update(it.copy(icon = it.icon.migrateLegacyIcon()))
}
}
companion object {
const val VERSION = 131100
fun String?.migrateLegacyIcon(): String? =
LEGACY_ICONS[this?.toIntOrNull()] ?: this
private val LEGACY_ICONS by lazy {
mapOf(
1 to LABEL,
2 to FILTER_LIST,
3 to CLOUD,
4 to ALL_INBOX,
5 to LABEL_OFF,
6 to HISTORY,
7 to TODAY,
8 to TasksIcons.LIST,
1000 to "flag",
1062 to "home",
1041 to "work_outline",
1001 to "pets",
1002 to "payment",
1003 to "attach_money",
1059 to "euro_symbol",
1042 to "store",
1043 to "shopping_cart",
1004 to "hourglass_empty",
1005 to "favorite_border",
1006 to "school",
1007 to "drive_eta",
1008 to "whatshot",
1009 to "star_border",
1010 to "account_balance",
1011 to "location_city",
1012 to "cake",
1013 to "kitchen",
1014 to "fitness_center",
1015 to "child_friendly",
1016 to "free_breakfast",
1017 to "golf_course",
1018 to "beach_access",
1019 to "restaurant_menu",
1020 to "local_pharmacy",
1021 to "fastfood",
1022 to "hotel",
1023 to "flight",
1057 to "flight_takeoff",
1058 to "flight_land",
1024 to "directions_run",
1025 to "wb_sunny",
1026 to "desktop_mac",
1027 to "computer",
1028 to "format_paint",
1029 to "storage",
1030 to "send",
1031 to "weekend",
1032 to "link",
1033 to "business",
1034 to "chat_bubble_outline",
1035 to "voicemail",
1036 to "email",
1037 to "call",
1039 to "movie",
1040 to "equalizer",
1071 to "pie_chart",
1072 to "show_chart",
1044 to "schedule",
1045 to "photo_camera",
1046 to DELETE,
1047 to "attachment",
1048 to "vpn_key",
1049 to "event",
1050 to PLACE,
1051 to "markunread_mailbox",
1052 to "label_important",
1053 to "android",
1054 to "build",
1055 to "bug_report",
1056 to "book",
1060 to "explore",
1061 to "gavel",
1063 to "print",
1064 to "receipt",
1038 to "new_releases",
1065 to "report_problem",
1068 to "error_outline",
1069 to "not_interested",
1070 to "report",
1066 to "turned_in",
1067 to "turned_in_not",
1073 to "headset",
1074 to "mic_none",
1075 to TIMER,
1076 to CLEAR,
1077 to "search",
1078 to "repeat",
1079 to NOTIFICATIONS,
1080 to "star_half",
1081 to "share",
1082 to "sentiment_very_satisfied",
1083 to "sentiment_very_dissatisfied",
1084 to "sentiment_satisfied",
1085 to "sentiment_dissatisfied",
1086 to "mood_bad",
1087 to "mood",
1088 to "spa",
1089 to "room_service",
1090 to "meeting_room",
1091 to "hot_tub",
1092 to "business_center",
1093 to "priority_high",
1094 to "power",
1095 to "power_off",
1096 to "directions_bike",
1097 to "local_florist",
1098 to "local_pizza",
1099 to "navigation",
1100 to "local_play",
1101 to "local_bar",
1102 to "local_laundry_service",
1103 to "local_offer",
1104 to "local_shipping",
1105 to "local_hospital",
1106 to "directions_boat",
1107 to "directions_walk",
1108 to "wb_incandescent",
1109 to "landscape",
1110 to "music_note",
1111 to "healing",
1112 to "brush",
1113 to "brightness_2",
1114 to "security",
1115 to "scanner",
1116 to "router",
1117 to "watch",
1118 to "videogame_asset",
1119 to "cached",
// 1120 to "ic_octocat",
1121 to "perm_identity",
1122 to "track_changes",
1123 to "open_in_new",
1124 to EDIT,
1125 to "info",
1126 to "palette",
1127 to "sd_storage",
1128 to "baseline_lens",
1129 to "map",
1130 to "check_blackdp",
1131 to "undo",
1132 to "next_week",
1133 to "local_cafe",
1134 to "nights_stay",
1135 to "single_bed",
1136 to "weather_sunset",
1137 to "calendar_today",
1138 to "select_all",
1139 to "widgets",
1140 to "call_split",
1141 to "ac_unit",
1142 to "airport_shuttle",
1143 to "apartment",
1144 to "bathtub",
1145 to "casino",
1146 to "child_care",
1147 to "pool",
1148 to "house",
1149 to "storefront",
1150 to "poll",
1151 to "emoji_transportation",
1152 to "emoji_objects",
1153 to "emoji_nature",
1154 to "emoji_food_beverage",
1155 to "emoji_events",
1156 to "deck",
1157 to "fireplace",
1158 to "outdoor_grill",
1159 to "thumb_up",
1160 to "thumb_down",
1161 to "vertical_align_top",
1162 to "keyboard_arrow_left",
1163 to "keyboard_arrow_right",
1164 to "content_paste",
1165 to "content_copy",
1166 to "play_arrow",
1167 to "play_circle_outline",
1168 to "not_started",
1169 to "date_range",
1170 to PENDING_ACTIONS,
1171 to "visibility_off",
1172 to "nature",
1173 to "eco",
1174 to "bedtime",
1175 to "auto_stories",
1176 to "flash_on",
1177 to "wb_twilight",
1178 to "local_atm",
1179 to "cleaning_services",
1180 to "plumbing",
1181 to "pest_control_rodent",
1182 to "people_outline",
1183 to "forum",
// 1184 to "twitter_logo_black",
1185 to "person_add",
1186 to "block",
)
}
}
}

@ -64,6 +64,7 @@ class Upgrader @Inject constructor(
private val upgrade_11_12_3: Lazy<Upgrade_11_12_3>, private val upgrade_11_12_3: Lazy<Upgrade_11_12_3>,
private val upgrade_12_4: Lazy<Upgrade_12_4>, private val upgrade_12_4: Lazy<Upgrade_12_4>,
private val upgrade_13_2: Lazy<Upgrade_13_2>, private val upgrade_13_2: Lazy<Upgrade_13_2>,
private val upgrade_13_11: Lazy<Upgrade_13_11>,
) { ) {
fun upgrade(from: Int, to: Int) { fun upgrade(from: Int, to: Int) {
@ -114,6 +115,9 @@ class Upgrader @Inject constructor(
caldavDao.updateParents() caldavDao.updateParents()
upgrade_13_2.get().rebuildFilters() upgrade_13_2.get().rebuildFilters()
} }
run(from, Upgrade_13_11.VERSION) {
upgrade_13_11.get().migrateIcons()
}
preferences.setBoolean(R.string.p_just_updated, true) preferences.setBoolean(R.string.p_just_updated, true)
} else { } else {
setInstallDetails(to) setInstallDetails(to)

@ -1,6 +1,5 @@
package org.tasks.activities package org.tasks.activities
import android.content.DialogInterface
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem import android.view.MenuItem
@ -8,36 +7,51 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.tasks.R import org.tasks.R
import org.tasks.compose.IconPickerActivity.Companion.launchIconPicker
import org.tasks.compose.IconPickerActivity.Companion.registerForIconPickerResult
import org.tasks.compose.components.imageVectorByName
import org.tasks.dialogs.ColorPalettePicker import org.tasks.dialogs.ColorPalettePicker
import org.tasks.dialogs.ColorPalettePicker.Companion.newColorPalette import org.tasks.dialogs.ColorPalettePicker.Companion.newColorPalette
import org.tasks.dialogs.ColorPickerAdapter.Palette import org.tasks.dialogs.ColorPickerAdapter.Palette
import org.tasks.dialogs.ColorWheelPicker import org.tasks.dialogs.ColorWheelPicker
import org.tasks.dialogs.DialogBuilder import org.tasks.dialogs.DialogBuilder
import org.tasks.dialogs.IconPickerDialog
import org.tasks.dialogs.IconPickerDialog.IconPickerCallback
import org.tasks.extensions.addBackPressedCallback import org.tasks.extensions.addBackPressedCallback
import org.tasks.injection.ThemedInjectingAppCompatActivity import org.tasks.injection.ThemedInjectingAppCompatActivity
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons.getIconResId
import org.tasks.themes.DrawableUtil import org.tasks.themes.DrawableUtil
import org.tasks.themes.TasksTheme
import org.tasks.themes.ThemeColor import org.tasks.themes.ThemeColor
import javax.inject.Inject import javax.inject.Inject
abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), IconPickerCallback, Toolbar.OnMenuItemClickListener, ColorPalettePicker.ColorPickedCallback, ColorWheelPicker.ColorPickedCallback { abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Toolbar.OnMenuItemClickListener, ColorPalettePicker.ColorPickedCallback, ColorWheelPicker.ColorPickedCallback {
@Inject lateinit var dialogBuilder: DialogBuilder @Inject lateinit var dialogBuilder: DialogBuilder
@Inject lateinit var colorProvider: ColorProvider @Inject lateinit var colorProvider: ColorProvider
protected abstract val defaultIcon: String
protected var selectedColor = 0 protected var selectedColor = 0
protected var selectedIcon = -1 protected var selectedIcon = MutableStateFlow<String?>(null)
private lateinit var clear: View private lateinit var clear: View
private lateinit var color: TextView private lateinit var color: TextView
private lateinit var icon: TextView
protected lateinit var toolbar: Toolbar protected lateinit var toolbar: Toolbar
protected lateinit var colorRow: ViewGroup protected lateinit var colorRow: ViewGroup
protected abstract val defaultIcon: Int
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -50,12 +64,36 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
colorRow = findViewById<ViewGroup>(R.id.color_row).apply { colorRow = findViewById<ViewGroup>(R.id.color_row).apply {
setOnClickListener { showThemePicker() } setOnClickListener { showThemePicker() }
} }
icon = findViewById(R.id.icon) findViewById<ComposeView>(R.id.icon).setContent {
TasksTheme {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
val name = selectedIcon.collectAsStateWithLifecycle().value
val icon = imageVectorByName(name ?:defaultIcon)
if (icon != null) {
Image(
imageVector = icon,
contentDescription = name ?: defaultIcon,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurface),
)
}
Spacer(modifier = Modifier.width(34.dp))
Text(
text = "Icon",
style = MaterialTheme.typography.bodyLarge.copy(
fontSize = 18.sp,
),
color = MaterialTheme.colorScheme.onSurface,
)
}
}
}
findViewById<View>(R.id.icon_row).setOnClickListener { showIconPicker() } findViewById<View>(R.id.icon_row).setOnClickListener { showIconPicker() }
toolbar = view.findViewById(R.id.toolbar) toolbar = view.findViewById(R.id.toolbar)
if (savedInstanceState != null) { if (savedInstanceState != null) {
selectedColor = savedInstanceState.getInt(EXTRA_SELECTED_THEME) selectedColor = savedInstanceState.getInt(EXTRA_SELECTED_THEME)
selectedIcon = savedInstanceState.getInt(EXTRA_SELECTED_ICON) selectedIcon.update { savedInstanceState.getString(EXTRA_SELECTED_ICON) }
} }
toolbar.title = toolbarTitle toolbar.title = toolbarTitle
toolbar.navigationIcon = getDrawable(R.drawable.ic_outline_save_24px) toolbar.navigationIcon = getDrawable(R.drawable.ic_outline_save_24px)
@ -73,7 +111,7 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putInt(EXTRA_SELECTED_THEME, selectedColor) outState.putInt(EXTRA_SELECTED_THEME, selectedColor)
outState.putInt(EXTRA_SELECTED_ICON, selectedIcon) outState.putString(EXTRA_SELECTED_ICON, selectedIcon.value)
} }
protected abstract fun hasChanges(): Boolean protected abstract fun hasChanges(): Boolean
@ -103,14 +141,12 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
.show(supportFragmentManager, FRAG_TAG_COLOR_PICKER) .show(supportFragmentManager, FRAG_TAG_COLOR_PICKER)
} }
private fun showIconPicker() { val launcher = registerForIconPickerResult { selected ->
IconPickerDialog.newIconPicker(selectedIcon).show(supportFragmentManager, FRAG_TAG_ICON_PICKER) selectedIcon.update { selected }
} }
override fun onSelected(dialogInterface: DialogInterface, icon: Int) { private fun showIconPicker() {
selectedIcon = icon launcher.launchIconPicker(this, selectedIcon.value)
dialogInterface.dismiss()
updateTheme()
} }
override fun onColorPicked(color: Int) { override fun onColorPicked(color: Int) {
@ -150,9 +186,6 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
clear.visibility = View.VISIBLE clear.visibility = View.VISIBLE
} }
themeColor.applyToNavigationBar(this) themeColor.applyToNavigationBar(this)
val icon = getIconResId(selectedIcon) ?: getIconResId(defaultIcon)
DrawableUtil.setLeftDrawable(this, this.icon, icon!!)
DrawableUtil.getLeftDrawable(this.icon).setTint(getColor(R.color.icon_tint_with_alpha))
} }
companion object { companion object {
@ -161,4 +194,4 @@ abstract class BaseListSettingsActivity : ThemedInjectingAppCompatActivity(), Ic
private const val FRAG_TAG_ICON_PICKER = "frag_tag_icon_picker" private const val FRAG_TAG_ICON_PICKER = "frag_tag_icon_picker"
private const val FRAG_TAG_COLOR_PICKER = "frag_tag_color_picker" private const val FRAG_TAG_COLOR_PICKER = "frag_tag_color_picker"
} }
} }

@ -33,6 +33,7 @@ import com.todoroo.astrid.core.CustomFilterItemTouchHelper
import org.tasks.data.db.Database import org.tasks.data.db.Database
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
@ -49,7 +50,7 @@ import org.tasks.extensions.Context.openUri
import org.tasks.extensions.hideKeyboard import org.tasks.extensions.hideKeyboard
import org.tasks.filters.FilterCriteriaProvider import org.tasks.filters.FilterCriteriaProvider
import org.tasks.filters.mapToSerializedString import org.tasks.filters.mapToSerializedString
import org.tasks.themes.CustomIcons import org.tasks.themes.TasksIcons
import java.util.Locale import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
@ -70,14 +71,14 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
private var filter: CustomFilter? = null private var filter: CustomFilter? = null
private lateinit var adapter: CustomFilterAdapter private lateinit var adapter: CustomFilterAdapter
private var criteria: MutableList<CriterionInstance> = ArrayList() private var criteria: MutableList<CriterionInstance> = ArrayList()
override val defaultIcon: Int = CustomIcons.FILTER override val defaultIcon = TasksIcons.FILTER_LIST
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
filter = intent.getParcelableExtra(TOKEN_FILTER) filter = intent.getParcelableExtra(TOKEN_FILTER)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (savedInstanceState == null && filter != null) { if (savedInstanceState == null && filter != null) {
selectedColor = filter!!.tint selectedColor = filter!!.tint
selectedIcon = filter!!.icon selectedIcon.update { filter!!.icon }
name.setText(filter!!.title) name.setText(filter!!.title)
} }
when { when {
@ -245,7 +246,7 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
id = filter?.id ?: 0L, id = filter?.id ?: 0L,
title = newName, title = newName,
color = selectedColor, color = selectedColor,
icon = selectedIcon, icon = selectedIcon.value,
values = criteria.values, values = criteria.values,
criterion = CriterionInstance.serialize(criteria), criterion = CriterionInstance.serialize(criteria),
sql = criteria.sql, sql = criteria.sql,
@ -276,10 +277,10 @@ class FilterSettingsActivity : BaseListSettingsActivity() {
override fun hasChanges(): Boolean { override fun hasChanges(): Boolean {
return if (isNew) { return if (isNew) {
(!Strings.isNullOrEmpty(newName) (!Strings.isNullOrEmpty(newName)
|| selectedColor != 0 || selectedIcon != -1 || criteria.size > 1) || selectedColor != 0 || selectedIcon.value?.isBlank() == false || criteria.size > 1)
} else newName != filter!!.title } else newName != filter!!.title
|| selectedColor != filter!!.tint || selectedColor != filter!!.tint
|| selectedIcon != filter!!.icon || selectedIcon.value != filter!!.icon
|| CriterionInstance.serialize(criteria) != filter!!.criterion!!.trim() || CriterionInstance.serialize(criteria) != filter!!.criterion!!.trim()
|| criteria.values != filter!!.valuesForNewTasks || criteria.values != filter!!.valuesForNewTasks
|| criteria.sql != filter!!.sql || criteria.sql != filter!!.sql

@ -13,22 +13,23 @@ import com.google.android.material.textfield.TextInputEditText
import com.google.api.services.tasks.model.TaskList import com.google.api.services.tasks.model.TaskList
import com.todoroo.astrid.activity.MainActivity import com.todoroo.astrid.activity.MainActivity
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import org.tasks.filters.GtasksFilter
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.data.entity.CaldavAccount import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.dao.GoogleTaskListDao
import org.tasks.databinding.ActivityGoogleTaskListSettingsBinding import org.tasks.databinding.ActivityGoogleTaskListSettingsBinding
import org.tasks.extensions.Context.hideKeyboard import org.tasks.extensions.Context.hideKeyboard
import org.tasks.extensions.Context.toast import org.tasks.extensions.Context.toast
import org.tasks.themes.CustomIcons import org.tasks.filters.GtasksFilter
import org.tasks.themes.TasksIcons
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -46,7 +47,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private val createListViewModel: CreateListViewModel by viewModels() private val createListViewModel: CreateListViewModel by viewModels()
private val renameListViewModel: RenameListViewModel by viewModels() private val renameListViewModel: RenameListViewModel by viewModels()
private val deleteListViewModel: DeleteListViewModel by viewModels() private val deleteListViewModel: DeleteListViewModel by viewModels()
override val defaultIcon: Int = CustomIcons.LIST override val defaultIcon = TasksIcons.LIST
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
gtasksList = intent.getParcelableExtra(EXTRA_STORE_DATA) gtasksList = intent.getParcelableExtra(EXTRA_STORE_DATA)
@ -58,7 +59,7 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (savedInstanceState == null) { if (savedInstanceState == null) {
selectedColor = gtasksList.color selectedColor = gtasksList.color
selectedIcon = gtasksList.getIcon()!! selectedIcon.update { gtasksList.icon }
} }
if (isNewList) { if (isNewList) {
name.requestFocus() name.requestFocus()
@ -115,8 +116,11 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
else -> { else -> {
if (colorChanged() || iconChanged()) { if (colorChanged() || iconChanged()) {
gtasksList.color = selectedColor gtasksList.color = selectedColor
gtasksList.setIcon(selectedIcon) googleTaskListDao.insertOrReplace(
googleTaskListDao.insertOrReplace(gtasksList) gtasksList.copy(
icon = selectedIcon.value
)
)
localBroadcastManager.broadcastRefresh() localBroadcastManager.broadcastRefresh()
setResult( setResult(
Activity.RESULT_OK, Activity.RESULT_OK,
@ -166,21 +170,22 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
private fun colorChanged() = selectedColor != gtasksList.color private fun colorChanged() = selectedColor != gtasksList.color
private fun iconChanged() = selectedIcon != gtasksList.getIcon() private fun iconChanged() = selectedIcon.value != gtasksList.icon
private fun nameChanged() = newName != gtasksList.name private fun nameChanged() = newName != gtasksList.name
private suspend fun onListCreated(taskList: TaskList) { private suspend fun onListCreated(taskList: TaskList) {
with(gtasksList) { val result = gtasksList.copy(
uuid = taskList.id uuid = taskList.id,
name = taskList.title name = taskList.title,
color = selectedColor color = selectedColor,
setIcon(selectedIcon) icon = selectedIcon.value,
id = googleTaskListDao.insertOrReplace(this) )
} val id = googleTaskListDao.insertOrReplace(result)
setResult( setResult(
Activity.RESULT_OK, Intent().putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList))) Activity.RESULT_OK,
Intent().putExtra(MainActivity.OPEN_FILTER, GtasksFilter(result.copy(id = id))))
finish() finish()
} }
@ -197,17 +202,17 @@ class GoogleTaskListSettingsActivity : BaseListSettingsActivity() {
} }
private suspend fun onListRenamed(taskList: TaskList) { private suspend fun onListRenamed(taskList: TaskList) {
with(gtasksList) { val result = gtasksList.copy(
name = taskList.title name = taskList.title,
color = selectedColor color = selectedColor,
setIcon(selectedIcon) icon = selectedIcon.value,
googleTaskListDao.insertOrReplace(this) )
} googleTaskListDao.insertOrReplace(result)
setResult( setResult(
Activity.RESULT_OK, Activity.RESULT_OK,
Intent(TaskListFragment.ACTION_RELOAD) Intent(TaskListFragment.ACTION_RELOAD)
.putExtra(MainActivity.OPEN_FILTER, GtasksFilter(gtasksList))) .putExtra(MainActivity.OPEN_FILTER, GtasksFilter(result)))
finish() finish()
} }

@ -10,6 +10,7 @@ import com.google.android.material.textfield.TextInputLayout
import com.todoroo.astrid.activity.MainActivity import com.todoroo.astrid.activity.MainActivity
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.update
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
@ -22,7 +23,7 @@ import org.tasks.extensions.formatNumber
import org.tasks.filters.PlaceFilter import org.tasks.filters.PlaceFilter
import org.tasks.location.MapFragment import org.tasks.location.MapFragment
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.themes.CustomIcons import org.tasks.themes.TasksIcons
import java.util.Locale import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -49,7 +50,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
@Inject lateinit var localBroadcastManager: LocalBroadcastManager @Inject lateinit var localBroadcastManager: LocalBroadcastManager
private lateinit var place: Place private lateinit var place: Place
override val defaultIcon: Int = CustomIcons.PLACE override val defaultIcon = TasksIcons.PLACE
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
if (intent?.hasExtra(EXTRA_PLACE) != true) { if (intent?.hasExtra(EXTRA_PLACE) != true) {
@ -69,7 +70,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
if (savedInstanceState == null) { if (savedInstanceState == null) {
name.setText(place.displayName) name.setText(place.displayName)
selectedColor = place.color selectedColor = place.color
selectedIcon = place.icon selectedIcon.update { place.icon }
} }
val dark = preferences.mapTheme == 2 val dark = preferences.mapTheme == 2
@ -106,7 +107,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
override fun hasChanges() = name.text.toString() != place.displayName override fun hasChanges() = name.text.toString() != place.displayName
|| selectedColor != place.color || selectedColor != place.color
|| selectedIcon != place.icon || selectedIcon.value != place.icon
override suspend fun save() { override suspend fun save() {
val newName: String = name.text.toString() val newName: String = name.text.toString()
@ -119,7 +120,7 @@ class PlaceSettingsActivity : BaseListSettingsActivity(), MapFragment.MapFragmen
place = place.copy( place = place.copy(
name = newName, name = newName,
color = selectedColor, color = selectedColor,
icon = selectedIcon, icon = selectedIcon.value,
radius = slider.value.toInt(), radius = slider.value.toInt(),
) )
locationDao.update(place) locationDao.update(place)

@ -15,8 +15,8 @@ import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.todoroo.astrid.activity.MainActivity import com.todoroo.astrid.activity.MainActivity
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import org.tasks.filters.TagFilter
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.update
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.R import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
@ -25,7 +25,8 @@ import org.tasks.data.dao.TagDataDao
import org.tasks.data.entity.TagData import org.tasks.data.entity.TagData
import org.tasks.databinding.ActivityTagSettingsBinding import org.tasks.databinding.ActivityTagSettingsBinding
import org.tasks.extensions.Context.hideKeyboard import org.tasks.extensions.Context.hideKeyboard
import org.tasks.themes.CustomIcons import org.tasks.filters.TagFilter
import org.tasks.themes.TasksIcons
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
@ -41,14 +42,14 @@ class TagSettingsActivity : BaseListSettingsActivity() {
private val isNewTag: Boolean private val isNewTag: Boolean
get() = tagData.id == null get() = tagData.id == null
override val defaultIcon: Int = CustomIcons.LABEL override val defaultIcon = TasksIcons.LABEL
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
tagData = intent.getParcelableExtra(EXTRA_TAG_DATA) ?: TagData() tagData = intent.getParcelableExtra(EXTRA_TAG_DATA) ?: TagData()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (savedInstanceState == null) { if (savedInstanceState == null) {
selectedColor = tagData.color ?: 0 selectedColor = tagData.color ?: 0
selectedIcon = tagData.getIcon()!! selectedIcon.update { tagData.icon }
} }
name.setText(tagData.name) name.setText(tagData.name)
if (isNewTag) { if (isNewTag) {
@ -88,7 +89,7 @@ class TagSettingsActivity : BaseListSettingsActivity() {
.copy( .copy(
name = newName, name = newName,
color = selectedColor, color = selectedColor,
icon = selectedIcon, icon = selectedIcon.value,
) )
.let { it.copy(id = tagDataDao.insert(it)) } .let { it.copy(id = tagDataDao.insert(it)) }
.let { .let {
@ -103,7 +104,7 @@ class TagSettingsActivity : BaseListSettingsActivity() {
.copy( .copy(
name = newName, name = newName,
color = selectedColor, color = selectedColor,
icon = selectedIcon, icon = selectedIcon.value,
) )
.let { .let {
tagDataDao.update(it) tagDataDao.update(it)
@ -121,10 +122,10 @@ class TagSettingsActivity : BaseListSettingsActivity() {
override fun hasChanges(): Boolean { override fun hasChanges(): Boolean {
return if (isNewTag) { return if (isNewTag) {
selectedColor >= 0 || selectedIcon >= 0 || !isNullOrEmpty(newName) selectedColor >= 0 || selectedIcon.value?.isBlank() == false || !isNullOrEmpty(newName)
} else { } else {
selectedColor != (tagData.color ?: 0) selectedColor != (tagData.color ?: 0)
|| selectedIcon != tagData.getIcon() || selectedIcon.value != tagData.icon
|| newName != tagData.name || newName != tagData.name
} }
} }

@ -7,6 +7,7 @@ import android.os.Handler
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.service.TaskCreator.Companion.getDefaultAlarms import com.todoroo.astrid.service.TaskCreator.Companion.getDefaultAlarms
import com.todoroo.astrid.service.TaskMover import com.todoroo.astrid.service.TaskMover
import com.todoroo.astrid.service.Upgrade_13_11.Companion.migrateLegacyIcon
import com.todoroo.astrid.service.Upgrade_13_2 import com.todoroo.astrid.service.Upgrade_13_2
import com.todoroo.astrid.service.Upgrader import com.todoroo.astrid.service.Upgrader
import com.todoroo.astrid.service.Upgrader.Companion.V12_4 import com.todoroo.astrid.service.Upgrader.Companion.V12_4
@ -99,7 +100,10 @@ class TasksJsonImporter @Inject constructor(
return@forEach return@forEach
} }
tagDataDao.insert( tagDataDao.insert(
tagData.copy(color = themeToColor(context, version, tagData.color ?: 0)) tagData.copy(
color = themeToColor(context, version, tagData.color ?: 0),
icon = tagData.icon.migrateLegacyIcon(),
)
) )
} }
backupContainer.googleTaskAccounts?.forEach { googleTaskAccount -> backupContainer.googleTaskAccounts?.forEach { googleTaskAccount ->
@ -116,7 +120,11 @@ class TasksJsonImporter @Inject constructor(
} }
backupContainer.places?.forEach { place -> backupContainer.places?.forEach { place ->
if (locationDao.getByUid(place.uid!!) == null) { if (locationDao.getByUid(place.uid!!) == null) {
locationDao.insert(place) locationDao.insert(
place.copy(
icon = place.icon.migrateLegacyIcon(),
)
)
} }
} }
backupContainer.googleTaskLists?.forEach { googleTaskList -> backupContainer.googleTaskLists?.forEach { googleTaskList ->
@ -126,7 +134,7 @@ class TasksJsonImporter @Inject constructor(
account = googleTaskList.account, account = googleTaskList.account,
uuid = googleTaskList.remoteId, uuid = googleTaskList.remoteId,
color = themeToColor(context, version, googleTaskList.color ?: 0), color = themeToColor(context, version, googleTaskList.color ?: 0),
icon = googleTaskList.icon?.toString().migrateLegacyIcon(),
) )
) )
} }
@ -139,7 +147,8 @@ class TasksJsonImporter @Inject constructor(
if (filterDao.getByName(filter.title!!) == null) { if (filterDao.getByName(filter.title!!) == null) {
filterDao.insert( filterDao.insert(
filter.copy( filter.copy(
color = themeToColor(context, version, filter.color ?: 0) color = themeToColor(context, version, filter.color ?: 0),
icon = filter.icon.migrateLegacyIcon(),
) )
) )
} }
@ -152,7 +161,10 @@ class TasksJsonImporter @Inject constructor(
backupContainer.caldavCalendars?.forEach { calendar -> backupContainer.caldavCalendars?.forEach { calendar ->
if (caldavDao.getCalendarByUuid(calendar.uuid!!) == null) { if (caldavDao.getCalendarByUuid(calendar.uuid!!) == null) {
caldavDao.insert( caldavDao.insert(
calendar.copy(color = themeToColor(context, version, calendar.color)) calendar.copy(
color = themeToColor(context, version, calendar.color),
icon = calendar.icon.migrateLegacyIcon(),
)
) )
} }
} }

@ -47,9 +47,11 @@ class PurchaseActivity : AppCompatActivity(), OnPurchasesUpdated {
theme.applyToContext(this) theme.applyToContext(this)
savedInstanceState?.let { if (savedInstanceState == null) {
nameYourPrice.value = it.getBoolean(EXTRA_NAME_YOUR_PRICE) nameYourPrice.value = intent?.extras?.getBoolean(EXTRA_NAME_YOUR_PRICE) ?: false
sliderPosition.value = it.getFloat(EXTRA_PRICE) } else {
nameYourPrice.value = savedInstanceState.getBoolean(EXTRA_NAME_YOUR_PRICE)
sliderPosition.value = savedInstanceState.getFloat(EXTRA_PRICE)
} }
setContent { setContent {
@ -128,6 +130,6 @@ class PurchaseActivity : AppCompatActivity(), OnPurchasesUpdated {
companion object { companion object {
const val EXTRA_GITHUB = "extra_github" const val EXTRA_GITHUB = "extra_github"
private const val EXTRA_PRICE = "extra_price" private const val EXTRA_PRICE = "extra_price"
private const val EXTRA_NAME_YOUR_PRICE = "extra_name_your_price" const val EXTRA_NAME_YOUR_PRICE = "extra_name_your_price"
} }
} }

@ -15,19 +15,20 @@ import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.todoroo.astrid.activity.MainActivity import com.todoroo.astrid.activity.MainActivity
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import org.tasks.filters.CaldavFilter
import org.tasks.data.UUIDHelper
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.tasks.R import org.tasks.R
import org.tasks.Strings.isNullOrEmpty import org.tasks.Strings.isNullOrEmpty
import org.tasks.activities.BaseListSettingsActivity import org.tasks.activities.BaseListSettingsActivity
import org.tasks.data.UUIDHelper
import org.tasks.data.dao.CaldavDao
import org.tasks.data.entity.CaldavAccount import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.dao.CaldavDao
import org.tasks.databinding.ActivityCaldavCalendarSettingsBinding import org.tasks.databinding.ActivityCaldavCalendarSettingsBinding
import org.tasks.extensions.Context.hideKeyboard import org.tasks.extensions.Context.hideKeyboard
import org.tasks.themes.CustomIcons import org.tasks.filters.CaldavFilter
import org.tasks.themes.TasksIcons
import org.tasks.ui.DisplayableException import org.tasks.ui.DisplayableException
import java.net.ConnectException import java.net.ConnectException
import javax.inject.Inject import javax.inject.Inject
@ -44,7 +45,7 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
protected var caldavCalendar: CaldavCalendar? = null protected var caldavCalendar: CaldavCalendar? = null
protected lateinit var caldavAccount: CaldavAccount protected lateinit var caldavAccount: CaldavAccount
override val defaultIcon: Int = CustomIcons.LIST override val defaultIcon = TasksIcons.LIST
override fun bind() = ActivityCaldavCalendarSettingsBinding.inflate(layoutInflater).let { override fun bind() = ActivityCaldavCalendarSettingsBinding.inflate(layoutInflater).let {
root = it.rootLayout root = it.rootLayout
@ -71,7 +72,7 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
if (caldavCalendar != null) { if (caldavCalendar != null) {
name.setText(caldavCalendar!!.name) name.setText(caldavCalendar!!.name)
selectedColor = caldavCalendar!!.color selectedColor = caldavCalendar!!.color
selectedIcon = caldavCalendar!!.getIcon()!! selectedIcon.update { caldavCalendar?.icon }
} }
} }
if (caldavCalendar == null) { if (caldavCalendar == null) {
@ -165,7 +166,7 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
url = url, url = url,
name = newName, name = newName,
color = selectedColor, color = selectedColor,
icon = selectedIcon, icon = selectedIcon.value,
) )
caldavDao.insert(caldavCalendar) caldavDao.insert(caldavCalendar)
setResult( setResult(
@ -175,20 +176,22 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
} }
protected suspend fun updateCalendar() { protected suspend fun updateCalendar() {
caldavCalendar!!.name = newName val result = caldavCalendar!!.copy(
caldavCalendar!!.color = selectedColor name = newName,
caldavCalendar!!.setIcon(selectedIcon) color = selectedColor,
caldavDao.update(caldavCalendar!!) icon = selectedIcon.value,
)
caldavDao.update(result)
setResult( setResult(
Activity.RESULT_OK, Activity.RESULT_OK,
Intent(TaskListFragment.ACTION_RELOAD) Intent(TaskListFragment.ACTION_RELOAD)
.putExtra(MainActivity.OPEN_FILTER, CaldavFilter(caldavCalendar!!))) .putExtra(MainActivity.OPEN_FILTER, CaldavFilter(result)))
finish() finish()
} }
override fun hasChanges(): Boolean = override fun hasChanges(): Boolean =
if (caldavCalendar == null) if (caldavCalendar == null)
!isNullOrEmpty(newName) || selectedColor != 0 || selectedIcon != -1 !isNullOrEmpty(newName) || selectedColor != 0 || selectedIcon.value?.isBlank() == false
else else
nameChanged() || iconChanged() || colorChanged() nameChanged() || iconChanged() || colorChanged()
@ -196,7 +199,7 @@ abstract class BaseCaldavCalendarSettingsActivity : BaseListSettingsActivity() {
private fun colorChanged(): Boolean = selectedColor != caldavCalendar!!.color private fun colorChanged(): Boolean = selectedColor != caldavCalendar!!.color
private fun iconChanged(): Boolean = selectedIcon != caldavCalendar!!.getIcon() private fun iconChanged(): Boolean = selectedIcon.value != caldavCalendar!!.icon
private val newName: String private val newName: String
get() = name.text.toString().trim { it <= ' ' } get() = name.text.toString().trim { it <= ' ' }

@ -116,7 +116,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
} }
override suspend fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) { override suspend fun createCalendar(caldavAccount: CaldavAccount, name: String, color: Int) {
caldavCalendar = viewModel.createCalendar(caldavAccount, name, color, selectedIcon) caldavCalendar = viewModel.createCalendar(caldavAccount, name, color, selectedIcon.value)
} }
override suspend fun updateNameAndColor( override suspend fun updateNameAndColor(
@ -125,7 +125,7 @@ class CaldavCalendarSettingsActivity : BaseCaldavCalendarSettingsActivity() {
name: String, name: String,
color: Int color: Int
) { ) {
viewModel.updateCalendar(account, calendar, name, color, selectedIcon) viewModel.updateCalendar(account, calendar, name, color, selectedIcon.value)
} }
override suspend fun deleteCalendar( override suspend fun deleteCalendar(

@ -3,19 +3,19 @@ package org.tasks.caldav
import android.content.Intent import android.content.Intent
import com.todoroo.astrid.activity.MainActivity import com.todoroo.astrid.activity.MainActivity
import com.todoroo.astrid.activity.TaskListFragment import com.todoroo.astrid.activity.TaskListFragment
import org.tasks.filters.CaldavFilter
import org.tasks.data.UUIDHelper
import com.todoroo.astrid.service.TaskDeleter import com.todoroo.astrid.service.TaskDeleter
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.tasks.data.* import org.tasks.data.PrincipalWithAccess
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_WRITE import org.tasks.data.UUIDHelper
import org.tasks.data.entity.CaldavCalendar.Companion.INVITE_UNKNOWN
import org.tasks.data.dao.CaldavDao import org.tasks.data.dao.CaldavDao
import org.tasks.data.dao.PrincipalDao import org.tasks.data.dao.PrincipalDao
import org.tasks.data.entity.CaldavAccount import org.tasks.data.entity.CaldavAccount
import org.tasks.data.entity.CaldavCalendar import org.tasks.data.entity.CaldavCalendar
import org.tasks.data.entity.CaldavCalendar.Companion.ACCESS_READ_WRITE
import org.tasks.data.entity.CaldavCalendar.Companion.INVITE_UNKNOWN
import org.tasks.filters.CaldavFilter
import org.tasks.sync.SyncAdapters import org.tasks.sync.SyncAdapters
import javax.inject.Inject import javax.inject.Inject
@ -33,7 +33,7 @@ class CaldavCalendarViewModel @Inject constructor(
caldavAccount: CaldavAccount, caldavAccount: CaldavAccount,
name: String, name: String,
color: Int, color: Int,
icon: Int icon: String?
): CaldavCalendar? = ): CaldavCalendar? =
doRequest { doRequest {
val url = withContext(Dispatchers.IO) { val url = withContext(Dispatchers.IO) {
@ -60,20 +60,20 @@ class CaldavCalendarViewModel @Inject constructor(
calendar: CaldavCalendar, calendar: CaldavCalendar,
name: String, name: String,
color: Int, color: Int,
icon: Int icon: String?
) = ) =
doRequest { doRequest {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
provider.forAccount(account, calendar.url!!).updateCollection(name, color) provider.forAccount(account, calendar.url!!).updateCollection(name, color)
} }
calendar.apply { val result = calendar.copy(
this.name = name name = name,
this.color = color color = color,
setIcon(icon) icon = icon,
caldavDao.update(this) )
} caldavDao.update(result)
finish.value = Intent(TaskListFragment.ACTION_RELOAD) finish.value = Intent(TaskListFragment.ACTION_RELOAD)
.putExtra(MainActivity.OPEN_FILTER, CaldavFilter(calendar)) .putExtra(MainActivity.OPEN_FILTER, CaldavFilter(result))
} }
suspend fun deleteCalendar(account: CaldavAccount, calendar: CaldavCalendar) = suspend fun deleteCalendar(account: CaldavAccount, calendar: CaldavCalendar) =

@ -1,7 +1,6 @@
package org.tasks.compose package org.tasks.compose
import android.content.res.Configuration import android.content.res.Configuration
import androidx.annotation.DrawableRes
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.defaultMinSize
@ -21,18 +20,18 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import org.tasks.R import org.tasks.R
import org.tasks.themes.CustomIcons import org.tasks.compose.components.imageVectorByName
import org.tasks.themes.TasksIcons
import org.tasks.themes.TasksTheme import org.tasks.themes.TasksTheme
@Composable @Composable
fun Chip( fun Chip(
@DrawableRes icon: Int?, icon: String?,
name: String?, name: String?,
theme: Int, theme: Int,
showText: Boolean, showText: Boolean,
@ -54,7 +53,7 @@ fun Chip(
@Composable @Composable
fun Chip( fun Chip(
text: String? = null, text: String? = null,
icon: Int? = null, icon: String? = null,
color: Color, color: Color,
onClick: () -> Unit = {}, onClick: () -> Unit = {},
clear: (() -> Unit)? = null, clear: (() -> Unit)? = null,
@ -68,7 +67,7 @@ fun Chip(
border = BorderStroke(1.dp, color = color), border = BorderStroke(1.dp, color = color),
leadingIcon = { leadingIcon = {
if (text != null) { if (text != null) {
ChipIcon(iconRes = icon) ChipIcon(icon = icon)
} }
}, },
trailingIcon = { trailingIcon = {
@ -90,7 +89,7 @@ fun Chip(
), ),
label = { label = {
if (text == null) { if (text == null) {
ChipIcon(iconRes = icon) ChipIcon(icon = icon)
} }
text?.let { text?.let {
Text( Text(
@ -106,10 +105,10 @@ fun Chip(
} }
@Composable @Composable
private fun ChipIcon(iconRes: Int?) { private fun ChipIcon(icon: String?) {
iconRes?.let { icon?.let {
Icon( Icon(
painter = painterResource(id = iconRes), imageVector = imageVectorByName(it) ?: return@let,
contentDescription = null, contentDescription = null,
modifier = Modifier.size(18.dp) modifier = Modifier.size(18.dp)
) )
@ -124,7 +123,7 @@ fun TasksChipIconAndTextPreview() {
TasksTheme { TasksTheme {
Chip( Chip(
text = "Home", text = "Home",
icon = CustomIcons.getIconResId(CustomIcons.LABEL), icon = TasksIcons.LABEL,
color = Color.Red, color = Color.Red,
) )
} }
@ -138,7 +137,7 @@ fun TasksChipIconTextAndClearPreview() {
TasksTheme { TasksTheme {
Chip( Chip(
text = "Home", text = "Home",
icon = CustomIcons.getIconResId(CustomIcons.LABEL), icon = TasksIcons.LABEL,
color = Color.Red, color = Color.Red,
clear = {}, clear = {},
) )
@ -153,7 +152,7 @@ fun TasksChipIconPreview() {
TasksTheme { TasksTheme {
Chip( Chip(
text = null, text = null,
icon = CustomIcons.getIconResId(CustomIcons.LABEL), icon = TasksIcons.LABEL,
color = Color.Red, color = Color.Red,
) )
} }

@ -2,19 +2,18 @@ package org.tasks.compose
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.themes.CustomIcons
@Composable @Composable
fun FilterChip( fun FilterChip(
filter: Filter, filter: Filter,
defaultIcon: Int, defaultIcon: String,
showText: Boolean, showText: Boolean,
showIcon: Boolean, showIcon: Boolean,
onClick: (Filter) -> Unit, onClick: (Filter) -> Unit,
colorProvider: (Int) -> Int, colorProvider: (Int) -> Int,
) { ) {
Chip( Chip(
CustomIcons.getIcon(filter.icon, defaultIcon), filter.icon ?: defaultIcon,
filter.title, filter.title,
filter.tint, filter.tint,
showText, showText,

@ -21,8 +21,6 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.IntentCompat import androidx.core.content.IntentCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -30,6 +28,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.tasks.LocalBroadcastManager import org.tasks.LocalBroadcastManager
import org.tasks.compose.components.imageVectorByName
import org.tasks.compose.pickers.SearchableFilterPicker import org.tasks.compose.pickers.SearchableFilterPicker
import org.tasks.dialogs.FilterPickerViewModel import org.tasks.dialogs.FilterPickerViewModel
import org.tasks.filters.Filter import org.tasks.filters.Filter
@ -76,7 +75,7 @@ class FilterSelectionActivity : AppCompatActivity() {
filters = if (searching) state.searchResults else state.filters, filters = if (searching) state.searchResults else state.filters,
query = state.query, query = state.query,
onQueryChange = { viewModel.onQueryChange(it) }, onQueryChange = { viewModel.onQueryChange(it) },
getIcon = { ImageVector.vectorResource(id = viewModel.getIcon(it)) }, getIcon = { imageVectorByName(viewModel.getIcon(it))!! },
getColor = { viewModel.getColor(it) }, getColor = { viewModel.getColor(it) },
selected = selected, selected = selected,
onClick = { filter -> onClick = { filter ->

@ -0,0 +1,99 @@
package org.tasks.compose
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.BasicAlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LifecycleEventEffect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.billing.Inventory
import org.tasks.billing.PurchaseActivity
import org.tasks.billing.PurchaseActivity.Companion.EXTRA_NAME_YOUR_PRICE
import org.tasks.compose.pickers.IconPicker
import org.tasks.compose.pickers.IconPickerViewModel
import org.tasks.themes.TasksTheme
import javax.inject.Inject
@AndroidEntryPoint
class IconPickerActivity : AppCompatActivity() {
@Inject lateinit var inventory: Inventory
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TasksTheme {
var hasPro by remember { mutableStateOf(false) }
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
hasPro = inventory.hasPro
}
val viewModel: IconPickerViewModel = viewModel()
val searchResults = viewModel.searchResults.collectAsStateWithLifecycle().value
val state = viewModel.viewState.collectAsStateWithLifecycle().value
BasicAlertDialog(
onDismissRequest = { finish() },
modifier = Modifier.padding(vertical = 32.dp)
) {
IconPicker(
icons = state.icons,
query = state.query,
searchResults = searchResults,
collapsed = state.collapsed,
onQueryChange = { viewModel.onQueryChange(it) },
onSelected = {
setResult(RESULT_OK, Intent().putExtra(EXTRA_SELECTED, it.name))
finish()
},
toggleCollapsed = { category, collapsed ->
viewModel.setCollapsed(category, collapsed)
},
hasPro = hasPro,
subscribe = {
startActivity(
Intent(this, PurchaseActivity::class.java)
.putExtra(EXTRA_NAME_YOUR_PRICE, true)
)
},
)
}
}
}
}
companion object {
const val EXTRA_SELECTED = "extra_selected"
const val EXTRA_ICON = "extra_icon"
fun ComponentActivity.registerForIconPickerResult(callback: (String) -> Unit): ActivityResultLauncher<Intent> {
return registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
it.data?.getStringExtra(EXTRA_SELECTED)?.let(callback)
}
}
fun ActivityResultLauncher<Intent>.launchIconPicker(
context: Context,
selected: String? = null,
) {
launch(
Intent(context, IconPickerActivity::class.java)
.putExtra(EXTRA_SELECTED, selected)
)
}
}
}

@ -6,9 +6,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import org.tasks.R
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.date.DateTimeUtils.toDateTime import org.tasks.date.DateTimeUtils.toDateTime
import org.tasks.themes.TasksIcons
import org.tasks.time.startOfDay import org.tasks.time.startOfDay
import java.time.format.FormatStyle import java.time.format.FormatStyle
@ -44,7 +44,7 @@ fun StartDateChip(
} }
if (text != null) { if (text != null) {
Chip( Chip(
icon = R.drawable.ic_pending_actions_24px, icon = TasksIcons.PENDING_ACTIONS,
name = text, name = text,
theme = 0, theme = 0,
showText = true, showText = true,

@ -245,12 +245,7 @@ object PurchaseText {
} }
}) { }) {
Text( Text(
text = stringResource( text = stringResource(R.string.more_options),
if (nameYourPrice.value)
R.string.back
else
R.string.more_options
),
color = if (solidButton) color = if (solidButton)
MaterialTheme.colorScheme.onSecondary MaterialTheme.colorScheme.onSecondary
else else
@ -414,7 +409,7 @@ object PurchaseText {
) { ) {
PurchaseButton( PurchaseButton(
price = sliderPosition.value.toInt(), price = sliderPosition.value.toInt(),
popperText = if (sliderPosition.value.toInt() >= 5) popperText = if (sliderPosition.value.toInt() >= 7)
"${stringResource(R.string.above_average, 16)} $POPPER" "${stringResource(R.string.above_average, 16)} $POPPER"
else else
"", "",

@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import org.tasks.R import org.tasks.R
import org.tasks.themes.TasksIcons
import java.text.NumberFormat import java.text.NumberFormat
@Composable @Composable
@ -16,9 +17,9 @@ fun SubtaskChip(
val context = LocalContext.current val context = LocalContext.current
Chip( Chip(
icon = if (collapsed) icon = if (collapsed)
R.drawable.ic_keyboard_arrow_down_black_24dp TasksIcons.KEYBOARD_ARROW_DOWN
else else
R.drawable.ic_keyboard_arrow_up_black_24dp, TasksIcons.KEYBOARD_ARROW_UP,
name = if (compact) name = if (compact)
NumberFormat.getInstance().format(children) NumberFormat.getInstance().format(children)
else else

@ -5,7 +5,7 @@ import org.tasks.filters.NavigationDrawerSubheader
sealed interface DrawerItem { sealed interface DrawerItem {
data class Filter( data class Filter(
val title: String, val title: String,
val icon: Int, val icon: String,
val color: Int = 0, val color: Int = 0,
val count: Int = 0, val count: Int = 0,
val shareCount: Int = 0, val shareCount: Int = 0,

@ -3,9 +3,7 @@ package org.tasks.compose.drawer
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -29,7 +27,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.Add import androidx.compose.material.icons.outlined.Add
import androidx.compose.material.icons.outlined.AttachMoney import androidx.compose.material.icons.outlined.AttachMoney
import androidx.compose.material.icons.outlined.ExpandMore
import androidx.compose.material.icons.outlined.PeopleOutline import androidx.compose.material.icons.outlined.PeopleOutline
import androidx.compose.material.icons.outlined.PermIdentity import androidx.compose.material.icons.outlined.PermIdentity
import androidx.compose.material.icons.outlined.Settings import androidx.compose.material.icons.outlined.Settings
@ -47,21 +44,22 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import org.tasks.R import org.tasks.R
import org.tasks.compose.components.Chevron
import org.tasks.compose.components.SearchBar import org.tasks.compose.components.SearchBar
import org.tasks.compose.components.imageVectorByName
import org.tasks.extensions.formatNumber import org.tasks.extensions.formatNumber
import org.tasks.filters.FilterImpl import org.tasks.filters.FilterImpl
import org.tasks.filters.NavigationDrawerSubheader import org.tasks.filters.NavigationDrawerSubheader
import org.tasks.themes.TasksIcons
import org.tasks.themes.TasksTheme import org.tasks.themes.TasksTheme
@Composable @Composable
@ -184,9 +182,7 @@ internal fun FilterItem(
.clickable(onClick = onClick), .clickable(onClick = onClick),
onClick = onClick, onClick = onClick,
) { ) {
if (item.icon != -1) { DrawerIcon(icon = item.icon, color = item.color)
DrawerIcon(icon = item.icon, color = item.color)
}
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
Text( Text(
text = item.title, text = item.title,
@ -219,27 +215,10 @@ internal fun FilterItem(
} }
@Composable @Composable
private fun MenuAction( private fun DrawerIcon(icon: String, color: Int = 0) {
icon: Int,
title: Int,
onClick: () -> Unit,
) {
MenuRow(onClick = onClick) {
DrawerIcon(icon = icon)
Spacer(modifier = Modifier.width(16.dp))
Text(
text = stringResource(id = title),
color = MaterialTheme.colorScheme.onSurface,
modifier = Modifier.weight(1f),
)
}
}
@Composable
private fun DrawerIcon(icon: Int, color: Int = 0) {
Icon( Icon(
modifier = Modifier.size(24.dp), modifier = Modifier.size(24.dp),
painter = painterResource(id = icon), imageVector = imageVectorByName(icon) ?: return,
contentDescription = null, contentDescription = null,
tint = when (color) { tint = when (color) {
0 -> MaterialTheme.colorScheme.onSurface 0 -> MaterialTheme.colorScheme.onSurface
@ -268,17 +247,7 @@ internal fun HeaderItem(
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
) )
IconButton(onClick = toggleCollapsed) { IconButton(onClick = toggleCollapsed) {
val rotation by animateFloatAsState( Chevron(item.collapsed)
targetValue = if (item.collapsed) 0f else 180f,
animationSpec = tween(250),
label = "arrow rotation",
)
Icon(
modifier = Modifier.rotate(rotation),
imageVector = Icons.Outlined.ExpandMore,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurface,
)
} }
if (canAdd) { if (canAdd) {
IconButton(onClick = onAddClick) { IconButton(onClick = onAddClick) {
@ -330,7 +299,7 @@ fun MenuPreview() {
filters = persistentListOf( filters = persistentListOf(
DrawerItem.Filter( DrawerItem.Filter(
title = "My Tasks", title = "My Tasks",
icon = R.drawable.ic_outline_all_inbox_24px, icon = TasksIcons.ALL_INBOX,
type = { FilterImpl() }, type = { FilterImpl() },
), ),
DrawerItem.Header( DrawerItem.Header(

@ -13,6 +13,7 @@ import org.tasks.compose.FilterChip
import org.tasks.compose.TaskEditRow import org.tasks.compose.TaskEditRow
import org.tasks.filters.Filter import org.tasks.filters.Filter
import org.tasks.filters.FilterImpl import org.tasks.filters.FilterImpl
import org.tasks.themes.TasksIcons
import org.tasks.themes.TasksTheme import org.tasks.themes.TasksTheme
@Composable @Composable
@ -28,7 +29,7 @@ fun ListRow(
if (list != null) { if (list != null) {
FilterChip( FilterChip(
filter = list, filter = list,
defaultIcon = R.drawable.ic_list_24px, defaultIcon = TasksIcons.LIST,
showText = true, showText = true,
showIcon = true, showIcon = true,
onClick = { onClick() }, onClick = { onClick() },

@ -2,6 +2,8 @@ package org.tasks.compose.edit
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Home
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -14,7 +16,7 @@ import org.tasks.compose.DisabledText
import org.tasks.compose.TaskEditRow import org.tasks.compose.TaskEditRow
import org.tasks.data.entity.TagData import org.tasks.data.entity.TagData
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons import org.tasks.themes.TasksIcons
import org.tasks.themes.TasksTheme import org.tasks.themes.TasksTheme
@Composable @Composable
@ -33,10 +35,7 @@ fun TagsRow(
} else { } else {
tags.sortedBy(TagData::name).forEach { tag -> tags.sortedBy(TagData::name).forEach { tag ->
Chip( Chip(
icon = CustomIcons.getIcon( icon = tag.icon ?: TasksIcons.LABEL,
tag.getIcon()!!,
R.drawable.ic_outline_label_24px
),
name = tag.name, name = tag.name,
theme = tag.color ?: 0, theme = tag.color ?: 0,
showText = true, showText = true,
@ -76,7 +75,7 @@ fun SingleTag() {
tags = listOf( tags = listOf(
TagData( TagData(
name = "Home", name = "Home",
icon = 1062, icon = Icons.Outlined.Home.name,
color = ColorProvider.BLUE_500 color = ColorProvider.BLUE_500
) )
), ),
@ -114,7 +113,7 @@ fun TagWithReallyLongName() {
tags = listOf( tags = listOf(
TagData( TagData(
name = "This is a tag with a really really long name", name = "This is a tag with a really really long name",
icon = 1062, icon = Icons.Outlined.Home.name,
color = ColorProvider.BLUE_500 color = ColorProvider.BLUE_500
) )
), ),

@ -22,9 +22,9 @@ import org.tasks.filters.Filter
import org.tasks.filters.FilterListItem import org.tasks.filters.FilterListItem
import org.tasks.filters.FilterProvider import org.tasks.filters.FilterProvider
import org.tasks.filters.NavigationDrawerSubheader import org.tasks.filters.NavigationDrawerSubheader
import org.tasks.filters.getIcon
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
@ -90,15 +90,7 @@ class FilterPickerViewModel @Inject constructor(
localBroadcastManager.broadcastRefreshList() localBroadcastManager.broadcastRefreshList()
} }
fun getIcon(filter: Filter): Int { fun getIcon(filter: Filter): String = filter.getIcon(inventory)
if (filter.icon < 1000 || inventory.hasPro) {
val icon = CustomIcons.getIconResId(filter.icon)
if (icon != null) {
return icon
}
}
return R.drawable.ic_list_24px
}
fun getColor(filter: Filter): Int { fun getColor(filter: Filter): Int {
if (filter.tint != 0) { if (filter.tint != 0) {

@ -1,72 +0,0 @@
package org.tasks.dialogs;
import static org.tasks.preferences.ResourceResolver.getData;
import android.app.Activity;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.DiffUtil.ItemCallback;
import androidx.recyclerview.widget.ListAdapter;
import org.tasks.Callback;
import org.tasks.R;
import org.tasks.billing.Inventory;
import org.tasks.databinding.DialogIconPickerCellBinding;
import org.tasks.themes.CustomIcons;
class IconPickerAdapter extends ListAdapter<Integer, IconPickerHolder> {
private final Activity activity;
private final Inventory inventory;
private final int current;
private final Callback<Integer> onSelected;
IconPickerAdapter(
Activity activity, Inventory inventory, int current, Callback<Integer> onSelected) {
super(new DiffCallback());
this.activity = activity;
this.inventory = inventory;
this.current = current;
this.onSelected = onSelected;
}
@NonNull
@Override
public IconPickerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new IconPickerHolder(
activity,
DialogIconPickerCellBinding.inflate(activity.getLayoutInflater(), parent, false),
onSelected);
}
@Override
public void onBindViewHolder(@NonNull IconPickerHolder holder, int position) {
int index = CustomIcons.getIndex(position);
Integer icon = CustomIcons.getIconResId(index);
if (icon != null) {
int tint = index == current
? getData(activity, androidx.appcompat.R.attr.colorAccent)
: activity.getColor(R.color.icon_tint);
boolean available = index < 1000 || inventory.getHasPro();
float alpha =
ResourcesCompat.getFloat(
activity.getResources(),
available ? R.dimen.alpha_primary : R.dimen.alpha_disabled);
holder.bind(index, icon, tint, alpha, available);
}
}
private static class DiffCallback extends ItemCallback<Integer> {
@Override
public boolean areItemsTheSame(@NonNull Integer oldItem, @NonNull Integer newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areContentsTheSame(@NonNull Integer oldItem, @NonNull Integer newItem) {
return true;
}
}
}

@ -1,86 +0,0 @@
package org.tasks.dialogs;
import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.RecyclerView;
import org.tasks.R;
import org.tasks.billing.Inventory;
import org.tasks.billing.PurchaseActivity;
import org.tasks.databinding.DialogIconPickerBinding;
import org.tasks.themes.CustomIcons;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
@AndroidEntryPoint
public class IconPickerDialog extends DialogFragment {
private static final String EXTRA_CURRENT = "extra_current";
@Inject DialogBuilder dialogBuilder;
@Inject Activity context;
@Inject Inventory inventory;
private IconPickerCallback callback;
public static IconPickerDialog newIconPicker(int currentIcon) {
IconPickerDialog dialog = new IconPickerDialog();
Bundle args = new Bundle();
args.putInt(EXTRA_CURRENT, currentIcon);
dialog.setArguments(args);
return dialog;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
DialogIconPickerBinding binding = DialogIconPickerBinding.inflate(LayoutInflater.from(context));
Bundle arguments = getArguments();
int current = arguments.getInt(EXTRA_CURRENT);
IconPickerAdapter iconPickerAdapter =
new IconPickerAdapter(context, inventory, current, this::onSelected);
RecyclerView recyclerView = binding.icons;
recyclerView.setLayoutManager(new IconLayoutManager(context));
recyclerView.setAdapter(iconPickerAdapter);
iconPickerAdapter.submitList(CustomIcons.getIconList());
AlertDialogBuilder builder =
dialogBuilder
.newDialog()
.setNegativeButton(R.string.cancel, null)
.setView(binding.getRoot());
if (!inventory.getHasPro()) {
builder.setPositiveButton(
R.string.upgrade_to_pro,
(dialog, which) -> startActivity(new Intent(getContext(), PurchaseActivity.class))
);
}
return builder.show();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback = (IconPickerCallback) activity;
}
private void onSelected(int index) {
callback.onSelected(getDialog(), index);
}
public interface IconPickerCallback {
void onSelected(DialogInterface d, int icon);
}
}

@ -0,0 +1,20 @@
package org.tasks.filters
import com.todoroo.astrid.api.CustomFilter
import org.tasks.billing.Inventory
import org.tasks.themes.TasksIcons
fun Filter.getIcon(inventory: Inventory): String {
if (inventory.hasPro) {
icon?.takeIf { it.isNotBlank() }?.let { return it }
}
return when (this) {
is TagFilter -> TasksIcons.LABEL
is GtasksFilter,
is CaldavFilter -> TasksIcons.LIST
is CustomFilter -> TasksIcons.FILTER_LIST
is PlaceFilter -> TasksIcons.PLACE
else -> icon!!
}
}

@ -1,18 +1,19 @@
package org.tasks.filters package org.tasks.filters
import org.tasks.data.sql.Join
import org.tasks.data.sql.QueryTemplate
import org.tasks.data.entity.Task
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.tasks.R
import org.tasks.data.entity.Notification import org.tasks.data.entity.Notification
import org.tasks.data.entity.Task
import org.tasks.data.sql.Join
import org.tasks.data.sql.QueryTemplate
import org.tasks.themes.TasksIcons
@Parcelize @Parcelize
data class NotificationsFilter( data class NotificationsFilter(
override val title: String, override val title: String,
) : Filter { ) : Filter {
override val icon: Int override val icon: String
get() = R.drawable.ic_outline_notifications_24px get() = TasksIcons.NOTIFICATIONS
override val sql: String override val sql: String
get() = QueryTemplate() get() = QueryTemplate()
.join(Join.inner(Notification.TABLE, Task.ID.eq(Notification.TASK))) .join(Join.inner(Notification.TABLE, Task.ID.eq(Notification.TASK)))

@ -13,7 +13,7 @@ import org.tasks.data.sql.Criterion.Companion.and
import org.tasks.data.sql.Field.Companion.field import org.tasks.data.sql.Field.Companion.field
import org.tasks.data.sql.Join.Companion.inner import org.tasks.data.sql.Join.Companion.inner
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.themes.CustomIcons import org.tasks.themes.TasksIcons
@Parcelize @Parcelize
data class PlaceFilter( data class PlaceFilter(
@ -32,8 +32,9 @@ data class PlaceFilter(
override val order: Int override val order: Int
get() = place.order get() = place.order
override val icon: Int override val icon: String
get() = place.icon.takeIf { it != -1 } ?: CustomIcons.PLACE get() = place.icon?.takeIf { it.isNotBlank() } ?: TasksIcons.PLACE
override val title: String override val title: String
get() = place.displayName get() = place.displayName
override val tint: Int override val tint: Int

@ -6,16 +6,16 @@ import org.tasks.data.sql.Join.Companion.inner
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.tasks.R
import org.tasks.data.entity.Alarm import org.tasks.data.entity.Alarm
import org.tasks.data.dao.TaskDao.TaskCriteria.activeAndVisible import org.tasks.data.dao.TaskDao.TaskCriteria.activeAndVisible
import org.tasks.themes.TasksIcons
@Parcelize @Parcelize
data class SnoozedFilter( data class SnoozedFilter(
override val title: String, override val title: String,
) : Filter { ) : Filter {
override val icon: Int override val icon: String
get() = R.drawable.ic_snooze_white_24dp get() = TasksIcons.SNOOZE
override val sql: String override val sql: String
get() = QueryTemplate() get() = QueryTemplate()

@ -4,12 +4,12 @@ import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.tasks.R import org.tasks.themes.TasksIcons
@Parcelize @Parcelize
data class TimerFilter(override val title: String?) : Filter { data class TimerFilter(override val title: String?) : Filter {
override val icon override val icon
get() = R.drawable.ic_outline_timer_24px get() = TasksIcons.TIMER
override val sql: String override val sql: String
get() = QueryTemplate() get() = QueryTemplate()

@ -6,7 +6,7 @@ import org.tasks.data.dao.TaskDao
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.sql.Criterion import org.tasks.data.sql.Criterion
import org.tasks.data.sql.QueryTemplate import org.tasks.data.sql.QueryTemplate
import org.tasks.themes.CustomIcons import org.tasks.themes.TasksIcons
@Parcelize @Parcelize
data class TodayFilter( data class TodayFilter(
@ -23,8 +23,9 @@ data class TodayFilter(
) )
) )
.toString() .toString()
override val icon: Int
get() = CustomIcons.TODAY override val icon: String
get() = TasksIcons.TODAY
override val valuesForNewTasks: String override val valuesForNewTasks: String
get() = mapToSerializedString(mapOf(Task.DUE_DATE.name to PermaSql.VALUE_NOON)) get() = mapToSerializedString(mapOf(Task.DUE_DATE.name to PermaSql.VALUE_NOON))

@ -9,19 +9,24 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil.ItemCallback; import androidx.recyclerview.widget.DiffUtil.ItemCallback;
import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.mikepenz.iconics.IconicsDrawable;
import com.mikepenz.iconics.typeface.library.googlematerial.OutlinedGoogleMaterial;
import org.tasks.R; import org.tasks.R;
import org.tasks.billing.Inventory; import org.tasks.billing.Inventory;
import org.tasks.data.PlaceExtensionsKt; import org.tasks.data.PlaceExtensionsKt;
import org.tasks.data.entity.Place;
import org.tasks.data.PlaceUsage; import org.tasks.data.PlaceUsage;
import org.tasks.data.entity.Place;
import org.tasks.filters.FilterExtensionsKt;
import org.tasks.filters.PlaceFilter;
import org.tasks.location.LocationPickerAdapter.PlaceViewHolder; import org.tasks.location.LocationPickerAdapter.PlaceViewHolder;
import org.tasks.themes.ColorProvider; import org.tasks.themes.ColorProvider;
import org.tasks.themes.CustomIcons;
import org.tasks.themes.DrawableUtil;
import org.tasks.themes.ThemeColor; import org.tasks.themes.ThemeColor;
public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHolder> { public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHolder> {
@ -53,6 +58,7 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
@Override @Override
public PlaceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public PlaceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new PlaceViewHolder( return new PlaceViewHolder(
context,
LayoutInflater.from(parent.getContext()).inflate(R.layout.row_place, parent, false), LayoutInflater.from(parent.getContext()).inflate(R.layout.row_place, parent, false),
callback); callback);
} }
@ -60,7 +66,9 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
@Override @Override
public void onBindViewHolder(@NonNull PlaceViewHolder holder, int position) { public void onBindViewHolder(@NonNull PlaceViewHolder holder, int position) {
PlaceUsage place = getItem(position); PlaceUsage place = getItem(position);
holder.bind(place, getColor(place.getColor()), getIcon(place.getIcon())); PlaceFilter filter = new PlaceFilter(place.getPlace(), 0);
String icon = FilterExtensionsKt.getIcon(filter, inventory);
holder.bind(place, getColor(place.getColor()), icon);
} }
private int getColor(int tint) { private int getColor(int tint) {
@ -73,16 +81,6 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
return context.getColor(R.color.text_primary); return context.getColor(R.color.text_primary);
} }
private int getIcon(int index) {
if (index < 1000 || inventory.getHasPro()) {
Integer icon = CustomIcons.getIconResId(index);
if (icon != null) {
return icon;
}
}
return R.drawable.ic_outline_place_24px;
}
public interface OnLocationPicked { public interface OnLocationPicked {
void picked(Place place); void picked(Place place);
@ -90,13 +88,15 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
} }
public static class PlaceViewHolder extends RecyclerView.ViewHolder { public static class PlaceViewHolder extends RecyclerView.ViewHolder {
private final Context context;
private final TextView name; private final TextView name;
private final TextView address; private final TextView address;
private final ImageView icon; private final ImageView icon;
private Place place; private Place place;
PlaceViewHolder(@NonNull View itemView, OnLocationPicked onLocationPicked) { PlaceViewHolder(Context context, @NonNull View itemView, OnLocationPicked onLocationPicked) {
super(itemView); super(itemView);
this.context = context;
itemView.setOnClickListener(v -> onLocationPicked.picked(place)); itemView.setOnClickListener(v -> onLocationPicked.picked(place));
name = itemView.findViewById(R.id.name); name = itemView.findViewById(R.id.name);
address = itemView.findViewById(R.id.address); address = itemView.findViewById(R.id.address);
@ -106,12 +106,15 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
.setOnClickListener(v -> onLocationPicked.settings(place)); .setOnClickListener(v -> onLocationPicked.settings(place));
} }
void bind(PlaceUsage placeUsage, int color, int icon) { void bind(PlaceUsage placeUsage, int color, String icon) {
place = placeUsage.place; place = placeUsage.place;
String name = PlaceExtensionsKt.getDisplayName(place); String name = PlaceExtensionsKt.getDisplayName(place);
String address = place.getDisplayAddress(); String address = place.getDisplayAddress();
Drawable wrapped = DrawableUtil.getWrapped(itemView.getContext(), icon); Drawable drawable = new IconicsDrawable(
this.icon.setImageDrawable(wrapped); context,
OutlinedGoogleMaterial.INSTANCE.getIcon("gmo_" + icon)
).mutate();
this.icon.setImageDrawable(drawable);
this.icon.getDrawable().setTint(color); this.icon.getDrawable().setTint(color);
this.name.setText(name); this.name.setText(name);
if (isNullOrEmpty(address) || address.equals(name)) { if (isNullOrEmpty(address) || address.equals(name)) {
@ -120,7 +123,6 @@ public class LocationPickerAdapter extends ListAdapter<PlaceUsage, PlaceViewHold
this.address.setText(address); this.address.setText(address);
this.address.setVisibility(View.VISIBLE); this.address.setVisibility(View.VISIBLE);
} }
} }
} }

@ -40,11 +40,14 @@ import kotlinx.coroutines.launch
import org.tasks.R import org.tasks.R
import org.tasks.Strings import org.tasks.Strings
import org.tasks.billing.Inventory import org.tasks.billing.Inventory
import org.tasks.compose.components.imageVectorByName
import org.tasks.data.entity.TagData import org.tasks.data.entity.TagData
import org.tasks.extensions.addBackPressedCallback import org.tasks.extensions.addBackPressedCallback
import org.tasks.filters.TagFilter
import org.tasks.filters.getIcon
import org.tasks.injection.ThemedInjectingAppCompatActivity import org.tasks.injection.ThemedInjectingAppCompatActivity
import org.tasks.themes.ColorProvider import org.tasks.themes.ColorProvider
import org.tasks.themes.CustomIcons import org.tasks.themes.TasksIcons
import org.tasks.themes.TasksTheme import org.tasks.themes.TasksTheme
import org.tasks.themes.Theme import org.tasks.themes.Theme
import javax.inject.Inject import javax.inject.Inject
@ -82,8 +85,8 @@ class TagPickerActivity : ThemedInjectingAppCompatActivity() {
TagPicker( TagPicker(
viewModel, viewModel,
onBackClicked = { handleBackPressed() }, onBackClicked = { handleBackPressed() },
getTagIcon = { tagData -> getIcon(tagData) }, getTagIcon = { tagData -> getIcon(tagData) },
getTagColor = { tagData -> getColor(tagData) } getTagColor = { tagData -> getColor(tagData) }
) )
} /* setContent */ } /* setContent */
} }
@ -112,15 +115,7 @@ class TagPickerActivity : ThemedInjectingAppCompatActivity() {
return Color(getColor(R.color.icon_tint_with_alpha)) return Color(getColor(R.color.icon_tint_with_alpha))
} }
private fun getIcon(tagData: TagData): Int private fun getIcon(tagData: TagData): String = TagFilter(tagData).getIcon(inventory)
{
val iconIndex = tagData.getIcon()
var iconResource = R.drawable.ic_outline_label_24px
if ( (iconIndex != null) && (iconIndex < 1000 || inventory.hasPro) ) {
iconResource = CustomIcons.getIconResId(iconIndex) ?: R.drawable.ic_outline_label_24px
}
return iconResource
}
/* Copy of the TagPickerActivity's companion object */ /* Copy of the TagPickerActivity's companion object */
companion object { companion object {
@ -134,7 +129,7 @@ class TagPickerActivity : ThemedInjectingAppCompatActivity() {
internal fun TagPicker( internal fun TagPicker(
viewModel: TagPickerViewModel, viewModel: TagPickerViewModel,
onBackClicked: () -> Unit, onBackClicked: () -> Unit,
getTagIcon: (TagData) -> Int, getTagIcon: (TagData) -> String,
getTagColor: (TagData) -> Color getTagColor: (TagData) -> Color
) { ) {
Box ( modifier = Modifier.fillMaxSize() ) Box ( modifier = Modifier.fillMaxSize() )
@ -194,7 +189,7 @@ internal fun SearchBar(
internal fun PickerBox ( internal fun PickerBox (
viewModel: TagPickerViewModel, viewModel: TagPickerViewModel,
tags: State<List<TagData>>, tags: State<List<TagData>>,
getTagIcon: (TagData) -> Int = { R.drawable.ic_outline_label_24px }, getTagIcon: (TagData) -> String = { TasksIcons.LABEL },
getTagColor: (TagData) -> Color = { Color.Gray } getTagColor: (TagData) -> Color = { Color.Gray }
) { ) {
val onClick: (TagData) -> Unit = { val onClick: (TagData) -> Unit = {
@ -224,7 +219,7 @@ internal fun PickerBox (
val checked = remember { mutableStateOf ( viewModel.getState(it) ) } val checked = remember { mutableStateOf ( viewModel.getState(it) ) }
val clickChecked: () -> Unit = { onClick(it); checked.value = viewModel.getState(it) } val clickChecked: () -> Unit = { onClick(it); checked.value = viewModel.getState(it) }
TagRow( TagRow(
icon = ImageVector.vectorResource(getTagIcon(it)), icon = imageVectorByName(getTagIcon(it))!!,
iconColor = getTagColor(it), iconColor = getTagColor(it),
text = it.name!!, text = it.name!!,
onClick = clickChecked onClick = clickChecked

@ -37,6 +37,7 @@ import org.tasks.filters.PlaceFilter
import org.tasks.filters.TagFilter import org.tasks.filters.TagFilter
import org.tasks.markdown.Markdown import org.tasks.markdown.Markdown
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
import org.tasks.themes.TasksIcons
import org.tasks.themes.TasksTheme import org.tasks.themes.TasksTheme
import org.tasks.time.DateTimeUtils2.currentTimeMillis import org.tasks.time.DateTimeUtils2.currentTimeMillis
import org.tasks.time.startOfDay import org.tasks.time.startOfDay
@ -276,7 +277,7 @@ class TaskViewHolder internal constructor(
if (place != null && filter !is PlaceFilter && remember { preferences.showPlaceChip }) { if (place != null && filter !is PlaceFilter && remember { preferences.showPlaceChip }) {
FilterChip( FilterChip(
filter = PlaceFilter(place), filter = PlaceFilter(place),
defaultIcon = R.drawable.ic_outline_place_24px, defaultIcon = TasksIcons.PLACE,
onClick = onClick, onClick = onClick,
showText = showText, showText = showText,
showIcon = showIcon, showIcon = showIcon,
@ -298,7 +299,7 @@ class TaskViewHolder internal constructor(
}?.let { }?.let {
FilterChip( FilterChip(
filter = it, filter = it,
defaultIcon = R.drawable.ic_list_24px, defaultIcon = TasksIcons.LIST,
onClick = onClick, onClick = onClick,
showText = showText, showText = showText,
showIcon = showIcon, showIcon = showIcon,
@ -318,7 +319,7 @@ class TaskViewHolder internal constructor(
.forEach { .forEach {
FilterChip( FilterChip(
filter = it, filter = it,
defaultIcon = R.drawable.ic_outline_label_24px, defaultIcon = TasksIcons.LABEL,
onClick = onClick, onClick = onClick,
showText = showText, showText = showText,
showIcon = showIcon, showIcon = showIcon,

@ -1,226 +0,0 @@
package org.tasks.themes
import androidx.annotation.DrawableRes
import org.tasks.R
object CustomIcons {
const val LABEL = 1
const val FILTER = 2
const val ALL_INBOX = 4
const val HISTORY = 6
const val TODAY = 7
const val LIST = 8
const val PLACE = 1050
@JvmStatic
var ICONS = mapOf(
LABEL to R.drawable.ic_outline_label_24px,
FILTER to R.drawable.ic_outline_filter_list_24px,
3 to R.drawable.ic_outline_cloud_24px,
ALL_INBOX to R.drawable.ic_outline_all_inbox_24px,
5 to R.drawable.ic_outline_label_off_24px,
HISTORY to R.drawable.ic_outline_history_24px,
TODAY to R.drawable.ic_outline_today_24px,
LIST to R.drawable.ic_list_24px,
1000 to R.drawable.ic_outline_flag_24px,
1062 to R.drawable.ic_outline_home_24px,
1041 to R.drawable.ic_outline_work_outline_24px,
1001 to R.drawable.ic_outline_pets_24px,
1002 to R.drawable.ic_outline_payment_24px,
1003 to R.drawable.ic_outline_attach_money_24px,
1059 to R.drawable.ic_outline_euro_symbol_24px,
1042 to R.drawable.ic_outline_store_24px,
1043 to R.drawable.ic_outline_shopping_cart_24px,
1004 to R.drawable.ic_outline_hourglass_empty_24px,
1005 to R.drawable.ic_outline_favorite_border_24px,
1006 to R.drawable.ic_outline_school_24px,
1007 to R.drawable.ic_outline_drive_eta_24px,
1008 to R.drawable.ic_outline_whatshot_24px,
1009 to R.drawable.ic_outline_star_border_24px,
1010 to R.drawable.ic_outline_account_balance_24px,
1011 to R.drawable.ic_outline_location_city_24px,
1012 to R.drawable.ic_outline_cake_24px,
1013 to R.drawable.ic_outline_kitchen_24px,
1014 to R.drawable.ic_outline_fitness_center_24px,
1015 to R.drawable.ic_outline_child_friendly_24px,
1016 to R.drawable.ic_outline_free_breakfast_24px,
1017 to R.drawable.ic_outline_golf_course_24px,
1018 to R.drawable.ic_outline_beach_access_24px,
1019 to R.drawable.ic_outline_restaurant_menu_24px,
1020 to R.drawable.ic_outline_local_pharmacy_24px,
1021 to R.drawable.ic_outline_fastfood_24px,
1022 to R.drawable.ic_outline_hotel_24px,
1023 to R.drawable.ic_outline_flight_24px,
1057 to R.drawable.ic_outline_flight_takeoff_24px,
1058 to R.drawable.ic_outline_flight_land_24px,
1024 to R.drawable.ic_outline_directions_run_24px,
1025 to R.drawable.ic_outline_wb_sunny_24px,
1026 to R.drawable.ic_outline_desktop_mac_24px,
1027 to R.drawable.ic_outline_computer_24px,
1028 to R.drawable.ic_outline_format_paint_24px,
1029 to R.drawable.ic_outline_storage_24px,
1030 to R.drawable.ic_outline_send_24px,
1031 to R.drawable.ic_outline_weekend_24px,
1032 to R.drawable.ic_outline_link_24px,
1033 to R.drawable.ic_outline_business_24px,
1034 to R.drawable.ic_outline_chat_bubble_outline_24px,
1035 to R.drawable.ic_outline_voicemail_24px,
1036 to R.drawable.ic_outline_email_24px,
1037 to R.drawable.ic_outline_call_24px,
1039 to R.drawable.ic_outline_movie_24px,
1040 to R.drawable.ic_outline_equalizer_24px,
1071 to R.drawable.ic_outline_pie_chart_24px,
1072 to R.drawable.ic_outline_show_chart_24px,
1044 to R.drawable.ic_outline_schedule_24px,
1045 to R.drawable.ic_outline_photo_camera_24px,
1046 to R.drawable.ic_outline_delete_24px,
1047 to R.drawable.ic_outline_attachment_24px,
1048 to R.drawable.ic_outline_vpn_key_24px,
1049 to R.drawable.ic_outline_event_24px,
PLACE to R.drawable.ic_outline_place_24px,
1051 to R.drawable.ic_outline_markunread_mailbox_24px,
1052 to R.drawable.ic_outline_label_important_24px,
1053 to R.drawable.ic_outline_android_24px,
1054 to R.drawable.ic_outline_build_24px,
1055 to R.drawable.ic_outline_bug_report_24px,
1056 to R.drawable.ic_outline_book_24px,
1060 to R.drawable.ic_outline_explore_24px,
1061 to R.drawable.ic_outline_gavel_24px,
1063 to R.drawable.ic_outline_print_24px,
1064 to R.drawable.ic_outline_receipt_24px,
1038 to R.drawable.ic_outline_new_releases_24px,
1065 to R.drawable.ic_outline_report_problem_24px,
1068 to R.drawable.ic_outline_error_outline_24px,
1069 to R.drawable.ic_outline_not_interested_24px,
1070 to R.drawable.ic_outline_report_24px,
1066 to R.drawable.ic_outline_turned_in_24px,
1067 to R.drawable.ic_outline_turned_in_not_24px,
1073 to R.drawable.ic_outline_headset_24px,
1074 to R.drawable.ic_outline_mic_none_24px,
1075 to R.drawable.ic_outline_timer_24px,
1076 to R.drawable.ic_outline_clear_24px,
1077 to R.drawable.ic_outline_search_24px,
1078 to R.drawable.ic_outline_repeat_24px,
1079 to R.drawable.ic_outline_notifications_24px,
1080 to R.drawable.ic_outline_star_half_24px,
1081 to R.drawable.ic_outline_share_24px,
1082 to R.drawable.ic_outline_sentiment_very_satisfied_24px,
1083 to R.drawable.ic_outline_sentiment_very_dissatisfied_24px,
1084 to R.drawable.ic_outline_sentiment_satisfied_24px,
1085 to R.drawable.ic_outline_sentiment_dissatisfied_24px,
1086 to R.drawable.ic_outline_mood_bad_24px,
1087 to R.drawable.ic_outline_mood_24px,
1088 to R.drawable.ic_outline_spa_24px,
1089 to R.drawable.ic_outline_room_service_24px,
1090 to R.drawable.ic_outline_meeting_room_24px,
1091 to R.drawable.ic_outline_hot_tub_24px,
1092 to R.drawable.ic_outline_business_center_24px,
1093 to R.drawable.ic_outline_priority_high_24px,
1094 to R.drawable.ic_outline_power_24px,
1095 to R.drawable.ic_outline_power_off_24px,
1096 to R.drawable.ic_outline_directions_bike_24px,
1097 to R.drawable.ic_outline_local_florist_24px,
1098 to R.drawable.ic_outline_local_pizza_24px,
1099 to R.drawable.ic_outline_navigation_24px,
1100 to R.drawable.ic_outline_local_play_24px,
1101 to R.drawable.ic_outline_local_bar_24px,
1102 to R.drawable.ic_outline_local_laundry_service_24px,
1103 to R.drawable.ic_outline_local_offer_24px,
1104 to R.drawable.ic_outline_local_shipping_24px,
1105 to R.drawable.ic_outline_local_hospital_24px,
1106 to R.drawable.ic_outline_directions_boat_24px,
1107 to R.drawable.ic_outline_directions_walk_24px,
1108 to R.drawable.ic_outline_wb_incandescent_24px,
1109 to R.drawable.ic_outline_landscape_24px,
1110 to R.drawable.ic_outline_music_note_24px,
1111 to R.drawable.ic_outline_healing_24px,
1112 to R.drawable.ic_outline_brush_24px,
1113 to R.drawable.ic_outline_brightness_2_24px,
1114 to R.drawable.ic_outline_security_24px,
1115 to R.drawable.ic_outline_scanner_24px,
1116 to R.drawable.ic_outline_router_24px,
1117 to R.drawable.ic_outline_watch_24px,
1118 to R.drawable.ic_outline_videogame_asset_24px,
1119 to R.drawable.ic_cached_24px,
1120 to R.drawable.ic_octocat,
1121 to R.drawable.ic_outline_perm_identity_24px,
1122 to R.drawable.ic_track_changes_24px,
1123 to R.drawable.ic_open_in_new_24px,
1124 to R.drawable.ic_outline_edit_24px,
1125 to R.drawable.ic_outline_info_24px,
1126 to R.drawable.ic_outline_palette_24px,
1127 to R.drawable.ic_outline_sd_storage_24px,
1128 to R.drawable.ic_baseline_lens_24px,
1129 to R.drawable.ic_map_24px,
1130 to R.drawable.ic_check_black_24dp,
1131 to R.drawable.ic_undo_24px,
1132 to R.drawable.ic_next_week_24px,
1133 to R.drawable.ic_local_cafe_24px, // duplicate
1134 to R.drawable.ic_nights_stay_24px,
1135 to R.drawable.ic_single_bed_24px,
1136 to R.drawable.ic_weather_sunset,
1137 to R.drawable.ic_calendar_today_24px,
1138 to R.drawable.ic_select_all_24px,
1139 to R.drawable.ic_widgets_24px,
1140 to R.drawable.ic_call_split_24px,
1141 to R.drawable.ic_ac_unit_24px,
1142 to R.drawable.ic_airport_shuttle_24px,
1143 to R.drawable.ic_apartment_24px,
1144 to R.drawable.ic_bathtub_24px,
1145 to R.drawable.ic_casino_24px,
1146 to R.drawable.ic_child_care_24px,
1147 to R.drawable.ic_pool_24px,
1148 to R.drawable.ic_house_24px,
1149 to R.drawable.ic_storefront_24px,
1150 to R.drawable.ic_poll_24px,
1151 to R.drawable.ic_emoji_transportation_24px,
1152 to R.drawable.ic_emoji_objects_24px,
1153 to R.drawable.ic_emoji_nature_24px,
1154 to R.drawable.ic_emoji_food_beverage_24px,
1155 to R.drawable.ic_emoji_events_24px,
1156 to R.drawable.ic_deck_24px,
1157 to R.drawable.ic_fireplace_24px,
1158 to R.drawable.ic_outdoor_grill_24px,
1159 to R.drawable.ic_thumb_up_24px,
1160 to R.drawable.ic_thumb_down_24px,
1161 to R.drawable.ic_vertical_align_top_24px,
1162 to R.drawable.ic_keyboard_arrow_left_24px,
1163 to R.drawable.ic_keyboard_arrow_right_24px,
1164 to R.drawable.ic_content_paste_24px,
1165 to R.drawable.ic_content_copy_24px,
1166 to R.drawable.ic_outline_play_arrow_24px,
1167 to R.drawable.ic_play_circle_outline_24px,
1168 to R.drawable.ic_not_started_24px,
1169 to R.drawable.ic_date_range_24px,
1170 to R.drawable.ic_pending_actions_24px,
1171 to R.drawable.ic_outline_visibility_off_24px,
1172 to R.drawable.ic_nature_24px,
1173 to R.drawable.ic_eco_24px,
1174 to R.drawable.ic_bedtime_24px,
1175 to R.drawable.ic_auto_stories_24px,
1176 to R.drawable.ic_flash_on_24px,
1177 to R.drawable.ic_wb_twilight_24px,
1178 to R.drawable.ic_local_atm_24px,
1179 to R.drawable.ic_cleaning_services_24px,
1180 to R.drawable.ic_plumbing_24px,
1181 to R.drawable.ic_pest_control_rodent_24px,
1182 to R.drawable.ic_outline_people_outline_24,
1183 to R.drawable.ic_outline_forum_24,
1184 to R.drawable.ic_twitter_logo_black,
1185 to R.drawable.ic_outline_person_add_24,
1186 to R.drawable.ic_outline_block_24,
)
@JvmStatic
fun getIconList() = ICONS.keys.toList()
@JvmStatic
fun getIconResId(index: Int) = ICONS[index]
@JvmStatic
fun getIndex(position: Int) = getIconList()[position]
@DrawableRes
fun getIcon(index: Int, def: Int) = getIconResId(index) ?: def
}

@ -3,10 +3,13 @@ package org.tasks.widget
import android.content.Context import android.content.Context
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.OutlinedGoogleMaterial
import com.todoroo.andlib.utility.DateUtilities import com.todoroo.andlib.utility.DateUtilities
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import org.tasks.BuildConfig import org.tasks.BuildConfig
import org.tasks.R import org.tasks.R
import org.tasks.billing.Inventory
import org.tasks.data.TaskContainer import org.tasks.data.TaskContainer
import org.tasks.data.entity.Task import org.tasks.data.entity.Task
import org.tasks.data.isHidden import org.tasks.data.isHidden
@ -17,7 +20,7 @@ import org.tasks.filters.Filter
import org.tasks.filters.GtasksFilter import org.tasks.filters.GtasksFilter
import org.tasks.filters.PlaceFilter import org.tasks.filters.PlaceFilter
import org.tasks.filters.TagFilter import org.tasks.filters.TagFilter
import org.tasks.themes.CustomIcons import org.tasks.filters.getIcon
import org.tasks.time.startOfDay import org.tasks.time.startOfDay
import org.tasks.ui.ChipListCache import org.tasks.ui.ChipListCache
import java.time.format.FormatStyle import java.time.format.FormatStyle
@ -28,6 +31,7 @@ class WidgetChipProvider @Inject constructor(
@ApplicationContext private val context: Context, @ApplicationContext private val context: Context,
private val chipListCache: ChipListCache, private val chipListCache: ChipListCache,
private val locale: Locale, private val locale: Locale,
private val inventory: Inventory,
) { ) {
var isDark = false var isDark = false
@ -109,11 +113,16 @@ class WidgetChipProvider @Inject constructor(
private fun newChip(filter: Filter, defaultIcon: Int) = private fun newChip(filter: Filter, defaultIcon: Int) =
newChip(filter.tint).apply { newChip(filter.tint).apply {
setTextViewText(R.id.chip_text, filter.title) setTextViewText(R.id.chip_text, filter.title)
val icon = filter.icon if (filter.icon.isNullOrBlank()) {
.takeIf { it >= 0 } setImageViewResource(R.id.chip_icon, defaultIcon)
?.let { CustomIcons.getIconResId(it) } } else {
?: defaultIcon val icon = filter.getIcon(inventory)
setImageViewResource(R.id.chip_icon, icon) val drawable = IconicsDrawable(
context,
OutlinedGoogleMaterial.getIcon("gmo_$icon")
)
setImageViewBitmap(R.id.chip_icon, drawable.toBitmap())
}
} }
private fun newChip(@ColorInt color: Int = 0) = RemoteViews(BuildConfig.APPLICATION_ID, R.layout.widget_chip).apply { private fun newChip(@ColorInt color: Int = 0) = RemoteViews(BuildConfig.APPLICATION_ID, R.layout.widget_chip).apply {

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M22,11h-4.17l3.24,-3.24 -1.41,-1.42L15,11h-2V9l4.66,-4.66 -1.42,-1.41L13,6.17V2h-2v4.17L7.76,2.93 6.34,4.34 11,9v2H9L4.34,6.34 2.93,7.76 6.17,11H2v2h4.17l-3.24,3.24 1.41,1.42L9,13h2v2l-4.66,4.66 1.42,1.41L11,17.83V22h2v-4.17l3.24,3.24 1.42,-1.41L13,15v-2h2l4.66,4.66 1.41,-1.42L17.83,13H22v-2z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17,5L3,5c-1.1,0 -2,0.89 -2,2v9h2c0,1.66 1.34,3 3,3s3,-1.34 3,-3h6c0,1.66 1.34,3 3,3s3,-1.34 3,-3h2v-5l-6,-6zM15,7h1l3,3h-4L15,7zM9,7h4v3L9,10L9,7zM3,7h4v3L3,10L3,7zM6,17.25c-0.69,0 -1.25,-0.56 -1.25,-1.25s0.56,-1.25 1.25,-1.25 1.25,0.56 1.25,1.25 -0.56,1.25 -1.25,1.25zM18,17.25c-0.69,0 -1.25,-0.56 -1.25,-1.25s0.56,-1.25 1.25,-1.25 1.25,0.56 1.25,1.25 -0.56,1.25 -1.25,1.25zM21,14h-0.78c-0.55,-0.61 -1.34,-1 -2.22,-1s-1.67,0.39 -2.22,1L8.22,14c-0.55,-0.61 -1.33,-1 -2.22,-1s-1.67,0.39 -2.22,1L3,14v-2h18v2z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17,11V3H7v4H3v14h8v-4h2v4h8V11H17zM7,19H5v-2h2V19zM7,15H5v-2h2V15zM7,11H5V9h2V11zM11,15H9v-2h2V15zM11,11H9V9h2V11zM11,7H9V5h2V7zM15,15h-2v-2h2V15zM15,11h-2V9h2V11zM15,7h-2V5h2V7zM19,19h-2v-2h2V19zM19,15h-2v-2h2V15z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M22.47,5.2C22,4.96 21.51,4.76 21,4.59v12.03C19.86,16.21 18.69,16 17.5,16c-1.9,0 -3.78,0.54 -5.5,1.58V5.48C10.38,4.55 8.51,4 6.5,4C4.71,4 3.02,4.44 1.53,5.2C1.2,5.36 1,5.71 1,6.08v12.08c0,0.58 0.47,0.99 1,0.99c0.16,0 0.32,-0.04 0.48,-0.12C3.69,18.4 5.05,18 6.5,18c2.07,0 3.98,0.82 5.5,2c1.52,-1.18 3.43,-2 5.5,-2c1.45,0 2.81,0.4 4.02,1.04c0.16,0.08 0.32,0.12 0.48,0.12c0.52,0 1,-0.41 1,-0.99V6.08C23,5.71 22.8,5.36 22.47,5.2zM10,16.62C8.86,16.21 7.69,16 6.5,16c-1.19,0 -2.36,0.21 -3.5,0.62V6.71C4.11,6.24 5.28,6 6.5,6C7.7,6 8.89,6.25 10,6.72V16.62zM19,0.5l-5,5V15l5,-4.5V0.5z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z"/>
</vector>

@ -1,6 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M7,7m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path android:fillColor="#FF000000" android:pathData="M20,13V4.83C20,3.27 18.73,2 17.17,2c-0.75,0 -1.47,0.3 -2,0.83l-1.25,1.25C13.76,4.03 13.59,4 13.41,4c-0.4,0 -0.77,0.12 -1.08,0.32l2.76,2.76c0.2,-0.31 0.32,-0.68 0.32,-1.08c0,-0.18 -0.03,-0.34 -0.07,-0.51l1.25,-1.25C16.74,4.09 16.95,4 17.17,4C17.63,4 18,4.37 18,4.83V13h-6.85c-0.3,-0.21 -0.57,-0.45 -0.82,-0.72l-1.4,-1.55c-0.19,-0.21 -0.43,-0.38 -0.69,-0.5C7.93,10.08 7.59,10 7.24,10C6,10.01 5,11.01 5,12.25V13H2v6c0,1.1 0.9,2 2,2c0,0.55 0.45,1 1,1h14c0.55,0 1,-0.45 1,-1c1.1,0 2,-0.9 2,-2v-6H20zM20,19H4v-4h16V19z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M9.27,4.49c-1.63,7.54 3.75,12.41 7.66,13.8C15.54,19.38 13.81,20 12,20c-4.41,0 -8,-3.59 -8,-8C4,8.55 6.2,5.6 9.27,4.49M11.99,2.01C6.4,2.01 2,6.54 2,12c0,5.52 4.48,10 10,10c3.71,0 6.93,-2.02 8.66,-5.02c-7.51,-0.25 -12.09,-8.43 -8.32,-14.97C12.22,2.01 12.11,2.01 11.99,2.01L11.99,2.01z"/>
</vector>

@ -1,10 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,5h14v14z"/>
<path android:fillColor="#FF000000" android:pathData="M7.5,16.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="#FF000000" android:pathData="M7.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="#FF000000" android:pathData="M12,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="#FF000000" android:pathData="M16.5,16.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="#FF000000" android:pathData="M16.5,7.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
</vector>

@ -1,7 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M14.5,10.5m-1.25,0a1.25,1.25 0,1 1,2.5 0a1.25,1.25 0,1 1,-2.5 0"/>
<path android:fillColor="#FF000000" android:pathData="M9.5,10.5m-1.25,0a1.25,1.25 0,1 1,2.5 0a1.25,1.25 0,1 1,-2.5 0"/>
<path android:fillColor="#FF000000" android:pathData="M22.94,11.34c-0.25,-1.51 -1.36,-2.74 -2.81,-3.17 -0.53,-1.12 -1.28,-2.1 -2.19,-2.91C16.36,3.85 14.28,3 12,3s-4.36,0.85 -5.94,2.26c-0.92,0.81 -1.67,1.8 -2.19,2.91 -1.45,0.43 -2.56,1.65 -2.81,3.17 -0.04,0.21 -0.06,0.43 -0.06,0.66 0,0.23 0.02,0.45 0.06,0.66 0.25,1.51 1.36,2.74 2.81,3.17 0.52,1.11 1.27,2.09 2.17,2.89C7.62,20.14 9.71,21 12,21s4.38,-0.86 5.97,-2.28c0.9,-0.8 1.65,-1.79 2.17,-2.89 1.44,-0.43 2.55,-1.65 2.8,-3.17 0.04,-0.21 0.06,-0.43 0.06,-0.66 0,-0.23 -0.02,-0.45 -0.06,-0.66zM19,14c-0.1,0 -0.19,-0.02 -0.29,-0.03 -0.2,0.67 -0.49,1.29 -0.86,1.86C16.6,17.74 14.45,19 12,19s-4.6,-1.26 -5.85,-3.17c-0.37,-0.57 -0.66,-1.19 -0.86,-1.86 -0.1,0.01 -0.19,0.03 -0.29,0.03 -1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2c0.1,0 0.19,0.02 0.29,0.03 0.2,-0.67 0.49,-1.29 0.86,-1.86C7.4,6.26 9.55,5 12,5s4.6,1.26 5.85,3.17c0.37,0.57 0.66,1.19 0.86,1.86 0.1,-0.01 0.19,-0.03 0.29,-0.03 1.1,0 2,0.9 2,2s-0.9,2 -2,2zM12,17c2.01,0 3.74,-1.23 4.5,-3h-9c0.76,1.77 2.49,3 4.5,3z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M16,11h-1V3c0,-1.1 -0.9,-2 -2,-2h-2C9.9,1 9,1.9 9,3v8H8c-2.76,0 -5,2.24 -5,5v7h18v-7C21,13.24 18.76,11 16,11zM11,3h2v8h-2V3zM19,21h-2v-3c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v3h-2v-3c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v3H9v-3c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v3H5v-5c0,-1.65 1.35,-3 3,-3h8c1.65,0 3,1.35 3,3V21z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,2h-4.18C14.4,0.84 13.3,0 12,0S9.6,0.84 9.18,2L5,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM12,2c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM19,20L5,20L5,4h2v3h10L17,4h2v16z"/>
</vector>

@ -1,7 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M22,9L12,2L2,9h9v13h2V9H22zM12,4.44L15.66,7H8.34L12,4.44z"/>
<path android:fillColor="#FF000000" android:pathData="M4.14,12l-1.96,0.37l0.82,4.37l0,5.26l2,0l0.02,-4l1.98,0l0,4l2,0l0,-6l-4.1,0z"/>
<path android:fillColor="#FF000000" android:pathData="M19.1,16l-4.1,0l0,6l2,0l0,-4l1.98,0l0.02,4l2,0l0,-5.26l0.82,-4.37l-1.96,-0.37z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6.05,8.05c-2.73,2.73 -2.73,7.17 0,9.9C7.42,19.32 9.21,20 11,20s3.58,-0.68 4.95,-2.05C19.43,14.47 20,4 20,4S9.53,4.57 6.05,8.05zM14.54,16.54C13.59,17.48 12.34,18 11,18c-0.89,0 -1.73,-0.25 -2.48,-0.68c0.92,-2.88 2.62,-5.41 4.88,-7.32c-2.63,1.36 -4.84,3.46 -6.37,6c-1.48,-1.96 -1.35,-4.75 0.44,-6.54C9.21,7.72 14.04,6.65 17.8,6.2C17.35,9.96 16.28,14.79 14.54,16.54z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,5h-2V3H7v2H5C3.9,5 3,5.9 3,7v1c0,2.55 1.92,4.63 4.39,4.94c0.63,1.5 1.98,2.63 3.61,2.96V19H7v2h10v-2h-4v-3.1c1.63,-0.33 2.98,-1.46 3.61,-2.96C19.08,12.63 21,10.55 21,8V7C21,5.9 20.1,5 19,5zM5,8V7h2v3.82C5.84,10.4 5,9.3 5,8zM12,14c-1.65,0 -3,-1.35 -3,-3V5h6v6C15,12.65 13.65,14 12,14zM19,8c0,1.3 -0.84,2.4 -2,2.82V7h2V8z"/>
</vector>

@ -1,6 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M2,19h18v2h-18z"/>
<path android:fillColor="#FF000000" android:pathData="M20,3H4v10c0,2.21 1.79,4 4,4h6c2.21,0 4,-1.79 4,-4v-3h2c1.11,0 2,-0.89 2,-2V5C22,3.89 21.11,3 20,3zM16,13c0,1.1 -0.9,2 -2,2H8c-1.1,0 -2,-0.9 -2,-2V5h3v1.4L7.19,7.85C7.07,7.94 7,8.09 7,8.24v4.26C7,12.78 7.22,13 7.5,13h4c0.28,0 0.5,-0.22 0.5,-0.5V8.24c0,-0.15 -0.07,-0.3 -0.19,-0.39L10,6.4V5h6V13zM9.5,7.28l1.5,1.2V12H8V8.48L9.5,7.28zM20,8h-2V5h2V8z"/>
</vector>

@ -1,6 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M21.94,4.88C21.76,4.35 21.25,4 20.68,4c-0.03,0 -0.06,0 -0.09,0H19.6l-0.31,-0.97C19.15,2.43 18.61,2 18,2h0c-0.61,0 -1.15,0.43 -1.29,1.04L16.4,4h-0.98c-0.03,0 -0.06,0 -0.09,0c-0.57,0 -1.08,0.35 -1.26,0.88c-0.19,0.56 0.04,1.17 0.56,1.48l0.87,0.52L15.1,8.12c-0.23,0.58 -0.04,1.25 0.45,1.62C15.78,9.91 16.06,10 16.33,10c0.31,0 0.61,-0.11 0.86,-0.32L18,8.98l0.81,0.7C19.06,9.89 19.36,10 19.67,10c0.27,0 0.55,-0.09 0.78,-0.26c0.5,-0.37 0.68,-1.04 0.45,-1.62l-0.39,-1.24l0.87,-0.52C21.89,6.05 22.12,5.44 21.94,4.88zM18,7c-0.55,0 -1,-0.45 -1,-1c0,-0.55 0.45,-1 1,-1s1,0.45 1,1C19,6.55 18.55,7 18,7z"/>
<path android:fillColor="#FF000000" android:pathData="M13.49,10.51c-0.43,-0.43 -0.94,-0.73 -1.49,-0.93V8h-1v1.38c-0.11,-0.01 -0.23,-0.03 -0.34,-0.03c-1.02,0 -2.05,0.39 -2.83,1.17c-0.12,0.12 -0.3,0.3 -0.5,0.5L6,10.52c-1.56,-0.55 -3.28,0.27 -3.83,1.82c0,0 0,0 0,0c-0.27,0.75 -0.23,1.57 0.12,2.29c0.23,0.48 0.58,0.87 1,1.16c-0.38,1.35 -0.06,2.85 1,3.91c0.78,0.78 1.8,1.17 2.83,1.17c0.37,0 0.73,-0.07 1.09,-0.17c0.29,0.42 0.68,0.77 1.16,1C9.78,21.9 10.21,22 10.65,22c0.34,0 0.68,-0.06 1.01,-0.17c0,0 0,0 0,0c1.56,-0.55 2.38,-2.27 1.82,-3.85l-0.49,-1.3c0.2,-0.2 0.38,-0.38 0.5,-0.5c0.87,-0.87 1.24,-2.04 1.14,-3.17H16v-1h-1.59C14.22,11.46 13.92,10.95 13.49,10.51zM7.58,18.82c-0.15,0.04 -0.3,0.06 -0.46,0.06c-0.53,0 -1.04,-0.21 -1.41,-0.59c-0.38,-0.38 -0.59,-0.88 -0.59,-1.41c0,-0.16 0.03,-0.32 0.06,-0.47c0.14,0.01 0.28,0.03 0.42,0.03c0.85,0 1.68,-0.2 2.44,-0.48C7.72,16.85 7.5,17.83 7.58,18.82zM4.67,14.29c-0.25,-0.09 -0.45,-0.27 -0.57,-0.51s-0.13,-0.51 -0.04,-0.76c0.19,-0.52 0.76,-0.79 1.26,-0.61l3.16,1.19C7.33,14.2 5.85,14.71 4.67,14.29zM10.99,19.94c-0.25,0.09 -0.52,0.08 -0.76,-0.04c-0.24,-0.11 -0.42,-0.32 -0.51,-0.57c-0.42,-1.18 0.09,-2.65 0.7,-3.8l1.18,3.13C11.78,19.18 11.51,19.76 10.99,19.94zM12.2,14.6l-0.61,-1.61c0,-0.01 -0.01,-0.02 -0.02,-0.03c-0.02,-0.04 -0.04,-0.08 -0.06,-0.12c-0.02,-0.04 -0.04,-0.07 -0.07,-0.11c-0.03,-0.03 -0.06,-0.06 -0.09,-0.09c-0.03,-0.03 -0.06,-0.06 -0.09,-0.09c-0.03,-0.03 -0.07,-0.05 -0.11,-0.07c-0.04,-0.02 -0.07,-0.05 -0.12,-0.06c-0.01,0 -0.02,-0.01 -0.03,-0.02L9.4,11.8c0.36,-0.29 0.79,-0.46 1.26,-0.46c0.53,0 1.04,0.21 1.41,0.59C12.8,12.66 12.84,13.81 12.2,14.6z"/>
</vector>

@ -1,8 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,3c-0.46,0 -0.93,0.04 -1.4,0.14C7.84,3.67 5.64,5.9 5.12,8.66c-0.48,2.61 0.48,5.01 2.22,6.56C7.77,15.6 8,16.13 8,16.69V19c0,1.1 0.9,2 2,2h0.28c0.35,0.6 0.98,1 1.72,1s1.38,-0.4 1.72,-1H14c1.1,0 2,-0.9 2,-2v-2.31c0,-0.55 0.22,-1.09 0.64,-1.46C18.09,13.95 19,12.08 19,10C19,6.13 15.87,3 12,3zM14,17h-4v-1h4V17zM10,19v-1h4v1H10zM15.31,13.74c-0.09,0.08 -0.16,0.18 -0.24,0.26H8.92c-0.08,-0.09 -0.15,-0.19 -0.24,-0.27c-1.32,-1.18 -1.91,-2.94 -1.59,-4.7c0.36,-1.94 1.96,-3.55 3.89,-3.93C11.32,5.03 11.66,5 12,5c2.76,0 5,2.24 5,5C17,11.43 16.39,12.79 15.31,13.74z"/>
<path android:fillColor="#FF000000" android:pathData="M11.5,11h1v3h-1z"/>
<path android:fillColor="#FF000000" android:pathData="M9.6724,9.5808l0.7071,-0.7071l2.1213,2.1213l-0.7071,0.7071z"/>
<path android:fillColor="#FF000000" android:pathData="M12.2081,11.7123l-0.7071,-0.7071l2.1213,-2.1213l0.7071,0.7071z"/>
</vector>

@ -1,10 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M20.57,10.66C20.43,10.26 20.05,10 19.6,10h-7.19c-0.46,0 -0.83,0.26 -0.98,0.66L10,14.77l0.01,5.51c0,0.38 0.31,0.72 0.69,0.72h0.62C11.7,21 12,20.62 12,20.24V19h8v1.24c0,0.38 0.31,0.76 0.69,0.76h0.61c0.38,0 0.69,-0.34 0.69,-0.72L22,18.91v-4.14L20.57,10.66zM12.41,11h7.19l1.03,3h-9.25L12.41,11zM12,17c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1s1,0.45 1,1S12.55,17 12,17zM20,17c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1s1,0.45 1,1S20.55,17 20,17z"/>
<path android:fillColor="#FF000000" android:pathData="M14,9l1,0l0,-6l-8,0l0,5l-5,0l0,13l1,0l0,-12l5,0l0,-5l6,0z"/>
<path android:fillColor="#FF000000" android:pathData="M5,11h2v2h-2z"/>
<path android:fillColor="#FF000000" android:pathData="M10,5h2v2h-2z"/>
<path android:fillColor="#FF000000" android:pathData="M5,15h2v2h-2z"/>
<path android:fillColor="#FF000000" android:pathData="M5,19h2v2h-2z"/>
</vector>

@ -1,6 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12.01,12.46c-0.15,0.42 -0.15,0.82 -0.08,1.28c0.1,0.55 0.33,1.04 0.2,1.6c-0.13,0.59 -0.77,1.38 -1.53,1.63c1.28,1.05 3.2,0.37 3.39,-1.32C14.16,14.11 12.55,13.67 12.01,12.46z"/>
<path android:fillColor="#FF000000" android:pathData="M2,2v20h20V2H2zM12,18c-1.58,0 -2.97,-1.88 -3,-3.06c0,-0.05 -0.01,-0.13 -0.01,-0.22c-0.13,-1.73 1,-3.2 2.47,-4.37c0.47,1.01 1.27,2.03 2.57,2.92C14.61,13.69 15,14.13 15,15C15,16.65 13.65,18 12,18zM20,20h-2v-2h-2.02c0.63,-0.84 1.02,-1.87 1.02,-3c0,-1.89 -1.09,-2.85 -1.85,-3.37C12.2,9.61 13,7 13,7c-6.73,3.57 -6.02,7.47 -6,8c0.03,0.96 0.49,2.07 1.23,3H6v2H4V4h16V20z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M7,2v11h3v9l7,-12h-4l3,-8z"/>
</vector>

@ -1,6 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,9.3V4h-3v2.6L12,3L2,12h3v8h6v-6h2v6h6v-8h3L19,9.3zM17,18h-2v-6H9v6H7v-7.81l5,-4.5l5,4.5V18z"/>
<path android:fillColor="#FF000000" android:pathData="M10,10h4c0,-1.1 -0.9,-2 -2,-2S10,8.9 10,10z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,5h14v14zM7,11h10v2L7,13z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M15.41,16.59L10.83,12l4.58,-4.59L14,6l-6,6 6,6 1.41,-1.41z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M11,17h2v-1h1c0.55,0 1,-0.45 1,-1v-3c0,-0.55 -0.45,-1 -1,-1h-3v-1h4L15,8h-2L13,7h-2v1h-1c-0.55,0 -1,0.45 -1,1v3c0,0.55 0.45,1 1,1h3v1L9,14v2h2v1zM20,4L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,6c0,-1.11 -0.89,-2 -2,-2zM20,18L4,18L4,6h16v12z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M13,16.12h-0.03c3.49,-0.4 6.2,-3.36 6.2,-6.95 0,-3.87 -3.13,-7 -7,-7s-7,3.13 -7,7c0,3.47 2.52,6.34 5.83,6.89V20H5v2h14v-2h-6v-3.88zM7.17,9.17c0,-2.76 2.24,-5 5,-5s5,2.24 5,5 -2.24,5 -5,5 -5,-2.24 -5,-5z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,4c4.41,0 8,3.59 8,8s-3.59,8 -8,8s-8,-3.59 -8,-8S7.59,4 12,4M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,6.48 17.52,2 12,2L12,2zM11,8H9v8h2V8zM17,12l-5,-4v8L17,12z"/>
</vector>

@ -1,8 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17,22c1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3c-1.3,0 -2.4,0.84 -2.82,2H9.14l1.99,-3.06C11.42,14.98 11.71,15 12,15s0.58,-0.02 0.87,-0.06l1.02,1.57c0.42,-0.53 0.96,-0.95 1.6,-1.21l-0.6,-0.93C17.31,13.27 19,10.84 19,8H5c0,2.84 1.69,5.27 4.12,6.37l-3.95,6.08c-0.3,0.46 -0.17,1.08 0.29,1.38h0c0.46,0.3 1.08,0.17 1.38,-0.29l1,-1.55h6.34C14.6,21.16 15.7,22 17,22zM17,18c0.55,0 1,0.45 1,1c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1C16,18.45 16.45,18 17,18zM7.42,10h9.16c-0.77,1.76 -2.54,3 -4.58,3S8.19,11.76 7.42,10z"/>
<path android:fillColor="#FF000000" android:pathData="M9.41,7h1c0.15,-1.15 0.23,-1.64 -0.89,-2.96C9.1,3.54 8.84,3.27 9.06,2H8.07C7.86,3.11 8.1,4.05 8.96,4.96C9.18,5.2 9.75,5.63 9.41,7z"/>
<path android:fillColor="#FF000000" android:pathData="M11.89,7h1c0.15,-1.15 0.23,-1.64 -0.89,-2.96c-0.42,-0.5 -0.68,-0.78 -0.46,-2.04h-0.99c-0.21,1.11 0.03,2.05 0.89,2.96C11.67,5.2 12.24,5.63 11.89,7z"/>
<path android:fillColor="#FF000000" android:pathData="M14.41,7h1c0.15,-1.15 0.23,-1.64 -0.89,-2.96C14.1,3.54 13.84,3.27 14.06,2h-0.99c-0.21,1.11 0.03,2.05 0.89,2.96C14.18,5.2 14.75,5.63 14.41,7z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6.5,10h-2v7h2v-7zM12.5,10h-2v7h2v-7zM21,19L2,19v2h19v-2zM18.5,10h-2v7h2v-7zM11.5,3.26L16.71,6L6.29,6l5.21,-2.74m0,-2.26L2,6v2h19L21,6l-9.5,-5z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v7c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM5,10h3.13c0.21,0.78 0.67,1.47 1.27,2L5,12v-2zM19,12h-4.4c0.6,-0.53 1.06,-1.22 1.27,-2L19,10v2zM19,8h-5v1c0,1.07 -0.93,2 -2,2s-2,-0.93 -2,-2L10,8L5,8L5,5h14v3zM17,15h-3v1c0,0.47 -0.19,0.9 -0.48,1.25 -0.37,0.45 -0.92,0.75 -1.52,0.75s-1.15,-0.3 -1.52,-0.75c-0.29,-0.35 -0.48,-0.78 -0.48,-1.25v-1L3,15v4c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-4h-4zM5,17h3.13c0.02,0.09 0.06,0.17 0.09,0.25 0.24,0.68 0.65,1.28 1.18,1.75L5,19v-2zM19,19h-4.4c0.54,-0.47 0.95,-1.07 1.18,-1.75 0.03,-0.08 0.07,-0.16 0.09,-0.25L19,17v2z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71s-0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M21,19.57l-1.427,1.428 -6.442,-6.442 1.43,-1.428zM13.12,3c-2.58,0 -5.16,0.98 -7.14,2.95l-0.01,0.01c-3.95,3.95 -3.95,10.36 0,14.31l14.3,-14.31C18.3,3.99 15.71,3 13.12,3zM6.14,17.27C5.4,16.03 5,14.61 5,13.12c0,-0.93 0.16,-1.82 0.46,-2.67 0.19,1.91 0.89,3.79 2.07,5.44l-1.39,1.38zM8.98,14.43C7.63,12.38 7.12,9.93 7.6,7.6c0.58,-0.12 1.16,-0.18 1.75,-0.18 1.8,0 3.55,0.55 5.08,1.56l-5.45,5.45zM10.45,5.46c0.85,-0.3 1.74,-0.46 2.67,-0.46 1.49,0 2.91,0.4 4.15,1.14l-1.39,1.39c-1.65,-1.18 -3.52,-1.88 -5.43,-2.07z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M18,2L6,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM9,4h2v5l-1,-0.75L9,9L9,4zM18,20L6,20L6,4h1v9l3,-2.25L13,13L13,4h5v16z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M10,4c4.41,0 8,3.59 8,8s-3.59,8 -8,8c-0.34,0 -0.68,-0.02 -1.01,-0.07C10.9,17.77 12,14.95 12,12s-1.1,-5.77 -3.01,-7.93C9.32,4.02 9.66,4 10,4m0,-2c-1.82,0 -3.53,0.5 -5,1.35C7.99,5.08 10,8.3 10,12s-2.01,6.92 -5,8.65C6.47,21.5 8.18,22 10,22c5.52,0 10,-4.48 10,-10S15.52,2 10,2z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M7,16c0.55,0 1,0.45 1,1 0,1.1 -0.9,2 -2,2 -0.17,0 -0.33,-0.02 -0.5,-0.05 0.31,-0.55 0.5,-1.21 0.5,-1.95 0,-0.55 0.45,-1 1,-1M18.67,3c-0.26,0 -0.51,0.1 -0.71,0.29L9,12.25 11.75,15l8.96,-8.96c0.39,-0.39 0.39,-1.02 0,-1.41l-1.34,-1.34c-0.2,-0.2 -0.45,-0.29 -0.7,-0.29zM7,14c-1.66,0 -3,1.34 -3,3 0,1.31 -1.16,2 -2,2 0.92,1.22 2.49,2 4,2 2.21,0 4,-1.79 4,-4 0,-1.66 -1.34,-3 -3,-3z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,7L12,3L2,3v18h20L22,7L12,7zM6,19L4,19v-2h2v2zM6,15L4,15v-2h2v2zM6,11L4,11L4,9h2v2zM6,7L4,7L4,5h2v2zM10,19L8,19v-2h2v2zM10,15L8,15v-2h2v2zM10,11L8,11L8,9h2v2zM10,7L8,7L8,5h2v2zM20,19h-8v-2h2v-2h-2v-2h2v-2h-2L12,9h8v10zM18,11h-2v2h2v-2zM18,15h-2v2h2v-2z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M20,7h-4L16,5l-2,-2h-4L8,5v2L4,7c-1.1,0 -2,0.9 -2,2v5c0,0.75 0.4,1.38 1,1.73L3,19c0,1.11 0.89,2 2,2h14c1.11,0 2,-0.89 2,-2v-3.28c0.59,-0.35 1,-0.99 1,-1.72L22,9c0,-1.1 -0.9,-2 -2,-2zM10,5h4v2h-4L10,5zM4,9h16v5h-5v-3L9,11v3L4,14L4,9zM13,15h-2v-2h2v2zM19,19L5,19v-3h4v1h6v-1h4v3z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,6c1.11,0 2,-0.9 2,-2 0,-0.38 -0.1,-0.73 -0.29,-1.03L12,0l-1.71,2.97c-0.19,0.3 -0.29,0.65 -0.29,1.03 0,1.1 0.9,2 2,2zM18,9h-5L13,7h-2v2L6,9c-1.66,0 -3,1.34 -3,3v9c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1v-9c0,-1.66 -1.34,-3 -3,-3zM19,20L5,20v-3c0.9,-0.01 1.76,-0.37 2.4,-1.01l1.09,-1.07 1.07,1.07c1.31,1.31 3.59,1.3 4.89,0l1.08,-1.07 1.07,1.07c0.64,0.64 1.5,1 2.4,1.01v3zM19,15.5c-0.51,-0.01 -0.99,-0.2 -1.35,-0.57l-2.13,-2.13 -2.14,2.13c-0.74,0.74 -2.03,0.74 -2.77,0L8.48,12.8l-2.14,2.13c-0.35,0.36 -0.83,0.56 -1.34,0.57L5,12c0,-0.55 0.45,-1 1,-1h12c0.55,0 1,0.45 1,1v3.5z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6.54,5c0.06,0.89 0.21,1.76 0.45,2.59l-1.2,1.2c-0.41,-1.2 -0.67,-2.47 -0.76,-3.79h1.51m9.86,12.02c0.85,0.24 1.72,0.39 2.6,0.45v1.49c-1.32,-0.09 -2.59,-0.35 -3.8,-0.75l1.2,-1.19M7.5,3H4c-0.55,0 -1,0.45 -1,1 0,9.39 7.61,17 17,17 0.55,0 1,-0.45 1,-1v-3.49c0,-0.55 -0.45,-1 -1,-1 -1.24,0 -2.45,-0.2 -3.57,-0.57 -0.1,-0.04 -0.21,-0.05 -0.31,-0.05 -0.26,0 -0.51,0.1 -0.71,0.29l-2.2,2.2c-2.83,-1.45 -5.15,-3.76 -6.59,-6.59l2.2,-2.2c0.28,-0.28 0.36,-0.67 0.25,-1.02C8.7,6.45 8.5,5.25 8.5,4c0,-0.55 -0.45,-1 -1,-1z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M13,2v8h8c0,-4.42 -3.58,-8 -8,-8zM15,8L15,4.34c1.7,0.6 3.05,1.95 3.66,3.66L15,8zM6.44,11l-0.95,-2L2,9v2h2.22s1.89,4.07 2.12,4.42c-1.1,0.59 -1.84,1.75 -1.84,3.08C4.5,20.43 6.07,22 8,22c1.76,0 3.22,-1.3 3.46,-3h2.08c0.24,1.7 1.7,3 3.46,3 1.93,0 3.5,-1.57 3.5,-3.5 0,-1.04 -0.46,-1.97 -1.18,-2.61C20.37,14.54 21,12.84 21,11L6.44,11zM8,20c-0.83,0 -1.5,-0.67 -1.5,-1.5S7.17,17 8,17s1.5,0.67 1.5,1.5S8.83,20 8,20zM17,20c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.17,17 17,17s1.5,0.67 1.5,1.5S17.83,20 17,20zM17.74,14.66l-0.29,0.37c-0.14,-0.02 -0.3,-0.03 -0.45,-0.03 -1.39,0 -2.6,0.82 -3.16,2h-2.68c-0.5,-1.04 -1.5,-1.8 -2.68,-1.97l-0.44,-0.67c-0.1,-0.17 -0.34,-0.69 -0.67,-1.36h11.29c-0.21,0.59 -0.52,1.15 -0.92,1.66z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,6c2.62,0 4.88,1.86 5.39,4.43l0.3,1.5 1.53,0.11c1.56,0.1 2.78,1.41 2.78,2.96 0,1.65 -1.35,3 -3,3H6c-2.21,0 -4,-1.79 -4,-4 0,-2.05 1.53,-3.76 3.56,-3.97l1.07,-0.11 0.5,-0.95C8.08,7.14 9.94,6 12,6m0,-2C9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96C18.67,6.59 15.64,4 12,4z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M21,2L3,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h7l-2,3v1h8v-1l-2,-3h7c1.1,0 2,-0.9 2,-2L23,4c0,-1.1 -0.9,-2 -2,-2zM21,14L3,14L3,4h18v10z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M15.5,5.5c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM5,12c-2.8,0 -5,2.2 -5,5s2.2,5 5,5 5,-2.2 5,-5 -2.2,-5 -5,-5zM5,20.5c-1.9,0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5 3.5,1.6 3.5,3.5 -1.6,3.5 -3.5,3.5zM10.8,10.5l2.4,-2.4 0.8,0.8c1.3,1.3 3,2.1 5.1,2.1L19.1,9c-1.5,0 -2.7,-0.6 -3.6,-1.5l-1.9,-1.9c-0.5,-0.4 -1,-0.6 -1.6,-0.6s-1.1,0.2 -1.4,0.6L7.8,8.4c-0.4,0.4 -0.6,0.9 -0.6,1.4 0,0.6 0.2,1.1 0.6,1.4L11,14v5h2v-6.2l-2.2,-2.3zM19,12c-2.8,0 -5,2.2 -5,5s2.2,5 5,5 5,-2.2 5,-5 -2.2,-5 -5,-5zM19,20.5c-1.9,0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5 3.5,1.6 3.5,3.5 -1.6,3.5 -3.5,3.5z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M13,3v1h-2L11,3h2m-1,7.11l5.38,1.77 2.39,0.78 -1.12,3.97c-0.54,-0.3 -0.94,-0.71 -1.14,-0.94L16,13.96l-1.51,1.72c-0.34,0.4 -1.28,1.32 -2.49,1.32s-2.15,-0.92 -2.49,-1.32L8,13.96l-1.51,1.72c-0.2,0.23 -0.6,0.63 -1.14,0.93l-1.13,-3.96 2.4,-0.79L12,10.11M15,1L9,1v3L6,4c-1.1,0 -2,0.9 -2,2v4.62l-1.29,0.42c-0.26,0.08 -0.48,0.26 -0.6,0.5s-0.15,0.52 -0.06,0.78L3.95,19L4,19c1.6,0 3.02,-0.88 4,-2 0.98,1.12 2.4,2 4,2s3.02,-0.88 4,-2c0.98,1.12 2.4,2 4,2h0.05l1.89,-6.68c0.08,-0.26 0.06,-0.54 -0.06,-0.78s-0.34,-0.42 -0.6,-0.5L20,10.62L20,6c0,-1.1 -0.9,-2 -2,-2h-3L15,1zM6,9.97L6,6h12v3.97L12,8 6,9.97zM16,19.68c-1.22,0.85 -2.61,1.28 -4,1.28s-2.78,-0.43 -4,-1.28C6.78,20.53 5.39,21 4,21L2,21v2h2c1.38,0 2.74,-0.35 4,-0.99 1.26,0.64 2.63,0.97 4,0.97s2.74,-0.32 4,-0.97c1.26,0.65 2.62,0.99 4,0.99h2v-2h-2c-1.39,0 -2.78,-0.47 -4,-1.32z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M13.49,5.48c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM9.89,19.38l1,-4.4 2.1,2v6h2v-7.5l-2.1,-2 0.6,-3c1.3,1.5 3.3,2.5 5.5,2.5v-2c-1.9,0 -3.5,-1 -4.3,-2.4l-1,-1.6c-0.4,-0.6 -1,-1 -1.7,-1 -0.3,0 -0.5,0.1 -0.8,0.1l-5.2,2.2v4.7h2v-3.4l1.8,-0.7 -1.6,8.1 -4.9,-1 -0.4,2 7,1.4z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M13.5,5.5c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM9.8,8.9L7,23h2.1l1.8,-8 2.1,2v6h2v-7.5l-2.1,-2 0.6,-3C14.8,12 16.8,13 19,13v-2c-1.9,0 -3.5,-1 -4.3,-2.4l-1,-1.6c-0.56,-0.89 -1.68,-1.25 -2.65,-0.84L6,8.3V13h2V9.6l1.8,-0.7"/>
</vector>

@ -1,7 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M18.92,5.01C18.72,4.42 18.16,4 17.5,4h-11c-0.66,0 -1.21,0.42 -1.42,1.01L3,11v8c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1h12v1c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-8l-2.08,-5.99zM6.85,6h10.29l1.04,3H5.81l1.04,-3zM19,16H5v-4.66l0.12,-0.34h13.77l0.11,0.34V16z"/>
<path android:fillColor="#FF000000" android:pathData="M7.5,13.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
<path android:fillColor="#FF000000" android:pathData="M16.5,13.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M10,20h4L14,4h-4v16zM4,20h4v-8L4,12v8zM16,9v11h4L20,9h-4z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M15,18.5c-2.51,0 -4.68,-1.42 -5.76,-3.5H15v-2H8.58c-0.05,-0.33 -0.08,-0.66 -0.08,-1s0.03,-0.67 0.08,-1H15V9H9.24C10.32,6.92 12.5,5.5 15,5.5c1.61,0 3.09,0.59 4.23,1.57L21,5.3C19.41,3.87 17.3,3 15,3c-3.92,0 -7.24,2.51 -8.48,6H3v2h3.06c-0.04,0.33 -0.06,0.66 -0.06,1s0.02,0.67 0.06,1H3v2h3.52c1.24,3.49 4.56,6 8.48,6 2.31,0 4.41,-0.87 6,-2.3l-1.78,-1.77c-1.13,0.98 -2.6,1.57 -4.22,1.57z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM6.5,17.5l7.51,-3.49L17.5,6.5 9.99,9.99 6.5,17.5zM12,10.9c0.61,0 1.1,0.49 1.1,1.1s-0.49,1.1 -1.1,1.1 -1.1,-0.49 -1.1,-1.1 0.49,-1.1 1.1,-1.1z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M1,21.98c0,0.56 0.45,1.01 1.01,1.01H15c0.56,0 1.01,-0.45 1.01,-1.01V21H1v0.98zM8.5,8.99C4.75,8.99 1,11 1,15h15c0,-4 -3.75,-6.01 -7.5,-6.01zM3.62,13c1.11,-1.55 3.47,-2.01 4.88,-2.01s3.77,0.46 4.88,2.01H3.62zM1,17h15v2H1zM18,5V1h-2v4h-5l0.23,2h9.56l-1.4,14H18v2h1.72c0.84,0 1.53,-0.65 1.63,-1.47L23,5h-5z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M20.57,14.86L22,13.43 20.57,12 17,15.57 8.43,7 12,3.43 10.57,2 9.14,3.43 7.71,2 5.57,4.14 4.14,2.71 2.71,4.14l1.43,1.43L2,7.71l1.43,1.43L2,10.57 3.43,12 7,8.43 15.57,17 12,20.57 13.43,22l1.43,-1.43L16.29,22l2.14,-2.14 1.43,1.43 1.43,-1.43 -1.43,-1.43L22,16.29l-1.43,-1.43z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M21,16v-2l-8,-5V3.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,2.67 10,3.5V9l-8,5v2l8,-2.5V19l-2,1.5V22l3.5,-1 3.5,1v-1.5L13,19v-5.5l8,2.5z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M2.5,19h19v2h-19v-2zM19.34,15.85c0.8,0.21 1.62,-0.26 1.84,-1.06 0.21,-0.8 -0.26,-1.62 -1.06,-1.84l-5.31,-1.42 -2.76,-9.02L10.12,2v8.28L5.15,8.95l-0.93,-2.32 -1.45,-0.39v5.17l16.57,4.44z"/>
</vector>

@ -1,5 +0,0 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M2.5,19h19v2h-19v-2zM22.07,9.64c-0.21,-0.8 -1.04,-1.28 -1.84,-1.06L14.92,10l-6.9,-6.43 -1.93,0.51 4.14,7.17 -4.97,1.33 -1.97,-1.54 -1.45,0.39 2.59,4.49L21,11.49c0.81,-0.23 1.28,-1.05 1.07,-1.85z"/>
</vector>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save