mirror of https://github.com/tasks/tasks
Repurpose "Hide until" as "Start date"
parent
7ac2421957
commit
7f5cbf372a
@ -1,259 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2012 Todoroo Inc
|
|
||||||
*
|
|
||||||
* See the file "LICENSE" for the full license governing this code.
|
|
||||||
*/
|
|
||||||
package com.todoroo.astrid.ui
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.*
|
|
||||||
import android.widget.AdapterView.OnItemSelectedListener
|
|
||||||
import butterknife.BindView
|
|
||||||
import butterknife.OnClick
|
|
||||||
import com.todoroo.andlib.utility.DateUtilities
|
|
||||||
import com.todoroo.astrid.data.Task
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import org.tasks.R
|
|
||||||
import org.tasks.activities.DateAndTimePickerActivity
|
|
||||||
import org.tasks.date.DateTimeUtils
|
|
||||||
import org.tasks.dialogs.MyTimePickerDialog
|
|
||||||
import org.tasks.locale.Locale
|
|
||||||
import org.tasks.preferences.Preferences
|
|
||||||
import org.tasks.ui.HiddenTopArrayAdapter
|
|
||||||
import org.tasks.ui.TaskEditControlFragment
|
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Control set for specifying when a task should be hidden
|
|
||||||
*
|
|
||||||
* @author Tim Su <tim></tim>@todoroo.com>
|
|
||||||
*/
|
|
||||||
@AndroidEntryPoint
|
|
||||||
class HideUntilControlSet : TaskEditControlFragment(), OnItemSelectedListener {
|
|
||||||
private val spinnerItems: MutableList<HideUntilValue> = ArrayList()
|
|
||||||
|
|
||||||
@Inject lateinit var activity: Activity
|
|
||||||
@Inject lateinit var preferences: Preferences
|
|
||||||
@Inject lateinit var locale: Locale
|
|
||||||
|
|
||||||
@BindView(R.id.hideUntil)
|
|
||||||
lateinit var spinner: Spinner
|
|
||||||
|
|
||||||
@BindView(R.id.clear)
|
|
||||||
lateinit var clearButton: ImageView
|
|
||||||
|
|
||||||
private lateinit var adapter: ArrayAdapter<HideUntilValue>
|
|
||||||
private var previousSetting = Task.HIDE_UNTIL_NONE
|
|
||||||
private var selection = 0
|
|
||||||
private var existingDate = EXISTING_TIME_UNSET
|
|
||||||
|
|
||||||
@OnClick(R.id.clear)
|
|
||||||
fun clearHideUntil() {
|
|
||||||
updateSpinnerOptions(0)
|
|
||||||
selection = 0
|
|
||||||
spinner.setSelection(selection)
|
|
||||||
refreshDisplayView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRowClick() {
|
|
||||||
spinner.performClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createView(savedInstanceState: Bundle?) {
|
|
||||||
adapter = object : HiddenTopArrayAdapter<HideUntilValue>(
|
|
||||||
activity, android.R.layout.simple_spinner_item, spinnerItems) {
|
|
||||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
|
||||||
var selectedItemPosition = position
|
|
||||||
if (parent is AdapterView<*>) {
|
|
||||||
selectedItemPosition = parent.selectedItemPosition
|
|
||||||
}
|
|
||||||
val tv = activity.layoutInflater.inflate(android.R.layout.simple_spinner_item, parent, false) as TextView
|
|
||||||
tv.setPadding(0, 0, 0, 0)
|
|
||||||
val value = getItem(selectedItemPosition)
|
|
||||||
if (value!!.setting == Task.HIDE_UNTIL_NONE) {
|
|
||||||
clearButton.visibility = View.GONE
|
|
||||||
tv.text = value.labelDisplay
|
|
||||||
tv.setTextColor(activity.getColor(R.color.text_tertiary))
|
|
||||||
} else {
|
|
||||||
val display = value.labelDisplay
|
|
||||||
tv.text = getString(R.string.TEA_hideUntil_display, display)
|
|
||||||
tv.setTextColor(activity.getColor(R.color.text_primary))
|
|
||||||
}
|
|
||||||
return tv
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (savedInstanceState == null) {
|
|
||||||
val dueDate = viewModel.dueDate!!
|
|
||||||
var hideUntil = viewModel.hideUntil!!
|
|
||||||
val dueDay = DateTimeUtils.newDateTime(dueDate)
|
|
||||||
.withHourOfDay(0)
|
|
||||||
.withMinuteOfHour(0)
|
|
||||||
.withSecondOfMinute(0)
|
|
||||||
.withMillisOfSecond(0)
|
|
||||||
|
|
||||||
// For the hide until due case, we need the time component
|
|
||||||
val dueTime = dueDate / 1000L * 1000L
|
|
||||||
if (hideUntil <= 0) {
|
|
||||||
selection = 0
|
|
||||||
hideUntil = 0
|
|
||||||
if (viewModel.isNew) {
|
|
||||||
when (preferences.getIntegerFromString(R.string.p_default_hideUntil_key, Task.HIDE_UNTIL_NONE)) {
|
|
||||||
Task.HIDE_UNTIL_DUE -> selection = 1
|
|
||||||
Task.HIDE_UNTIL_DUE_TIME -> selection = 2
|
|
||||||
Task.HIDE_UNTIL_DAY_BEFORE -> selection = 3
|
|
||||||
Task.HIDE_UNTIL_WEEK_BEFORE -> selection = 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (hideUntil == dueDay.millis) {
|
|
||||||
selection = 1
|
|
||||||
hideUntil = 0
|
|
||||||
} else if (hideUntil == dueTime) {
|
|
||||||
selection = 2
|
|
||||||
hideUntil = 0
|
|
||||||
} else if (hideUntil + DateUtilities.ONE_DAY == dueDay.millis) {
|
|
||||||
selection = 3
|
|
||||||
hideUntil = 0
|
|
||||||
} else if (hideUntil + DateUtilities.ONE_WEEK == dueDay.millis) {
|
|
||||||
selection = 4
|
|
||||||
hideUntil = 0
|
|
||||||
}
|
|
||||||
updateSpinnerOptions(hideUntil)
|
|
||||||
} else {
|
|
||||||
updateSpinnerOptions(savedInstanceState.getLong(EXTRA_CUSTOM))
|
|
||||||
selection = savedInstanceState.getInt(EXTRA_SELECTION)
|
|
||||||
}
|
|
||||||
spinner.adapter = adapter
|
|
||||||
spinner.setSelection(selection)
|
|
||||||
spinner.onItemSelectedListener = this
|
|
||||||
refreshDisplayView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val layout = R.layout.control_set_hide
|
|
||||||
|
|
||||||
override val icon = R.drawable.ic_outline_visibility_off_24px
|
|
||||||
|
|
||||||
override fun controlId() = TAG
|
|
||||||
|
|
||||||
override val isClickable = true
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
||||||
if (requestCode == REQUEST_HIDE_UNTIL) {
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
setCustomDate(data!!.getLongExtra(MyTimePickerDialog.EXTRA_TIMESTAMP, 0L))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
super.onSaveInstanceState(outState)
|
|
||||||
outState.putLong(EXTRA_CUSTOM, existingDate)
|
|
||||||
outState.putInt(EXTRA_SELECTION, selection)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateSpinnerOptions(specificDate: Long) {
|
|
||||||
spinnerItems.clear()
|
|
||||||
// set up base values
|
|
||||||
val labelsSpinner = resources.getStringArray(R.array.TEA_hideUntil_spinner)
|
|
||||||
val labelsDisplay = resources.getStringArray(R.array.TEA_hideUntil_display)
|
|
||||||
spinnerItems.addAll(
|
|
||||||
ArrayList(
|
|
||||||
listOf(
|
|
||||||
HideUntilValue(labelsSpinner[0], labelsDisplay[0], Task.HIDE_UNTIL_DUE),
|
|
||||||
HideUntilValue(labelsSpinner[1], labelsDisplay[1], Task.HIDE_UNTIL_DUE_TIME),
|
|
||||||
HideUntilValue(labelsSpinner[2], labelsDisplay[2], Task.HIDE_UNTIL_DAY_BEFORE),
|
|
||||||
HideUntilValue(labelsSpinner[3], labelsDisplay[3], Task.HIDE_UNTIL_WEEK_BEFORE),
|
|
||||||
HideUntilValue(
|
|
||||||
labelsSpinner[4],
|
|
||||||
"",
|
|
||||||
Task.HIDE_UNTIL_SPECIFIC_DAY,
|
|
||||||
-1)))) // no need for a string for display here, since the chosen day will be
|
|
||||||
// displayed
|
|
||||||
existingDate = if (specificDate > 0) {
|
|
||||||
spinnerItems.add(0, getHideUntilValue(specificDate))
|
|
||||||
specificDate
|
|
||||||
} else {
|
|
||||||
spinnerItems.add(
|
|
||||||
0, HideUntilValue(getString(R.string.TEA_hideUntil_label), Task.HIDE_UNTIL_NONE))
|
|
||||||
EXISTING_TIME_UNSET
|
|
||||||
}
|
|
||||||
adapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getHideUntilValue(timestamp: Long): HideUntilValue {
|
|
||||||
val hideUntilAsDate = DateTimeUtils.newDateTime(timestamp)
|
|
||||||
return if (hideUntilAsDate.hourOfDay == 0 && hideUntilAsDate.minuteOfHour == 0 && hideUntilAsDate.secondOfMinute == 0) {
|
|
||||||
HideUntilValue(
|
|
||||||
DateUtilities.getDateString(context, DateTimeUtils.newDateTime(timestamp)),
|
|
||||||
Task.HIDE_UNTIL_SPECIFIC_DAY,
|
|
||||||
timestamp)
|
|
||||||
} else {
|
|
||||||
HideUntilValue(
|
|
||||||
DateUtilities.getLongDateStringWithTime(timestamp, locale.locale),
|
|
||||||
Task.HIDE_UNTIL_SPECIFIC_DAY_TIME,
|
|
||||||
timestamp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
|
|
||||||
// if specific date selected, show dialog
|
|
||||||
// ... at conclusion of dialog, update our list
|
|
||||||
val item = adapter.getItem(position)
|
|
||||||
if (item!!.date == SPECIFIC_DATE.toLong()) {
|
|
||||||
val customDate = DateTimeUtils.newDateTime(if (existingDate == EXISTING_TIME_UNSET) DateUtilities.now() else existingDate)
|
|
||||||
.withSecondOfMinute(0)
|
|
||||||
val intent = Intent(activity, DateAndTimePickerActivity::class.java)
|
|
||||||
intent.putExtra(DateAndTimePickerActivity.EXTRA_TIMESTAMP, customDate.millis)
|
|
||||||
startActivityForResult(intent, REQUEST_HIDE_UNTIL)
|
|
||||||
spinner.setSelection(previousSetting)
|
|
||||||
} else {
|
|
||||||
previousSetting = position
|
|
||||||
}
|
|
||||||
selection = spinner.selectedItemPosition
|
|
||||||
refreshDisplayView()
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- listening for events
|
|
||||||
private fun setCustomDate(timestamp: Long) {
|
|
||||||
updateSpinnerOptions(timestamp)
|
|
||||||
spinner.setSelection(0)
|
|
||||||
refreshDisplayView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(arg0: AdapterView<*>?) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refreshDisplayView() {
|
|
||||||
viewModel.hideUntilValue = adapter.getItem(selection)
|
|
||||||
clearButton.visibility = if (viewModel.hideUntilValue!!.setting == Task.HIDE_UNTIL_NONE) View.GONE else View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
class HideUntilValue internal constructor(
|
|
||||||
private val labelSpinner: String,
|
|
||||||
val labelDisplay: String,
|
|
||||||
val setting: Int,
|
|
||||||
val date: Long = 0
|
|
||||||
) {
|
|
||||||
internal constructor(label: String, setting: Int) : this(label, label, setting, 0)
|
|
||||||
|
|
||||||
internal constructor(label: String, setting: Int, date: Long) : this(label, label, setting, date)
|
|
||||||
|
|
||||||
override fun toString() = labelSpinner
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = R.string.TEA_ctrl_hide_until_pref
|
|
||||||
private const val EXTRA_CUSTOM = "extra_custom"
|
|
||||||
private const val EXTRA_SELECTION = "extra_selection"
|
|
||||||
private const val SPECIFIC_DATE = -1
|
|
||||||
private const val EXISTING_TIME_UNSET = -2L
|
|
||||||
private const val REQUEST_HIDE_UNTIL = 11011
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
package com.todoroo.astrid.ui
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.TextView
|
||||||
|
import butterknife.BindView
|
||||||
|
import com.todoroo.andlib.utility.DateUtilities
|
||||||
|
import com.todoroo.andlib.utility.DateUtilities.now
|
||||||
|
import com.todoroo.astrid.data.Task
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import org.tasks.R
|
||||||
|
import org.tasks.date.DateTimeUtils.newDateTime
|
||||||
|
import org.tasks.date.DateTimeUtils.toDateTime
|
||||||
|
import org.tasks.dialogs.StartDatePicker
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.DAY_BEFORE_DUE
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.DUE_DATE
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.DUE_TIME
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.EXTRA_DAY
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.EXTRA_TIME
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.NO_DAY
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.NO_TIME
|
||||||
|
import org.tasks.dialogs.StartDatePicker.Companion.WEEK_BEFORE_DUE
|
||||||
|
import org.tasks.locale.Locale
|
||||||
|
import org.tasks.preferences.Preferences
|
||||||
|
import org.tasks.time.DateTimeUtils.millisOfDay
|
||||||
|
import org.tasks.time.DateTimeUtils.startOfDay
|
||||||
|
import org.tasks.ui.TaskEditControlFragment
|
||||||
|
import java.time.format.FormatStyle
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class StartDateControlSet : TaskEditControlFragment() {
|
||||||
|
@Inject lateinit var activity: Activity
|
||||||
|
@Inject lateinit var preferences: Preferences
|
||||||
|
@Inject lateinit var locale: Locale
|
||||||
|
|
||||||
|
@BindView(R.id.start_date)
|
||||||
|
lateinit var startDate: TextView
|
||||||
|
|
||||||
|
private val dueDateTime
|
||||||
|
get() = viewModel.dueDate!!
|
||||||
|
|
||||||
|
private var selectedDay = NO_DAY
|
||||||
|
private var selectedTime = NO_TIME
|
||||||
|
|
||||||
|
override fun onRowClick() {
|
||||||
|
val fragmentManager = parentFragmentManager
|
||||||
|
if (fragmentManager.findFragmentByTag(FRAG_TAG_DATE_PICKER) == null) {
|
||||||
|
StartDatePicker.newDateTimePicker(
|
||||||
|
this,
|
||||||
|
REQUEST_HIDE_UNTIL,
|
||||||
|
selectedDay,
|
||||||
|
selectedTime,
|
||||||
|
preferences.getBoolean(R.string.p_auto_dismiss_datetime_edit_screen, false))
|
||||||
|
.show(fragmentManager, FRAG_TAG_DATE_PICKER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createView(savedInstanceState: Bundle?) {
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
val dueDay = dueDateTime.startOfDay()
|
||||||
|
val dueTime = dueDateTime.millisOfDay()
|
||||||
|
val hideUntil = viewModel.hideUntil?.takeIf { it > 0 }?.toDateTime()
|
||||||
|
if (hideUntil == null) {
|
||||||
|
if (viewModel.isNew) {
|
||||||
|
when (preferences.getIntegerFromString(R.string.p_default_hideUntil_key, Task.HIDE_UNTIL_NONE)) {
|
||||||
|
Task.HIDE_UNTIL_DUE -> selectedDay = DUE_DATE
|
||||||
|
Task.HIDE_UNTIL_DUE_TIME -> selectedDay = DUE_TIME
|
||||||
|
Task.HIDE_UNTIL_DAY_BEFORE -> selectedDay = DAY_BEFORE_DUE
|
||||||
|
Task.HIDE_UNTIL_WEEK_BEFORE -> selectedDay = WEEK_BEFORE_DUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selectedDay = hideUntil.startOfDay().millis
|
||||||
|
selectedTime = hideUntil.millisOfDay
|
||||||
|
selectedDay = when (selectedDay) {
|
||||||
|
dueDay -> if (selectedTime == dueTime) {
|
||||||
|
selectedTime = NO_TIME
|
||||||
|
DUE_TIME
|
||||||
|
} else {
|
||||||
|
DUE_DATE
|
||||||
|
}
|
||||||
|
dueDay.toDateTime().minusDays(1).millis ->
|
||||||
|
DAY_BEFORE_DUE
|
||||||
|
dueDay.toDateTime().minusDays(7).millis ->
|
||||||
|
WEEK_BEFORE_DUE
|
||||||
|
else -> selectedDay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selectedDay = savedInstanceState.getLong(EXTRA_DAY)
|
||||||
|
selectedTime = savedInstanceState.getInt(EXTRA_TIME)
|
||||||
|
}
|
||||||
|
refreshDisplayView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val layout = R.layout.control_set_hide
|
||||||
|
|
||||||
|
override val icon = R.drawable.ic_pending_actions_24px
|
||||||
|
|
||||||
|
override fun controlId() = TAG
|
||||||
|
|
||||||
|
override val isClickable = true
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
if (requestCode == REQUEST_HIDE_UNTIL) {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
selectedDay = data?.getLongExtra(EXTRA_DAY, 0L) ?: NO_DAY
|
||||||
|
selectedTime = data?.getIntExtra(EXTRA_TIME, 0) ?: NO_TIME
|
||||||
|
applySelectionToHideUntil()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putLong(EXTRA_DAY, selectedDay)
|
||||||
|
outState.putInt(EXTRA_TIME, selectedTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRelativeDateString(resId: Int) = if (selectedTime == NO_TIME) {
|
||||||
|
getString(resId)
|
||||||
|
} else {
|
||||||
|
"${getString(resId)} ${DateUtilities.getTimeString(context, newDateTime().withMillisOfDay(selectedTime))}"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshDisplayView() {
|
||||||
|
startDate.text = when (selectedDay) {
|
||||||
|
DUE_DATE -> getRelativeDateString(R.string.due_date)
|
||||||
|
DUE_TIME -> getString(R.string.due_time)
|
||||||
|
DAY_BEFORE_DUE -> getRelativeDateString(R.string.day_before_due)
|
||||||
|
WEEK_BEFORE_DUE -> getRelativeDateString(R.string.week_before_due)
|
||||||
|
in 1..Long.MAX_VALUE -> DateUtilities.getRelativeDateTime(
|
||||||
|
activity,
|
||||||
|
selectedDay + selectedTime,
|
||||||
|
locale.locale,
|
||||||
|
FormatStyle.FULL,
|
||||||
|
preferences.alwaysDisplayFullDate,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
val started = viewModel.hideUntil?.takeIf { it > 0 }?.let { it < now() } ?: false
|
||||||
|
startDate.setTextColor(
|
||||||
|
activity.getColor(if (started) R.color.overdue else R.color.text_primary)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onDueDateChanged() = applySelectionToHideUntil()
|
||||||
|
|
||||||
|
private fun applySelectionToHideUntil() {
|
||||||
|
val due = dueDateTime.takeIf { it > 0 }?.toDateTime()
|
||||||
|
val millisOfDay = selectedTime
|
||||||
|
viewModel.hideUntil = when (selectedDay) {
|
||||||
|
DUE_DATE -> due?.withMillisOfDay(millisOfDay)?.millis ?: 0
|
||||||
|
DUE_TIME -> due?.millis ?: 0
|
||||||
|
DAY_BEFORE_DUE -> due?.minusDays(1)?.withMillisOfDay(millisOfDay)?.millis ?: 0
|
||||||
|
WEEK_BEFORE_DUE -> due?.minusDays(7)?.withMillisOfDay(millisOfDay)?.millis ?: 0
|
||||||
|
else -> selectedDay + selectedTime
|
||||||
|
}
|
||||||
|
refreshDisplayView()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = R.string.TEA_ctrl_hide_until_pref
|
||||||
|
private const val REQUEST_HIDE_UNTIL = 11011
|
||||||
|
private const val FRAG_TAG_DATE_PICKER = "frag_tag_date_picker"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,235 @@
|
|||||||
|
package org.tasks.dialogs
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.Activity.RESULT_OK
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import butterknife.ButterKnife
|
||||||
|
import butterknife.OnClick
|
||||||
|
import com.todoroo.andlib.utility.DateUtilities
|
||||||
|
import com.todoroo.astrid.dao.TaskDao
|
||||||
|
import com.todoroo.astrid.data.Task
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import org.tasks.R
|
||||||
|
import org.tasks.databinding.DialogStartDatePickerBinding
|
||||||
|
import org.tasks.date.DateTimeUtils.newDateTime
|
||||||
|
import org.tasks.dialogs.MyTimePickerDialog.newTimePicker
|
||||||
|
import org.tasks.locale.Locale
|
||||||
|
import org.tasks.notifications.NotificationManager
|
||||||
|
import org.tasks.time.DateTime
|
||||||
|
import java.time.format.FormatStyle
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class StartDatePicker : BaseDateTimePicker() {
|
||||||
|
|
||||||
|
@Inject lateinit var activity: Activity
|
||||||
|
@Inject lateinit var locale: Locale
|
||||||
|
@Inject lateinit var taskDao: TaskDao
|
||||||
|
@Inject lateinit var notificationManager: NotificationManager
|
||||||
|
|
||||||
|
lateinit var binding: DialogStartDatePickerBinding
|
||||||
|
private var customDate = NO_DAY
|
||||||
|
private var customTime = NO_TIME
|
||||||
|
private var selectedDay = NO_DAY
|
||||||
|
private var selectedTime = NO_TIME
|
||||||
|
private val today = newDateTime().startOfDay()
|
||||||
|
override val calendarView get() = binding.calendarView
|
||||||
|
override val morningButton get() = binding.shortcuts.morningButton
|
||||||
|
override val afternoonButton get() = binding.shortcuts.afternoonButton
|
||||||
|
override val eveningButton get() = binding.shortcuts.eveningButton
|
||||||
|
override val nightButton get() = binding.shortcuts.nightButton
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val REQUEST_TIME = 10101
|
||||||
|
private const val FRAG_TAG_TIME_PICKER = "frag_tag_time_picker"
|
||||||
|
const val EXTRA_DAY = "extra_day"
|
||||||
|
const val EXTRA_TIME = "extra_time"
|
||||||
|
const val NO_DAY = 0L
|
||||||
|
const val NO_TIME = 0
|
||||||
|
const val DUE_DATE = -1L
|
||||||
|
const val DAY_BEFORE_DUE = -2L
|
||||||
|
const val WEEK_BEFORE_DUE = -3L
|
||||||
|
const val DUE_TIME = -4L
|
||||||
|
|
||||||
|
fun newDateTimePicker(target: Fragment, rc: Int, day: Long, time: Int, autoClose: Boolean): StartDatePicker {
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putLong(EXTRA_DAY, day)
|
||||||
|
bundle.putInt(EXTRA_TIME, time)
|
||||||
|
bundle.putBoolean(EXTRA_AUTO_CLOSE, autoClose)
|
||||||
|
val fragment = StartDatePicker()
|
||||||
|
fragment.arguments = bundle
|
||||||
|
fragment.setTargetFragment(target, rc)
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
binding = DialogStartDatePickerBinding.inflate(theme.getLayoutInflater(context))
|
||||||
|
setupShortcutsAndCalendar()
|
||||||
|
ButterKnife.bind(this, binding.root)
|
||||||
|
binding.calendarView.setOnDateChangeListener { _, y, m, d ->
|
||||||
|
returnDate(day = DateTime(y, m + 1, d).millis)
|
||||||
|
refreshButtons()
|
||||||
|
}
|
||||||
|
selectedDay = savedInstanceState?.getLong(EXTRA_DAY) ?: requireArguments().getLong(EXTRA_DAY)
|
||||||
|
selectedTime =
|
||||||
|
savedInstanceState?.getInt(EXTRA_TIME)
|
||||||
|
?: requireArguments().getInt(EXTRA_TIME)
|
||||||
|
.takeIf { Task.hasDueTime(it.toLong()) }
|
||||||
|
?: NO_TIME
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refreshButtons() {
|
||||||
|
when (selectedDay) {
|
||||||
|
0L -> binding.shortcuts.dateGroup.check(R.id.no_date_button)
|
||||||
|
DUE_DATE -> binding.shortcuts.dateGroup.check(R.id.due_date_button)
|
||||||
|
DUE_TIME -> {
|
||||||
|
binding.shortcuts.dateGroup.check(R.id.due_time_button)
|
||||||
|
binding.shortcuts.timeGroup.clearChecked()
|
||||||
|
}
|
||||||
|
DAY_BEFORE_DUE -> binding.shortcuts.dateGroup.check(R.id.day_before_due_button)
|
||||||
|
WEEK_BEFORE_DUE -> binding.shortcuts.dateGroup.check(R.id.week_before_due_button)
|
||||||
|
else -> {
|
||||||
|
customDate = selectedDay
|
||||||
|
binding.shortcuts.dateGroup.check(R.id.current_date_selection)
|
||||||
|
binding.shortcuts.currentDateSelection.visibility = View.VISIBLE
|
||||||
|
binding.shortcuts.currentDateSelection.text =
|
||||||
|
DateUtilities.getRelativeDay(context, selectedDay, locale.locale, FormatStyle.MEDIUM)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Task.hasDueTime(selectedTime.toLong())) {
|
||||||
|
when (selectedTime) {
|
||||||
|
morning -> binding.shortcuts.timeGroup.check(R.id.morning_button)
|
||||||
|
afternoon -> binding.shortcuts.timeGroup.check(R.id.afternoon_button)
|
||||||
|
evening -> binding.shortcuts.timeGroup.check(R.id.evening_button)
|
||||||
|
night -> binding.shortcuts.timeGroup.check(R.id.night_button)
|
||||||
|
else -> {
|
||||||
|
customTime = selectedTime
|
||||||
|
binding.shortcuts.timeGroup.check(R.id.current_time_selection)
|
||||||
|
binding.shortcuts.currentTimeSelection.visibility = View.VISIBLE
|
||||||
|
binding.shortcuts.currentTimeSelection.text = DateUtilities.getTimeString(context, today.withMillisOfDay(selectedTime))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedDay == DUE_TIME) {
|
||||||
|
selectedDay = DUE_DATE
|
||||||
|
}
|
||||||
|
} else if (selectedDay != DUE_TIME) {
|
||||||
|
binding.shortcuts.timeGroup.check(R.id.no_time)
|
||||||
|
}
|
||||||
|
if (selectedDay > 0) {
|
||||||
|
binding.calendarView.setDate(selectedDay, true, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.no_date_button)
|
||||||
|
fun clearDate() = returnDate(day = 0, time = 0)
|
||||||
|
|
||||||
|
@OnClick(R.id.no_time)
|
||||||
|
fun clearTime() = returnDate(
|
||||||
|
day = when (selectedDay) {
|
||||||
|
DUE_TIME -> DUE_DATE
|
||||||
|
else -> selectedDay
|
||||||
|
},
|
||||||
|
time = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
@OnClick(R.id.due_date_button)
|
||||||
|
fun setToday() = returnDate(day = DUE_DATE)
|
||||||
|
|
||||||
|
@OnClick(R.id.day_before_due_button)
|
||||||
|
fun setTomorrow() = returnDate(day = DAY_BEFORE_DUE)
|
||||||
|
|
||||||
|
@OnClick(R.id.week_before_due_button)
|
||||||
|
fun setNextWeek() = returnDate(day = WEEK_BEFORE_DUE)
|
||||||
|
|
||||||
|
@OnClick(R.id.morning_button)
|
||||||
|
fun setMorning() = returnSelectedTime(morning)
|
||||||
|
|
||||||
|
@OnClick(R.id.afternoon_button)
|
||||||
|
fun setAfternoon() = returnSelectedTime(afternoon)
|
||||||
|
|
||||||
|
@OnClick(R.id.evening_button)
|
||||||
|
fun setEvening() = returnSelectedTime(evening)
|
||||||
|
|
||||||
|
@OnClick(R.id.night_button)
|
||||||
|
fun setNight() = returnSelectedTime(night)
|
||||||
|
|
||||||
|
@OnClick(R.id.due_time_button)
|
||||||
|
fun setDueTime() = returnDate(day = DUE_TIME, time = NO_TIME)
|
||||||
|
|
||||||
|
@OnClick(R.id.current_date_selection)
|
||||||
|
fun currentDate() = returnDate(day = customDate)
|
||||||
|
|
||||||
|
@OnClick(R.id.current_time_selection)
|
||||||
|
fun currentTime() = returnSelectedTime(customTime)
|
||||||
|
|
||||||
|
@OnClick(R.id.pick_time_button)
|
||||||
|
fun pickTime() {
|
||||||
|
val time = if (selectedTime < 0 || !Task.hasDueTime(today.withMillisOfDay(selectedTime).millis)) {
|
||||||
|
today.noon().millisOfDay
|
||||||
|
} else {
|
||||||
|
selectedTime
|
||||||
|
}
|
||||||
|
newTimePicker(this, REQUEST_TIME, today.withMillisOfDay(time).millis)
|
||||||
|
.show(parentFragmentManager, FRAG_TAG_TIME_PICKER)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun returnSelectedTime(millisOfDay: Int) {
|
||||||
|
val day = when {
|
||||||
|
selectedDay == DUE_TIME -> DUE_DATE
|
||||||
|
selectedDay != 0L -> selectedDay
|
||||||
|
today.withMillisOfDay(millisOfDay).isAfterNow -> today.millis
|
||||||
|
else -> today.plusDays(1).millis
|
||||||
|
}
|
||||||
|
returnDate(day = day, time = millisOfDay)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun returnDate(day: Long = selectedDay, time: Int = selectedTime) {
|
||||||
|
selectedDay = day
|
||||||
|
selectedTime = time
|
||||||
|
if (closeAutomatically()) {
|
||||||
|
sendSelected()
|
||||||
|
} else {
|
||||||
|
refreshButtons()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sendSelected() {
|
||||||
|
if (selectedDay != arguments?.getLong(EXTRA_DAY)
|
||||||
|
|| selectedTime != arguments?.getInt(EXTRA_TIME)) {
|
||||||
|
val intent = Intent().apply {
|
||||||
|
putExtra(EXTRA_DAY, selectedDay)
|
||||||
|
putExtra(EXTRA_TIME, selectedTime)
|
||||||
|
}
|
||||||
|
targetFragment?.onActivityResult(targetRequestCode, RESULT_OK, intent)
|
||||||
|
}
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
|
||||||
|
outState.putLong(EXTRA_DAY, selectedDay)
|
||||||
|
outState.putInt(EXTRA_TIME, selectedTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
if (requestCode == REQUEST_TIME) {
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
val timestamp = data!!.getLongExtra(MyTimePickerDialog.EXTRA_TIMESTAMP, today.millis)
|
||||||
|
returnSelectedTime(newDateTime(timestamp).millisOfDay + 1000)
|
||||||
|
} else {
|
||||||
|
refreshButtons()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,24 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/start_date"
|
||||||
|
style="@style/TaskEditTextPrimary"
|
||||||
|
android:hint="@string/no_start_date"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:baselineAligned="false"
|
android:textAlignment="viewStart" />
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="100"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/hideUntil"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@null"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<include layout="@layout/control_set_clear_button"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
|
||||||
|
android:background="@color/dialog_background">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="@dimen/keyline_first">
|
||||||
|
|
||||||
|
<include
|
||||||
|
layout="@layout/start_date_picker_shortcuts"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/shortcuts" />
|
||||||
|
|
||||||
|
<CalendarView
|
||||||
|
android:id="@+id/calendar_view"
|
||||||
|
android:layout_below="@id/shortcuts"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||||
|
android:id="@+id/date_group"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/half_keyline_first"
|
||||||
|
android:layout_marginBottom="@dimen/half_keyline_first"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@id/guideline"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintWidth_max="wrap"
|
||||||
|
app:layout_constraintWidth_percent="0.5"
|
||||||
|
app:singleSelection="true"
|
||||||
|
android:layout_marginStart="16dp">
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/current_date_selection"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
tools:text="Nov 24, 2021"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:icon="@drawable/ic_outline_today_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/due_date_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
android:text="@string/due_date"
|
||||||
|
app:icon="@drawable/ic_calendar_today_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/due_time_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
app:icon="@drawable/ic_outline_schedule_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
android:text="@string/due_time" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/day_before_due_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
android:text="@string/day_before_due"
|
||||||
|
app:icon="@drawable/ic_outline_wb_sunny_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/due_date_button" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/week_before_due_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
app:icon="@drawable/ic_date_range_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/day_before_due_button"
|
||||||
|
android:text="@string/week_before_due" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/no_date_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
android:text="@string/no_date"
|
||||||
|
app:icon="@drawable/ic_outline_not_interested_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/week_before_due_button" />
|
||||||
|
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Guideline
|
||||||
|
android:id="@+id/guideline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintGuide_percent="0.5" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||||
|
android:id="@+id/time_group"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/half_keyline_first"
|
||||||
|
android:layout_marginBottom="@dimen/half_keyline_first"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/guideline"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintWidth_max="wrap"
|
||||||
|
app:layout_constraintWidth_percent="0.5"
|
||||||
|
app:selectionRequired="true"
|
||||||
|
app:singleSelection="true"
|
||||||
|
android:layout_marginEnd="16dp">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/current_time_selection"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
app:icon="@drawable/ic_outline_schedule_24px"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:visibility="visible"
|
||||||
|
tools:text="08:15" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/morning_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
tools:text="9 AM"
|
||||||
|
app:icon="@drawable/ic_local_cafe_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/afternoon_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
android:layout_marginTop="1dp"
|
||||||
|
tools:text="1 PM"
|
||||||
|
app:icon="@drawable/ic_outline_wb_sunny_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/evening_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
tools:text="5 PM"
|
||||||
|
app:icon="@drawable/ic_weather_sunset"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/night_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
tools:text="8 PM"
|
||||||
|
app:icon="@drawable/ic_nights_stay_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/pick_time_button"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
android:text="@string/shortcut_pick_time"
|
||||||
|
app:icon="@drawable/ic_outline_schedule_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/no_time"
|
||||||
|
style="@style/DateTimeShortcuts"
|
||||||
|
android:text="@string/no_time"
|
||||||
|
app:icon="@drawable/ic_outline_not_interested_24px"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Loading…
Reference in New Issue