diff --git a/app/src/main/java/org/tasks/ui/ChipListCache.java b/app/src/main/java/org/tasks/ui/ChipListCache.java index 86fe472c6..3d653d75a 100644 --- a/app/src/main/java/org/tasks/ui/ChipListCache.java +++ b/app/src/main/java/org/tasks/ui/ChipListCache.java @@ -18,7 +18,7 @@ import org.tasks.data.TagDataDao; import org.tasks.injection.ApplicationScope; @ApplicationScope -class ChipListCache { +public class ChipListCache { private final Map googleTaskLists = new HashMap<>(); private final Map caldavCalendars = new HashMap<>(); diff --git a/app/src/main/java/org/tasks/ui/ChipProvider.java b/app/src/main/java/org/tasks/ui/ChipProvider.java deleted file mode 100644 index 9f4eeaa84..000000000 --- a/app/src/main/java/org/tasks/ui/ChipProvider.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.tasks.ui; - -import static com.google.common.collect.Collections2.filter; -import static com.google.common.collect.Collections2.transform; -import static com.google.common.collect.Iterables.removeIf; -import static com.google.common.collect.Sets.newHashSet; -import static com.todoroo.andlib.utility.AndroidUtilities.assertMainThread; -import static org.tasks.Strings.isNullOrEmpty; - -import android.app.Activity; -import android.content.res.ColorStateList; -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.content.res.ResourcesCompat; -import com.google.android.material.chip.Chip; -import com.google.common.base.Predicates; -import com.google.common.collect.Ordering; -import com.todoroo.astrid.api.CaldavFilter; -import com.todoroo.astrid.api.Filter; -import com.todoroo.astrid.api.GtasksFilter; -import com.todoroo.astrid.api.TagFilter; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import javax.inject.Inject; -import org.tasks.R; -import org.tasks.billing.Inventory; -import org.tasks.data.Location; -import org.tasks.data.TagData; -import org.tasks.data.TaskContainer; -import org.tasks.filters.PlaceFilter; -import org.tasks.locale.Locale; -import org.tasks.preferences.Preferences; -import org.tasks.themes.ColorProvider; -import org.tasks.themes.CustomIcons; -import org.tasks.themes.ThemeColor; - -public class ChipProvider { - - private final Activity activity; - private final Inventory inventory; - private final int iconAlpha; - private final ChipListCache lists; - private final Preferences preferences; - private final ColorProvider colorProvider; - private final Locale locale; - private final Ordering orderByName = - new Ordering() { - @Override - public int compare(TagFilter left, TagFilter right) { - return left.listingTitle.compareTo(right.listingTitle); - } - }; - private boolean filled; - private boolean showIcon; - private boolean showText; - - @Inject - public ChipProvider( - Activity activity, - Inventory inventory, - ChipListCache lists, - Preferences preferences, - ColorProvider colorProvider, - Locale locale) { - this.activity = activity; - this.inventory = inventory; - iconAlpha = - (int) (255 * ResourcesCompat.getFloat(activity.getResources(), R.dimen.alpha_secondary)); - this.lists = lists; - this.preferences = preferences; - this.colorProvider = colorProvider; - this.locale = locale; - - setStyle(preferences.getIntegerFromString(R.string.p_chip_style, 0)); - setAppearance(preferences.getIntegerFromString(R.string.p_chip_appearance, 0)); - } - - public void setStyle(int style) { - filled = style == 1; - } - - public void setAppearance(int appearance) { - showText = appearance != 2; - showIcon = appearance != 1; - } - - public Chip newSubtaskChip(TaskContainer task, boolean compact) { - Chip chip = newChip(task); - apply( - chip, - task.isCollapsed() - ? R.drawable.ic_keyboard_arrow_up_black_24dp - : R.drawable.ic_keyboard_arrow_down_black_24dp, - compact - ? locale.formatNumber(task.children) - : activity - .getResources() - .getQuantityString(R.plurals.subtask_count, task.children, task.children), - 0, - true, - true); - return chip; - } - - public List getChips(Filter filter, boolean isSubtask, TaskContainer task) { - assertMainThread(); - - List chips = new ArrayList<>(); - if (task.hasChildren()) { - chips.add(newSubtaskChip(task, !showText)); - } - if (preferences.getBoolean(R.string.p_show_list_indicators, true)) { - if (task.hasLocation() && !(filter instanceof PlaceFilter)) { - Location location = task.getLocation(); - chips.add(newChip(new PlaceFilter(location.getPlace()), R.drawable.ic_outline_place_24px)); - } - if (!isSubtask) { - if (!isNullOrEmpty(task.getGoogleTaskList()) && !(filter instanceof GtasksFilter)) { - chips.add( - newChip( - lists.getGoogleTaskList(task.getGoogleTaskList()), - R.drawable.ic_list_24px)); - } else if (!isNullOrEmpty(task.getCaldav()) && !(filter instanceof CaldavFilter)) { - chips.add( - newChip(lists.getCaldavList(task.getCaldav()), R.drawable.ic_list_24px)); - } - } - String tagString = task.getTagsString(); - if (!isNullOrEmpty(tagString)) { - Set tags = newHashSet(tagString.split(",")); - if (filter instanceof TagFilter) { - tags.remove(((TagFilter) filter).getUuid()); - } - chips.addAll( - transform( - orderByName.sortedCopy(filter(transform(tags, lists::getTag), Predicates.notNull())), - tag -> newChip(tag, R.drawable.ic_outline_label_24px))); - } - } - - removeIf(chips, Predicates.isNull()); - return chips; - } - - public void apply(Chip chip, @NonNull TagData tagData) { - apply( - chip, - getIcon(tagData.getIcon(), R.drawable.ic_outline_label_24px), - tagData.getName(), - tagData.getColor(), - true, - true); - } - - private @Nullable Chip newChip(Filter filter, int defIcon) { - return newChip(filter, defIcon, showText, showIcon); - } - - Chip newChip(Filter filter, int defIcon, boolean showText, boolean showIcon) { - if (filter == null) { - return null; - } - Chip chip = newChip(filter); - apply(chip, getIcon(filter.icon, defIcon), filter.listingTitle, filter.tint, showText, showIcon); - return chip; - } - - public Chip newClosableChip(Object tag) { - Chip chip = getChip(); - chip.setCloseIconVisible(true); - chip.setTag(tag); - return chip; - } - - private Chip newChip(@Nullable Object tag) { - Chip chip = getChip(); - chip.setTag(tag); - return chip; - } - - private Chip getChip() { - return (Chip) - activity - .getLayoutInflater() - .inflate(filled ? R.layout.chip_filled : R.layout.chip_outlined, null); - } - - private void apply( - Chip chip, - @Nullable @DrawableRes Integer icon, - String name, - int theme, - boolean showText, - boolean showIcon) { - if (showText) { - chip.setText(name); - chip.setIconEndPadding(0f); - } else { - chip.setText(null); - chip.setContentDescription(name); - chip.setTextStartPadding(0f); - chip.setChipEndPadding(0f); - } - ThemeColor themeColor = getColor(theme); - if (themeColor != null) { - int primaryColor = themeColor.getPrimaryColor(); - ColorStateList primaryColorSL = - new ColorStateList(new int[][] {new int[] {}}, new int[] {primaryColor}); - if (filled) { - int colorOnPrimary = themeColor.getColorOnPrimary(); - ColorStateList colorOnPrimarySL = - new ColorStateList(new int[][] {new int[] {}}, new int[] {colorOnPrimary}); - chip.setChipBackgroundColor(primaryColorSL); - chip.setTextColor(colorOnPrimary); - chip.setCloseIconTint(colorOnPrimarySL); - chip.setChipIconTint(colorOnPrimarySL); - } else { - chip.setTextColor(primaryColor); - chip.setCloseIconTint(primaryColorSL); - chip.setChipIconTint(primaryColorSL); - chip.setChipStrokeColor(primaryColorSL); - } - } - if (showIcon && icon != null) { - chip.setChipIconResource(icon); - chip.getChipDrawable().setAlpha(iconAlpha); - } - } - - private @DrawableRes Integer getIcon(int index, int def) { - Integer icon = CustomIcons.getIconResId(index); - return icon != null ? icon : def; - } - - private @Nullable ThemeColor getColor(int theme) { - if (theme != 0) { - ThemeColor color = colorProvider.getThemeColor(theme, true); - if (color.isFree() || inventory.purchasedThemes()) { - return color; - } - } - return null; - } -} diff --git a/app/src/main/java/org/tasks/ui/ChipProvider.kt b/app/src/main/java/org/tasks/ui/ChipProvider.kt new file mode 100644 index 000000000..7688c6938 --- /dev/null +++ b/app/src/main/java/org/tasks/ui/ChipProvider.kt @@ -0,0 +1,195 @@ +package org.tasks.ui + +import android.app.Activity +import android.content.res.ColorStateList +import androidx.annotation.DrawableRes +import androidx.core.content.res.ResourcesCompat +import com.google.android.material.chip.Chip +import com.todoroo.andlib.utility.AndroidUtilities +import com.todoroo.astrid.api.CaldavFilter +import com.todoroo.astrid.api.Filter +import com.todoroo.astrid.api.GtasksFilter +import com.todoroo.astrid.api.TagFilter +import org.tasks.R +import org.tasks.Strings.isNullOrEmpty +import org.tasks.billing.Inventory +import org.tasks.data.TagData +import org.tasks.data.TaskContainer +import org.tasks.filters.PlaceFilter +import org.tasks.locale.Locale +import org.tasks.preferences.Preferences +import org.tasks.themes.ColorProvider +import org.tasks.themes.CustomIcons.getIconResId +import org.tasks.themes.ThemeColor +import java.util.* +import javax.inject.Inject + +class ChipProvider @Inject constructor( + private val activity: Activity, + private val inventory: Inventory, + private val lists: ChipListCache, + private val preferences: Preferences, + private val colorProvider: ColorProvider, + private val locale: Locale) { + + private val iconAlpha: Int = (255 * ResourcesCompat.getFloat(activity.resources, R.dimen.alpha_secondary)).toInt() + private var filled = false + private var showIcon = false + private var showText = false + + fun setStyle(style: Int) { + filled = style == 1 + } + + fun setAppearance(appearance: Int) { + showText = appearance != 2 + showIcon = appearance != 1 + } + + fun newSubtaskChip(task: TaskContainer, compact: Boolean): Chip { + val chip = newChip(task) + apply( + chip, + if (task.isCollapsed) R.drawable.ic_keyboard_arrow_up_black_24dp else R.drawable.ic_keyboard_arrow_down_black_24dp, + if (compact) locale.formatNumber(task.children) else activity + .resources + .getQuantityString(R.plurals.subtask_count, task.children, task.children), + 0, + showText = true, + showIcon = true) + return chip + } + + fun getChips(filter: Filter?, isSubtask: Boolean, task: TaskContainer): List { + AndroidUtilities.assertMainThread() + val chips = ArrayList() + if (task.hasChildren()) { + chips.add(newSubtaskChip(task, !showText)) + } + if (preferences.getBoolean(R.string.p_show_list_indicators, true)) { + if (task.hasLocation() && filter !is PlaceFilter) { + val location = task.getLocation() + newChip(PlaceFilter(location.place), R.drawable.ic_outline_place_24px)?.let(chips::add) + } + if (!isSubtask) { + if (!isNullOrEmpty(task.googleTaskList) && filter !is GtasksFilter) { + newChip(lists.getGoogleTaskList(task.googleTaskList), R.drawable.ic_list_24px) + ?.let(chips::add) + } else if (!isNullOrEmpty(task.caldav) && filter !is CaldavFilter) { + newChip(lists.getCaldavList(task.caldav), R.drawable.ic_list_24px)?.let(chips::add) + } + } + val tagString = task.tagsString + if (!isNullOrEmpty(tagString)) { + val tags = tagString.split(",").toHashSet() + if (filter is TagFilter) { + tags.remove(filter.uuid) + } + tags.mapNotNull(lists::getTag) + .sortedBy(TagFilter::listingTitle) + .map { newChip(it, R.drawable.ic_outline_label_24px)!! } + .let(chips::addAll) + } + } + return chips + } + + fun apply(chip: Chip, tagData: TagData) { + apply( + chip, + getIcon(tagData.getIcon()!!, R.drawable.ic_outline_label_24px), + tagData.name, + tagData.getColor()!!, + showText = true, + showIcon = true) + } + + private fun newChip(filter: Filter?, defIcon: Int): Chip? { + return newChip(filter, defIcon, showText, showIcon) + } + + fun newChip(filter: Filter?, defIcon: Int, showText: Boolean, showIcon: Boolean): Chip? { + if (filter == null) { + return null + } + val chip = newChip(filter) + apply(chip, getIcon(filter.icon, defIcon), filter.listingTitle, filter.tint, showText, showIcon) + return chip + } + + fun newClosableChip(tag: Any?): Chip { + val chip = chip + chip.isCloseIconVisible = true + chip.tag = tag + return chip + } + + private fun newChip(tag: Any?): Chip { + val chip = chip + chip.tag = tag + return chip + } + + private val chip: Chip + get() = activity + .layoutInflater + .inflate(if (filled) R.layout.chip_filled else R.layout.chip_outlined, null) as Chip + + private fun apply( + chip: Chip, + @DrawableRes icon: Int?, + name: String?, + theme: Int, + showText: Boolean, + showIcon: Boolean) { + if (showText) { + chip.text = name + chip.iconEndPadding = 0f + } else { + chip.text = null + chip.contentDescription = name + chip.textStartPadding = 0f + chip.chipEndPadding = 0f + } + val themeColor = getColor(theme) + if (themeColor != null) { + val primaryColor = themeColor.primaryColor + val primaryColorSL = ColorStateList(arrayOf(intArrayOf()), intArrayOf(primaryColor)) + if (filled) { + val colorOnPrimary = themeColor.colorOnPrimary + val colorOnPrimarySL = ColorStateList(arrayOf(intArrayOf()), intArrayOf(colorOnPrimary)) + chip.chipBackgroundColor = primaryColorSL + chip.setTextColor(colorOnPrimary) + chip.closeIconTint = colorOnPrimarySL + chip.chipIconTint = colorOnPrimarySL + } else { + chip.setTextColor(primaryColor) + chip.closeIconTint = primaryColorSL + chip.chipIconTint = primaryColorSL + chip.chipStrokeColor = primaryColorSL + } + } + if (showIcon && icon != null) { + chip.setChipIconResource(icon) + chip.chipDrawable.alpha = iconAlpha + } + } + + @DrawableRes + private fun getIcon(index: Int, def: Int) = getIconResId(index) ?: def + + private fun getColor(theme: Int): ThemeColor? { + if (theme != 0) { + val color = colorProvider.getThemeColor(theme, true) + if (color.isFree || inventory.purchasedThemes()) { + return color + } + } + return null + } + + init { + setStyle(preferences.getIntegerFromString(R.string.p_chip_style, 0)) + setAppearance(preferences.getIntegerFromString(R.string.p_chip_appearance, 0)) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/ui/ListFragment.kt b/app/src/main/java/org/tasks/ui/ListFragment.kt index a08e248e5..8052aaba8 100644 --- a/app/src/main/java/org/tasks/ui/ListFragment.kt +++ b/app/src/main/java/org/tasks/ui/ListFragment.kt @@ -163,7 +163,7 @@ class ListFragment : TaskEditControlFragment() { private fun refreshView() { chipGroup.removeAllViews() - val chip = chipProvider.newChip(selectedList, R.drawable.ic_list_24px, true, true) + val chip = chipProvider.newChip(selectedList, R.drawable.ic_list_24px, showText = true, showIcon = true)!! chip.setOnClickListener { openPicker() } chipGroup.addView(chip) }