diff --git a/Habitica/build.gradle b/Habitica/build.gradle
index 76fbff872..6368c6a3a 100644
--- a/Habitica/build.gradle
+++ b/Habitica/build.gradle
@@ -150,7 +150,7 @@ android {
buildConfigField "String", "STORE", "\"google\""
multiDexEnabled true
- versionCode 2080
+ versionCode 2081
versionName "1.8.1"
}
diff --git a/Habitica/res/anim/rotate_45_degrees.xml b/Habitica/res/anim/rotate_45_degrees.xml
new file mode 100644
index 000000000..b2cf69b8f
--- /dev/null
+++ b/Habitica/res/anim/rotate_45_degrees.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/Habitica/res/drawable/plus_taskform.xml b/Habitica/res/drawable/plus_taskform.xml
new file mode 100644
index 000000000..e3979cd7f
--- /dev/null
+++ b/Habitica/res/drawable/plus_taskform.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/Habitica/res/drawable/task_form_control_bg.xml b/Habitica/res/drawable/task_form_control_bg.xml
new file mode 100644
index 000000000..64cd42452
--- /dev/null
+++ b/Habitica/res/drawable/task_form_control_bg.xml
@@ -0,0 +1,16 @@
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/activity_task_form.xml b/Habitica/res/layout/activity_task_form.xml
index 2cfebee45..bbb97492e 100644
--- a/Habitica/res/layout/activity_task_form.xml
+++ b/Habitica/res/layout/activity_task_form.xml
@@ -75,6 +75,17 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/task_form_reminder_item.xml b/Habitica/res/layout/task_form_reminder_item.xml
new file mode 100644
index 000000000..fbfa7e8ca
--- /dev/null
+++ b/Habitica/res/layout/task_form_reminder_item.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/layout/task_form_task_scheduling.xml b/Habitica/res/layout/task_form_task_scheduling.xml
new file mode 100644
index 000000000..31d20cf5d
--- /dev/null
+++ b/Habitica/res/layout/task_form_task_scheduling.xml
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 587eeac9e..447d9eca8 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -152,7 +152,7 @@
%d MP
You used %1$s for %2$d mana.
You used %1$s.
- new checklist item
+ New checklist entry
Add
Remember to check off your tasks
@@ -505,7 +505,7 @@
Monthly gem cap
Inactive
1 Month
- %d Months
+ %d Months
month
3 months
6 months
@@ -876,4 +876,14 @@
Assigned Stat
Monthly
Weekly
+ Repeats
+ Every
+ Scheduling
+ Days
+ Weeks
+ Months
+ Years
+ Checklist Text
+ New reminder
+ Streak
diff --git a/Habitica/res/values/styles.xml b/Habitica/res/values/styles.xml
index 83422e781..d6f363211 100644
--- a/Habitica/res/values/styles.xml
+++ b/Habitica/res/values/styles.xml
@@ -518,5 +518,11 @@
- 28dp
+
+
#99edecee
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt
index 77653bbbd..1764f7fbb 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt
@@ -81,10 +81,10 @@ open class Task : RealmObject, Parcelable {
private var weeksOfMonthString: String? = null
@Ignore
- private var daysOfMonth: MutableList? = null
+ private var daysOfMonth: List? = null
@Ignore
- private var weeksOfMonth: MutableList? = null
+ private var weeksOfMonth: List? = null
val completedChecklistCount: Int
get() = checklist?.count { it.completed } ?: 0
@@ -306,56 +306,54 @@ open class Task : RealmObject, Parcelable {
}
- fun setWeeksOfMonth(weeksOfMonth: MutableList) {
+ fun setWeeksOfMonth(weeksOfMonth: List?) {
this.weeksOfMonth = weeksOfMonth
this.weeksOfMonthString = this.weeksOfMonth?.toString()
}
fun getWeeksOfMonth(): List? {
if (weeksOfMonth == null) {
- weeksOfMonth = ArrayList()
+ val weeksOfMonth = mutableListOf()
if (weeksOfMonthString != null) {
try {
val obj = JSONArray(weeksOfMonthString)
var i = 0
while (i < obj.length()) {
- weeksOfMonth?.add(obj.getInt(i))
+ weeksOfMonth.add(obj.getInt(i))
i += 1
}
} catch (e: JSONException) {
e.printStackTrace()
}
- } else {
- weeksOfMonth = ArrayList()
}
+ this.weeksOfMonth = weeksOfMonth.toList()
}
return weeksOfMonth
}
- fun setDaysOfMonth(daysOfMonth: MutableList) {
+ fun setDaysOfMonth(daysOfMonth: List?) {
this.daysOfMonth = daysOfMonth
this.daysOfMonthString = daysOfMonth.toString()
}
fun getDaysOfMonth(): List? {
if (daysOfMonth == null) {
- daysOfMonth = ArrayList()
+ val daysOfMonth = mutableListOf()
if (daysOfMonthString != null) {
try {
val obj = JSONArray(daysOfMonthString)
var i = 0
while (i < obj.length()) {
- daysOfMonth?.add(obj.getInt(i))
+ daysOfMonth.add(obj.getInt(i))
i += 1
}
} catch (e: JSONException) {
e.printStackTrace()
}
- } else {
- daysOfMonth = ArrayList()
}
+ this.daysOfMonth = daysOfMonth
}
return daysOfMonth
@@ -381,6 +379,7 @@ open class Task : RealmObject, Parcelable {
const val FREQUENCY_WEEKLY = "weekly"
const val FREQUENCY_DAILY = "daily"
const val FREQUENCY_MONTHLY = "monthly"
+ const val FREQUENCY_YEARLY = "yearly"
@JvmField
val CREATOR: Parcelable.Creator = object : Parcelable.Creator {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/OldTaskFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/OldTaskFormActivity.kt
index 0bd7d880e..24aaa0de3 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/OldTaskFormActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/OldTaskFormActivity.kt
@@ -964,13 +964,8 @@ class OldTaskFormActivity : BaseActivity() {
val dayOfTheWeek = sharedPreferences.getString("FirstDayOfTheWeek",
Integer.toString(Calendar.getInstance().firstDayOfWeek))
val firstDayOfTheWeekHelper = FirstDayOfTheWeekHelper.newInstance(Integer.parseInt(dayOfTheWeek ?: "0"))
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT_WATCH) {
- @Suppress("DEPRECATION")
- datePickerDialog.datePicker.calendarView.firstDayOfWeek = firstDayOfTheWeekHelper.firstDayOfTheWeek
- } else {
- datePickerDialog.datePicker.firstDayOfWeek = firstDayOfTheWeekHelper
+ datePickerDialog.datePicker.firstDayOfWeek = firstDayOfTheWeekHelper
.firstDayOfTheWeek
- }
this.datePickerDialog.setButton(DialogInterface.BUTTON_NEUTRAL, resources.getString(R.string.today)) { _, _ -> setCalendar(Calendar.getInstance().time) }
updateDateText()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
index 295016c78..d4736a938 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
@@ -23,9 +23,6 @@ import com.habitrpg.android.habitica.models.tasks.HabitResetOption
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.ui.helpers.bindView
-import com.habitrpg.android.habitica.ui.views.tasks.form.HabitResetStreakButtons
-import com.habitrpg.android.habitica.ui.views.tasks.form.HabitScoringButtonsView
-import com.habitrpg.android.habitica.ui.views.tasks.form.TaskDifficultyButtons
import io.reactivex.functions.Consumer
import javax.inject.Inject
import android.content.res.ColorStateList
@@ -37,7 +34,9 @@ import androidx.core.view.children
import androidx.core.view.forEach
import androidx.core.view.forEachIndexed
import com.habitrpg.android.habitica.extensions.dpToPx
+import com.habitrpg.android.habitica.ui.views.tasks.form.*
import io.realm.RealmList
+import java.util.*
class TaskFormActivity : BaseActivity() {
@@ -54,13 +53,20 @@ class TaskFormActivity : BaseActivity() {
private val textEditText: EditText by bindView(R.id.text_edit_text)
private val notesEditText: EditText by bindView(R.id.notes_edit_text)
private val habitScoringButtons: HabitScoringButtonsView by bindView(R.id.habit_scoring_buttons)
+ private val checklistTitleView: TextView by bindView(R.id.checklist_title)
+ private val checklistContainer: ChecklistContainer by bindView(R.id.checklist_container)
private val habitResetStreakTitleView: TextView by bindView(R.id.habit_reset_streak_title)
private val habitResetStreakButtons: HabitResetStreakButtons by bindView(R.id.habit_reset_streak_buttons)
+ private val taskSchedulingTitleView: TextView by bindView(R.id.scheduling_title)
+ private val taskSchedulingControls: TaskSchedulingControls by bindView(R.id.scheduling_controls)
private val adjustStreakWrapper: ViewGroup by bindView(R.id.adjust_streak_wrapper)
private val adjustStreakTitleView: TextView by bindView(R.id.adjust_streak_title)
private val habitAdjustPositiveStreakView: EditText by bindView(R.id.habit_adjust_positive_streak)
private val habitAdjustNegativeStreakView: EditText by bindView(R.id.habit_adjust_negative_streak)
+ private val remindersTitleView: TextView by bindView(R.id.reminders_title)
+ private val remindersContainer: ReminderContainer by bindView(R.id.reminders_container)
+ private val taskDifficultyTitleView: TextView by bindView(R.id.task_difficulty_title)
private val taskDifficultyButtons: TaskDifficultyButtons by bindView(R.id.task_difficulty_buttons)
private val statWrapper: ViewGroup by bindView(R.id.stat_wrapper)
@@ -115,7 +121,7 @@ class TaskFormActivity : BaseActivity() {
val taskId = bundle.getString(OldTaskFormActivity.TASK_ID_KEY)
if (taskId != null) {
isCreating = false
- compositeSubscription.add(taskRepository.getUnmanagedTask(taskId).subscribe(Consumer {
+ compositeSubscription.add(taskRepository.getUnmanagedTask(taskId).firstElement().subscribe(Consumer {
task = it
//tintColor = ContextCompat.getColor(this, it.mediumTaskColor)
fillForm(it)
@@ -164,11 +170,32 @@ class TaskFormActivity : BaseActivity() {
habitScoringButtons.visibility = habitViewsVisibility
habitResetStreakTitleView.visibility = habitViewsVisibility
habitResetStreakButtons.visibility = habitViewsVisibility
- habitAdjustPositiveStreakView.visibility = habitViewsVisibility
habitAdjustNegativeStreakView.visibility = habitViewsVisibility
- val dailyViewsVisibility = if (taskType == Task.TYPE_DAILY) View.VISIBLE else View.GONE
- val todoViewsVisibility = if (taskType == Task.TYPE_TODO) View.VISIBLE else View.GONE
+ val habitDailyVisibility = if (taskType == Task.TYPE_DAILY || taskType == Task.TYPE_HABIT) View.VISIBLE else View.GONE
+ adjustStreakTitleView.visibility = habitDailyVisibility
+ adjustStreakWrapper.visibility = habitDailyVisibility
+ if (taskType == Task.TYPE_HABIT) {
+ habitAdjustPositiveStreakView.hint = getString(R.string.positive_habit_form)
+ } else {
+ habitAdjustPositiveStreakView.hint = getString(R.string.streak)
+ }
+
+ val todoDailyViewsVisibility = if (taskType == Task.TYPE_DAILY || taskType == Task.TYPE_TODO) View.VISIBLE else View.GONE
+
+ checklistTitleView.visibility = todoDailyViewsVisibility
+ checklistContainer.visibility = todoDailyViewsVisibility
+
+ remindersTitleView.visibility = todoDailyViewsVisibility
+ remindersContainer.visibility = todoDailyViewsVisibility
+
+ val rewardHideViews = if (taskType == Task.TYPE_REWARD) View.GONE else View.VISIBLE
+ taskDifficultyTitleView.visibility = rewardHideViews
+ taskDifficultyButtons.visibility = rewardHideViews
+
+ taskSchedulingTitleView.visibility = todoDailyViewsVisibility
+ taskSchedulingControls.visibility = todoDailyViewsVisibility
+ taskSchedulingControls.taskType = taskType
statWrapper.visibility = if (usesTaskAttributeStats) View.VISIBLE else View.GONE
if (isCreating) {
@@ -201,12 +228,28 @@ class TaskFormActivity : BaseActivity() {
textEditText.setText(task.text)
notesEditText.setText(task.notes)
taskDifficultyButtons.selectedDifficulty = task.priority
- if (taskType == Task.TYPE_HABIT) {
- habitScoringButtons.isPositive = task.up ?: false
- habitScoringButtons.isNegative = task.down ?: false
- task.frequency?.let { habitResetStreakButtons.selectedResetOption = HabitResetOption.valueOf(it.toUpperCase()) }
- habitAdjustPositiveStreakView.setText((task.counterUp ?: 0).toString())
- habitAdjustNegativeStreakView.setText((task.counterDown ?: 0).toString())
+ when (taskType) {
+ Task.TYPE_HABIT -> {
+ habitScoringButtons.isPositive = task.up ?: false
+ habitScoringButtons.isNegative = task.down ?: false
+ task.frequency?.let { habitResetStreakButtons.selectedResetOption = HabitResetOption.valueOf(it.toUpperCase()) }
+ habitAdjustPositiveStreakView.setText((task.counterUp ?: 0).toString())
+ habitAdjustNegativeStreakView.setText((task.counterDown ?: 0).toString())
+ }
+ Task.TYPE_DAILY -> {
+ taskSchedulingControls.startDate = task.startDate ?: Date()
+ taskSchedulingControls.frequency = task.frequency ?: Task.FREQUENCY_DAILY
+ taskSchedulingControls.everyX = task.everyX ?: 1
+ task.repeat?.let { taskSchedulingControls.weeklyRepeat = it }
+ taskSchedulingControls.daysOfMonth = task.getDaysOfMonth()
+ taskSchedulingControls.weeksOfMonth = task.getWeeksOfMonth()
+ habitAdjustPositiveStreakView.setText((task.streak ?: 0).toString())
+ }
+ Task.TYPE_TODO -> taskSchedulingControls.dueDate = task.dueDate
+ }
+ if (taskType == Task.TYPE_DAILY || taskType == Task.TYPE_TODO) {
+ task.checklist?.let { checklistContainer.checklistItems = it }
+ task.reminders?.let { remindersContainer.reminders = it }
}
task.attribute?.let { setSelectedAttribute(it) }
setAllTagSelections()
@@ -254,8 +297,22 @@ class TaskFormActivity : BaseActivity() {
thisTask.frequency = habitResetStreakButtons.selectedResetOption.value
if (habitAdjustPositiveStreakView.text.isNotEmpty()) thisTask.counterUp = habitAdjustPositiveStreakView.text.toString().toInt()
if (habitAdjustNegativeStreakView.text.isNotEmpty()) thisTask.counterDown = habitAdjustNegativeStreakView.text.toString().toInt()
+ } else if (taskType == Task.TYPE_DAILY) {
+ thisTask.startDate = taskSchedulingControls.startDate
+ thisTask.everyX = taskSchedulingControls.everyX
+ thisTask.frequency = taskSchedulingControls.frequency
+ thisTask.repeat = taskSchedulingControls.weeklyRepeat
+ thisTask.setDaysOfMonth(taskSchedulingControls.daysOfMonth)
+ thisTask.setWeeksOfMonth(taskSchedulingControls.weeksOfMonth)
+ if (habitAdjustPositiveStreakView.text.isNotEmpty()) thisTask.streak = habitAdjustPositiveStreakView.text.toString().toInt()
+ } else if (taskType == Task.TYPE_TODO) {
+ thisTask.dueDate = taskSchedulingControls.dueDate
}
+ if (taskType == Task.TYPE_DAILY || taskType == Task.TYPE_TODO) {
+ thisTask.checklist = checklistContainer.checklistItems
+ thisTask.reminders = remindersContainer.reminders
+ }
thisTask.tags = RealmList()
tagsWrapper.forEachIndexed { index, view ->
val tagView = view as? CheckBox
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt
index ab63696b5..255e3f0b7 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt
@@ -286,12 +286,8 @@ class TasksFragment : BaseMainFragment() {
return
}
- val allocationMode = user?.preferences?.hasTaskBasedAllocation() ?: false
-
val bundle = Bundle()
bundle.putString(OldTaskFormActivity.TASK_TYPE_KEY, type)
- bundle.putString(OldTaskFormActivity.USER_ID_KEY, if (this.user != null) this.user?.id else null)
- bundle.putBoolean(OldTaskFormActivity.ALLOCATION_MODE_KEY, allocationMode)
bundle.putBoolean(OldTaskFormActivity.SAVE_TO_DB, true)
val intent = Intent(activity, TaskFormActivity::class.java)
@@ -309,14 +305,9 @@ class TasksFragment : BaseMainFragment() {
return
}
- val allocationMode = user?.preferences?.hasTaskBasedAllocation() ?: false
-
val bundle = Bundle()
bundle.putString(OldTaskFormActivity.TASK_TYPE_KEY, event.Task.type)
bundle.putString(OldTaskFormActivity.TASK_ID_KEY, event.Task.id)
- bundle.putString(OldTaskFormActivity.USER_ID_KEY, if (this.user != null) this.user?.id else null)
- bundle.putBoolean(OldTaskFormActivity.ALLOCATION_MODE_KEY, allocationMode)
- bundle.putBoolean(OldTaskFormActivity.SAVE_TO_DB, true)
val intent = Intent(activity, TaskFormActivity::class.java)
intent.putExtras(bundle)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ChecklistContainer.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ChecklistContainer.kt
new file mode 100644
index 000000000..6085058e5
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ChecklistContainer.kt
@@ -0,0 +1,98 @@
+package com.habitrpg.android.habitica.ui.views.tasks.form
+
+import android.animation.LayoutTransition
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.widget.LinearLayout
+import androidx.core.view.children
+import androidx.core.view.updateMargins
+import com.habitrpg.android.habitica.extensions.dpToPx
+import com.habitrpg.android.habitica.models.tasks.ChecklistItem
+import io.realm.RealmList
+
+class ChecklistContainer @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : LinearLayout(context, attrs, defStyleAttr) {
+ var checklistItems: RealmList
+ get() {
+ val list = RealmList()
+ for (child in children) {
+ val view = child as? ChecklistItemFormView ?: continue
+ if (view.item.text?.isNotEmpty() == true) {
+ list.add(view.item)
+ }
+ }
+ return list
+ }
+ set(value) {
+ val unAnimatedTransitions = LayoutTransition()
+ unAnimatedTransitions.disableTransitionType(LayoutTransition.APPEARING)
+ unAnimatedTransitions.disableTransitionType(LayoutTransition.CHANGING)
+ unAnimatedTransitions.disableTransitionType(LayoutTransition.DISAPPEARING)
+ layoutTransition = unAnimatedTransitions
+ if (childCount > 1) {
+ for (child in children.take(childCount - 1)) {
+ removeView(child)
+ }
+ }
+ for (item in value) {
+ addChecklistViewAt(childCount-1, item)
+ }
+ val animatedTransitions = LayoutTransition()
+ layoutTransition = animatedTransitions
+ }
+
+ init {
+ orientation = LinearLayout.VERTICAL
+
+ addChecklistViewAt(0)
+ }
+
+ private fun addChecklistViewAt(index: Int, item: ChecklistItem? = null) {
+ val view = ChecklistItemFormView(context)
+ item?.let {
+ view.item = it
+ view.isAddButton = false
+ }
+ view.textChangedListener = {
+ if (isLastChild(view)) {
+ addChecklistViewAt(-1)
+ view.animDuration = 300
+ view.isAddButton = false
+ } else if (shouldBecomeNewAddButton(view)) {
+ removeViewAt(childCount-1)
+ view.animDuration = 300
+ view.isAddButton = true
+ }
+ }
+ val indexToUse = if (index < 0) {
+ childCount - index
+ } else {
+ index
+ }
+ if (childCount <= indexToUse) {
+ addView(view)
+ view.isAddButton = true
+ } else {
+ addView(view, indexToUse)
+ }
+ val layoutParams = view.layoutParams as? LinearLayout.LayoutParams
+ layoutParams?.updateMargins(bottom = 8.dpToPx(context))
+ view.layoutParams = layoutParams
+ }
+
+ private fun shouldBecomeNewAddButton(view: ChecklistItemFormView): Boolean {
+ if (childCount > 2 && view.item.text?.isEmpty() != false && children.indexOf(view) == childCount-2) {
+ val lastView = (getChildAt(childCount-1) as? ChecklistItemFormView)
+ if (lastView != null && lastView.item.text?.isEmpty() != false) {
+ return true
+ }
+ }
+ return false
+ }
+
+ private fun isLastChild(view: View): Boolean {
+ return children.lastOrNull() == view
+ }
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ChecklistItemFormView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ChecklistItemFormView.kt
new file mode 100644
index 000000000..1956be9d3
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ChecklistItemFormView.kt
@@ -0,0 +1,90 @@
+package com.habitrpg.android.habitica.ui.views.tasks.form
+
+import android.animation.ObjectAnimator
+import android.content.Context
+import android.text.Editable
+import android.text.TextWatcher
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.ViewGroup
+import android.widget.EditText
+import android.widget.ImageButton
+import android.widget.LinearLayout
+import androidx.core.content.ContextCompat
+import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.extensions.dpToPx
+import com.habitrpg.android.habitica.extensions.inflate
+import com.habitrpg.android.habitica.models.tasks.ChecklistItem
+import com.habitrpg.android.habitica.ui.helpers.bindView
+import android.view.animation.LinearInterpolator
+import android.view.animation.Animation
+import android.view.animation.RotateAnimation
+
+
+
+
+class ChecklistItemFormView @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : LinearLayout(context, attrs, defStyleAttr), TextWatcher {
+
+
+ private val button: ImageButton by bindView(R.id.button)
+ private val editText: EditText by bindView(R.id.edit_text)
+
+ var item: ChecklistItem = ChecklistItem()
+ set(value) {
+ field = value
+ editText.setText(item.text)
+ }
+
+ var tintColor: Int = ContextCompat.getColor(context, R.color.brand_300)
+ var textChangedListener: ((String) -> Unit)? = null
+ var animDuration = 0L
+ var isAddButton: Boolean = true
+ set(value) {
+ field = value
+ editText.hint = context.getString(if (value) R.string.new_checklist_item else R.string.checklist_text)
+ if (value) {
+ val rotate = RotateAnimation(135f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
+ rotate.duration = animDuration
+ rotate.interpolator = LinearInterpolator()
+ rotate.fillAfter = true
+ button.startAnimation(rotate)
+ } else {
+ val rotate = RotateAnimation(0f, 135f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
+ rotate.duration = animDuration
+ rotate.interpolator = LinearInterpolator()
+ rotate.fillAfter = true
+ button.startAnimation(rotate)
+ }
+ }
+
+ init {
+ minimumHeight = 38.dpToPx(context)
+ inflate(R.layout.task_form_checklist_item, true)
+ background = context.getDrawable(R.drawable.layout_rounded_bg_task_form)
+ background.mutate().setTint(ContextCompat.getColor(context, R.color.taskform_gray))
+ gravity = Gravity.CENTER_VERTICAL
+
+ button.setOnClickListener {
+ if (!isAddButton) {
+ (parent as? ViewGroup)?.removeView(this)
+ }
+ }
+ button.drawable.mutate().setTint(tintColor)
+
+ editText.addTextChangedListener(this)
+ }
+
+ override fun afterTextChanged(s: Editable?) {
+ }
+
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
+ }
+
+ override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
+ item.text = s.toString()
+ textChangedListener?.let { it(s.toString()) }
+ }
+
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt
index 74249bf85..13dbc567b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/HabitScoringButtonsView.kt
@@ -64,6 +64,4 @@ class HabitScoringButtonsView @JvmOverloads constructor(
isPositive = true
isNegative = true
}
-
-
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ReminderContainer.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ReminderContainer.kt
new file mode 100644
index 000000000..91215f4af
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ReminderContainer.kt
@@ -0,0 +1,85 @@
+package com.habitrpg.android.habitica.ui.views.tasks.form
+
+import android.animation.LayoutTransition
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.widget.LinearLayout
+import androidx.core.view.children
+import androidx.core.view.updateMargins
+import com.habitrpg.android.habitica.extensions.dpToPx
+import com.habitrpg.android.habitica.models.tasks.ChecklistItem
+import com.habitrpg.android.habitica.models.tasks.RemindersItem
+import io.realm.RealmList
+
+class ReminderContainer @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : LinearLayout(context, attrs, defStyleAttr) {
+ var reminders: RealmList
+ get() {
+ val list = RealmList()
+ for (child in children) {
+ val view = child as? ReminderItemFormView ?: continue
+ if (view.item.time != null) {
+ list.add(view.item)
+ }
+ }
+ return list
+ }
+ set(value) {
+ val unAnimatedTransitions = LayoutTransition()
+ unAnimatedTransitions.disableTransitionType(LayoutTransition.APPEARING)
+ unAnimatedTransitions.disableTransitionType(LayoutTransition.CHANGING)
+ unAnimatedTransitions.disableTransitionType(LayoutTransition.DISAPPEARING)
+ layoutTransition = unAnimatedTransitions
+ if (childCount > 1) {
+ for (child in children.take(childCount - 1)) {
+ removeView(child)
+ }
+ }
+ for (item in value) {
+ addReminderViewAt(childCount-1, item)
+ }
+ val animatedTransitions = LayoutTransition()
+ layoutTransition = animatedTransitions
+ }
+
+ init {
+ orientation = LinearLayout.VERTICAL
+
+ addReminderViewAt(0)
+ }
+
+ private fun addReminderViewAt(index: Int, item: RemindersItem? = null) {
+ val view = ReminderItemFormView(context)
+ item?.let {
+ view.item = it
+ view.isAddButton = false
+ }
+ view.valueChangedListener = {
+ if (isLastChild(view)) {
+ addReminderViewAt(-1)
+ view.animDuration = 300
+ view.isAddButton = false
+ }
+ }
+ val indexToUse = if (index < 0) {
+ childCount - index
+ } else {
+ index
+ }
+ if (childCount <= indexToUse) {
+ addView(view)
+ view.isAddButton = true
+ } else {
+ addView(view, indexToUse)
+ }
+ val layoutParams = view.layoutParams as? LinearLayout.LayoutParams
+ layoutParams?.updateMargins(bottom = 8.dpToPx(context))
+ view.layoutParams = layoutParams
+ }
+
+ private fun isLastChild(view: View): Boolean {
+ return children.lastOrNull() == view
+ }
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ReminderItemFormView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ReminderItemFormView.kt
new file mode 100644
index 000000000..684f0039c
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/ReminderItemFormView.kt
@@ -0,0 +1,99 @@
+package com.habitrpg.android.habitica.ui.views.tasks.form
+
+import android.app.DatePickerDialog
+import android.app.TimePickerDialog
+import android.content.Context
+import android.content.DialogInterface
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.ViewGroup
+import android.view.animation.Animation
+import android.view.animation.LinearInterpolator
+import android.view.animation.RotateAnimation
+import android.widget.ImageButton
+import android.widget.LinearLayout
+import android.widget.TextView
+import android.widget.TimePicker
+import androidx.core.content.ContextCompat
+import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.extensions.dpToPx
+import com.habitrpg.android.habitica.extensions.inflate
+import com.habitrpg.android.habitica.models.tasks.RemindersItem
+import com.habitrpg.android.habitica.ui.helpers.bindView
+import java.text.DateFormat
+import java.util.*
+
+
+class ReminderItemFormView @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : LinearLayout(context, attrs, defStyleAttr), TimePickerDialog.OnTimeSetListener {
+
+
+ private val button: ImageButton by bindView(R.id.button)
+ private val textView: TextView by bindView(R.id.text_view)
+
+ private val formatter = DateFormat.getTimeInstance(DateFormat.SHORT)
+
+ var item: RemindersItem = RemindersItem()
+ set(value) {
+ field = value
+ textView.text = formatter.format(item.time)
+ }
+
+ var tintColor: Int = ContextCompat.getColor(context, R.color.brand_300)
+ var valueChangedListener: ((Date) -> Unit)? = null
+ var animDuration = 0L
+ var isAddButton: Boolean = true
+ set(value) {
+ field = value
+ textView.text = if (value) context.getString(R.string.new_reminder) else formatter.format(item.time)
+ if (value) {
+ val rotate = RotateAnimation(135f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
+ rotate.duration = animDuration
+ rotate.interpolator = LinearInterpolator()
+ rotate.fillAfter = true
+ button.startAnimation(rotate)
+ } else {
+ val rotate = RotateAnimation(0f, 135f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f)
+ rotate.duration = animDuration
+ rotate.interpolator = LinearInterpolator()
+ rotate.fillAfter = true
+ button.startAnimation(rotate)
+ }
+ }
+
+ init {
+ minimumHeight = 38.dpToPx(context)
+ inflate(R.layout.task_form_reminder_item, true)
+ background = context.getDrawable(R.drawable.layout_rounded_bg_task_form)
+ background.mutate().setTint(ContextCompat.getColor(context, R.color.taskform_gray))
+ gravity = Gravity.CENTER_VERTICAL
+
+ button.setOnClickListener {
+ if (!isAddButton) {
+ (parent as? ViewGroup)?.removeView(this)
+ }
+ }
+ button.drawable.mutate().setTint(tintColor)
+
+ textView.setOnClickListener {
+ val calendar = Calendar.getInstance()
+ item.time?.let { calendar.time = it }
+ val timePickerDialog = TimePickerDialog(context, this,
+ calendar.get(Calendar.HOUR_OF_DAY),
+ calendar.get(Calendar.MINUTE),
+ android.text.format.DateFormat.is24HourFormat(context))
+ timePickerDialog.show()
+ }
+ }
+ override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
+ valueChangedListener?.let {
+ val calendar = Calendar.getInstance()
+ calendar.set(Calendar.HOUR_OF_DAY, hourOfDay)
+ calendar.set(Calendar.MINUTE, minute)
+ item.time = calendar.time
+ textView.text = formatter.format(item.time)
+ item.time?.let { date -> it(date) }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt
index 31f2980d5..855e66c0f 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskDifficultyButtons.kt
@@ -52,10 +52,10 @@ class TaskDifficultyButtons @JvmOverloads constructor(
val isActive = selectedDifficulty == difficulty.value
var difficultyColor = ContextCompat.getColor(context, R.color.white)
if (isActive) {
- view.findViewById(R.id.image_view).background.setTint(tintColor)
+ view.findViewById(R.id.image_view).background.mutate().setTint(tintColor)
view.findViewById(R.id.text_view).setTextColor(tintColor)
} else {
- view.findViewById(R.id.image_view).background.setTint(ContextCompat.getColor(context, R.color.taskform_gray))
+ view.findViewById(R.id.image_view).background.mutate().setTint(ContextCompat.getColor(context, R.color.taskform_gray))
view.findViewById(R.id.text_view).setTextColor(ContextCompat.getColor(context, R.color.gray_100))
difficultyColor = ContextCompat.getColor(context, R.color.gray_400)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskSchedulingControls.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskSchedulingControls.kt
new file mode 100644
index 000000000..508d048c9
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/form/TaskSchedulingControls.kt
@@ -0,0 +1,269 @@
+package com.habitrpg.android.habitica.ui.views.tasks.form
+
+import android.app.DatePickerDialog
+import android.content.Context
+import android.content.DialogInterface
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.*
+import androidx.appcompat.widget.AppCompatEditText
+import androidx.appcompat.widget.AppCompatTextView
+import androidx.core.content.ContextCompat
+import androidx.preference.PreferenceManager
+import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.extensions.dpToPx
+import com.habitrpg.android.habitica.extensions.inflate
+import com.habitrpg.android.habitica.helpers.FirstDayOfTheWeekHelper
+import com.habitrpg.android.habitica.models.tasks.Days
+import com.habitrpg.android.habitica.models.tasks.Task
+import com.habitrpg.android.habitica.ui.helpers.bindView
+import java.text.DateFormat
+import java.text.DateFormatSymbols
+import java.util.*
+
+class TaskSchedulingControls @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : LinearLayout(context, attrs, defStyleAttr), DatePickerDialog.OnDateSetListener {
+
+ var tintColor: Int = ContextCompat.getColor(context, R.color.brand_300)
+
+ private val startDateWrapper: ViewGroup by bindView(R.id.start_date_wrapper)
+ private val startDateTitleView: TextView by bindView(R.id.start_date_title)
+ private val startDateTextView: TextView by bindView(R.id.start_date_textview)
+ private val repeatsEveryWrapper: ViewGroup by bindView(R.id.repeats_every_wrapper)
+ private val repeatsEverySpinner: Spinner by bindView(R.id.repeats_every_spinner)
+ private val repeatsEveryEdittext: AppCompatEditText by bindView(R.id.repeats_every_edittext)
+ private val repeatsEveryTitleView: TextView by bindView(R.id.repeats_every_title)
+ private val weeklyRepeatWrapper: ViewGroup by bindView(R.id.weekly_repeat_wrapper)
+ private val monthlyRepeatWrapper: ViewGroup by bindView(R.id.monthly_repeat_wrapper)
+ private val monthlyRepeatDaysButton: TextView by bindView(R.id.monthly_repeat_days)
+ private val monthlyRepeatWeeksButton: TextView by bindView(R.id.monthly_repeat_weeks)
+ private val summaryTextView: TextView by bindView(R.id.summary_textview)
+
+ private val dateFormatter = DateFormat.getDateInstance(DateFormat.MEDIUM)
+ private val frequencyAdapter = ArrayAdapter.createFromResource(context,
+ R.array.repeatables_frequencies, android.R.layout.simple_spinner_item)
+
+ var taskType = Task.TYPE_DAILY
+ set(value) {
+ field = value
+ configureViewsForType()
+ }
+ var startDate = Date()
+ set(value) {
+ field = value
+ startDateTextView.text = dateFormatter.format(value)
+ startDateCalendar.time = value
+ }
+ private var startDateCalendar = Calendar.getInstance()
+ var dueDate: Date? = null
+ set(value) {
+ field = value
+ value?.let { startDateTextView.text = dateFormatter.format(it) }
+ }
+ var frequency = Task.FREQUENCY_DAILY
+ set(value) {
+ field = value
+ repeatsEverySpinner.setSelection(when (value) {
+ Task.FREQUENCY_WEEKLY -> 1
+ Task.FREQUENCY_MONTHLY -> 2
+ Task.FREQUENCY_YEARLY -> 3
+ else -> 0
+ })
+ configureViewsForFrequency()
+ }
+ var everyX
+ get() = (repeatsEveryEdittext.text ?: "1").toString().toInt()
+ set(value) {
+ repeatsEveryEdittext.setText(value.toString())
+ }
+ var weeklyRepeat: Days = Days()
+ set(value) {
+ field = value
+ createWeeklyRepeatViews()
+ }
+
+ var daysOfMonth: List? = null
+ set(value) {
+ field = value
+ configureMonthlyRepeatViews()
+ }
+ var weeksOfMonth: List? = null
+ set(value) {
+ field = value
+ configureMonthlyRepeatViews()
+ }
+
+ private val weekdays: Array by lazy {
+ DateFormatSymbols().weekdays
+ }
+ private val weekdayOrder: List by lazy {
+ val codes = (1..7).toList()
+ Collections.rotate(codes, -startDateCalendar.firstDayOfWeek)
+ codes
+ }
+
+ init {
+ inflate(R.layout.task_form_task_scheduling, true)
+ repeatsEverySpinner.adapter = frequencyAdapter
+
+ repeatsEverySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onNothingSelected(parent: AdapterView<*>?) {
+ frequency = frequency
+ }
+
+ override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
+ frequency = when (position) {
+ 1 -> Task.FREQUENCY_WEEKLY
+ 2 -> Task.FREQUENCY_MONTHLY
+ 3 -> Task.FREQUENCY_YEARLY
+ else -> Task.FREQUENCY_DAILY
+ }
+ }
+ }
+
+ startDateWrapper.setOnClickListener {
+ val datePickerDialog = DatePickerDialog(context, this,
+ startDateCalendar.get(Calendar.YEAR),
+ startDateCalendar.get(Calendar.MONTH),
+ startDateCalendar.get(Calendar.DAY_OF_MONTH))
+ datePickerDialog.setButton(DialogInterface.BUTTON_NEUTRAL, resources.getString(R.string.today)) { _, _ ->
+ if (taskType == Task.TYPE_TODO) {
+ dueDate = Date()
+ } else {
+ startDate = Date()
+ }
+ }
+ if (taskType == Task.TYPE_TODO) {
+ datePickerDialog.setButton(DialogInterface.BUTTON_NEUTRAL, resources.getString(R.string.clear)) { _, _ ->
+ dueDate = null
+ }
+ }
+ datePickerDialog.show()
+ }
+
+ monthlyRepeatDaysButton.setOnClickListener {
+ daysOfMonth = mutableListOf(startDateCalendar.get(Calendar.DATE))
+ weeksOfMonth = null
+ }
+ monthlyRepeatWeeksButton.setOnClickListener {
+ weeksOfMonth = mutableListOf(startDateCalendar.get(Calendar.WEEK_OF_MONTH))
+ daysOfMonth = null
+ }
+
+ orientation = LinearLayout.VERTICAL
+ configureViewsForType()
+ configureViewsForFrequency()
+ }
+
+ private fun configureViewsForType() {
+ startDateTitleView.text = context.getString(if (taskType == Task.TYPE_DAILY) R.string.start_date else R.string.due_date)
+ repeatsEveryWrapper.visibility = if (taskType == Task.TYPE_DAILY) View.VISIBLE else View.GONE
+ }
+
+ override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
+ startDateCalendar.set(year, month, dayOfMonth)
+ if (taskType == Task.TYPE_TODO) {
+ dueDate = startDateCalendar.time
+ } else {
+ startDate = startDateCalendar.time
+ }
+ }
+
+ private fun configureViewsForFrequency() {
+ repeatsEveryTitleView.text = context.getText(when (frequency) {
+ Task.FREQUENCY_WEEKLY -> R.string.weeks
+ Task.FREQUENCY_MONTHLY -> R.string.months
+ Task.FREQUENCY_YEARLY -> R.string.years
+ else -> R.string.days
+ })
+ weeklyRepeatWrapper.visibility = if (frequency == Task.FREQUENCY_WEEKLY && taskType == Task.TYPE_DAILY) View.VISIBLE else View.GONE
+ monthlyRepeatWrapper.visibility = if (frequency == Task.FREQUENCY_MONTHLY && taskType == Task.TYPE_DAILY) View.VISIBLE else View.GONE
+ if (frequency == Task.FREQUENCY_WEEKLY) {
+ createWeeklyRepeatViews()
+ } else if (frequency == Task.FREQUENCY_MONTHLY) {
+ if (weeksOfMonth?.isNotEmpty() != true && daysOfMonth?.isNotEmpty() != true) {
+ daysOfMonth = listOf(startDateCalendar.get(Calendar.DATE))
+ }
+ }
+ }
+
+ private fun setWeekdayActive(weekday: Int, isActive: Boolean) {
+ when (weekday) {
+ 2 -> weeklyRepeat.m = isActive
+ 3 -> weeklyRepeat.t = isActive
+ 4 -> weeklyRepeat.w = isActive
+ 5 -> weeklyRepeat.th = isActive
+ 6 -> weeklyRepeat.f = isActive
+ 7 -> weeklyRepeat.s = isActive
+ 1 -> weeklyRepeat.su = isActive
+ }
+ createWeeklyRepeatViews()
+ }
+
+ private fun isWeekdayActive(weekday: Int): Boolean {
+ return when (weekday) {
+ 2 -> weeklyRepeat.m
+ 3 -> weeklyRepeat.t
+ 4 -> weeklyRepeat.w
+ 5 -> weeklyRepeat.th
+ 6 -> weeklyRepeat.f
+ 7 -> weeklyRepeat.s
+ 1 -> weeklyRepeat.su
+ else -> false
+ }
+ }
+
+ private fun createWeeklyRepeatViews() {
+ weeklyRepeatWrapper.removeAllViews()
+ val size = 32.dpToPx(context)
+ val lastWeekday = weekdayOrder.last()
+ for (weekdayCode in weekdayOrder) {
+ val button = TextView(context, null, 0, R.style.TaskFormWeekdayButton)
+ val layoutParams = LinearLayout.LayoutParams(size, size)
+ button.layoutParams = layoutParams
+ button.text = weekdays[weekdayCode].first().toUpperCase().toString()
+ val isActive = isWeekdayActive(weekdayCode)
+ if (isActive) {
+ button.background = context.getDrawable(R.drawable.habit_scoring_circle_selected)
+ button.background.mutate().setTint(tintColor)
+ button.setTextColor(ContextCompat.getColor(context, R.color.white))
+ } else {
+ button.background = context.getDrawable(R.drawable.habit_scoring_circle)
+ button.setTextColor(ContextCompat.getColor(context, R.color.gray_100))
+ }
+ button.setOnClickListener {
+ setWeekdayActive(weekdayCode, !isActive)
+ }
+ weeklyRepeatWrapper.addView(button)
+ if (weekdayCode != lastWeekday) {
+ val space = Space(context)
+ val spaceLayoutParams = LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT)
+ spaceLayoutParams.weight = 1f
+ space.layoutParams = spaceLayoutParams
+ weeklyRepeatWrapper.addView(space)
+ }
+ }
+ }
+
+ private fun configureMonthlyRepeatViews() {
+ val white = ContextCompat.getColor(context, R.color.white)
+ val unselectedText = ContextCompat.getColor(context, R.color.gray_100)
+ val unselectedBackground = ContextCompat.getColor(context, R.color.taskform_gray)
+ if (daysOfMonth != null && daysOfMonth?.isEmpty() != true) {
+ monthlyRepeatDaysButton.setTextColor(white)
+ monthlyRepeatDaysButton.background.mutate().setTint(tintColor)
+ } else {
+ monthlyRepeatDaysButton.setTextColor(unselectedText)
+ monthlyRepeatDaysButton.background.mutate().setTint(unselectedBackground)
+ }
+ if (weeksOfMonth != null && weeksOfMonth?.isEmpty() != true) {
+ monthlyRepeatWeeksButton.setTextColor(white)
+ monthlyRepeatWeeksButton.background.mutate().setTint(tintColor)
+ } else {
+ monthlyRepeatWeeksButton.setTextColor(unselectedText)
+ monthlyRepeatWeeksButton.background.mutate().setTint(unselectedBackground)
+ }
+ }
+}
\ No newline at end of file