mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.2 KiB
Kotlin
214 lines
7.2 KiB
Kotlin
/*
|
|
* Copyright (c) 2012 Todoroo Inc
|
|
*
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
*/
|
|
package com.todoroo.astrid.timers
|
|
|
|
import android.app.Activity
|
|
import android.os.Bundle
|
|
import android.os.SystemClock
|
|
import android.text.format.DateFormat
|
|
import android.text.format.DateUtils
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.widget.Chronometer
|
|
import android.widget.Chronometer.OnChronometerTickListener
|
|
import android.widget.ImageView
|
|
import android.widget.TextView
|
|
import androidx.appcompat.app.AlertDialog
|
|
import butterknife.BindView
|
|
import butterknife.OnClick
|
|
import com.todoroo.andlib.utility.DateUtilities
|
|
import com.todoroo.astrid.data.Task
|
|
import com.todoroo.astrid.ui.TimeDurationControlSet
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
import org.tasks.R
|
|
import org.tasks.Strings.isNullOrEmpty
|
|
import org.tasks.dialogs.DialogBuilder
|
|
import org.tasks.themes.Theme
|
|
import org.tasks.ui.TaskEditControlFragment
|
|
import javax.inject.Inject
|
|
|
|
/**
|
|
* Control Set for managing repeats
|
|
*
|
|
* @author Tim Su <tim></tim>@todoroo.com>
|
|
*/
|
|
@AndroidEntryPoint
|
|
class TimerControlSet : TaskEditControlFragment() {
|
|
@Inject lateinit var activity: Activity
|
|
@Inject lateinit var dialogBuilder: DialogBuilder
|
|
@Inject lateinit var theme: Theme
|
|
|
|
@BindView(R.id.display_row_edit)
|
|
lateinit var displayEdit: TextView
|
|
|
|
@BindView(R.id.timer)
|
|
lateinit var chronometer: Chronometer
|
|
|
|
@BindView(R.id.timer_button)
|
|
lateinit var timerButton: ImageView
|
|
|
|
private lateinit var estimated: TimeDurationControlSet
|
|
private lateinit var elapsed: TimeDurationControlSet
|
|
private var timerStarted: Long = 0
|
|
private var dialog: AlertDialog? = null
|
|
private lateinit var dialogView: View
|
|
private lateinit var callback: TimerControlSetCallback
|
|
|
|
override fun onCreateView(
|
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
val view = super.onCreateView(inflater, container, savedInstanceState)
|
|
val elapsedSeconds: Int
|
|
val estimatedSeconds: Int
|
|
if (savedInstanceState == null) {
|
|
timerStarted = task.timerStart
|
|
elapsedSeconds = task.elapsedSeconds
|
|
estimatedSeconds = task.estimatedSeconds
|
|
} else {
|
|
timerStarted = savedInstanceState.getLong(EXTRA_STARTED)
|
|
elapsedSeconds = savedInstanceState.getInt(EXTRA_ELAPSED)
|
|
estimatedSeconds = savedInstanceState.getInt(EXTRA_ESTIMATED)
|
|
}
|
|
dialogView = inflater.inflate(R.layout.control_set_timers_dialog, null)
|
|
estimated = TimeDurationControlSet(activity, dialogView, R.id.estimatedDuration, theme)
|
|
elapsed = TimeDurationControlSet(activity, dialogView, R.id.elapsedDuration, theme)
|
|
estimated.setTimeDuration(estimatedSeconds)
|
|
elapsed.setTimeDuration(elapsedSeconds)
|
|
refresh()
|
|
return view
|
|
}
|
|
|
|
override fun onAttach(activity: Activity) {
|
|
super.onAttach(activity)
|
|
callback = activity as TimerControlSetCallback
|
|
}
|
|
|
|
override fun onSaveInstanceState(outState: Bundle) {
|
|
super.onSaveInstanceState(outState)
|
|
outState.putInt(EXTRA_ELAPSED, elapsed.timeDurationInSeconds)
|
|
outState.putInt(EXTRA_ESTIMATED, estimated.timeDurationInSeconds)
|
|
outState.putLong(EXTRA_STARTED, timerStarted)
|
|
}
|
|
|
|
override fun onRowClick() {
|
|
if (dialog == null) {
|
|
dialog = buildDialog()
|
|
}
|
|
dialog!!.show()
|
|
}
|
|
|
|
override val isClickable: Boolean
|
|
get() = true
|
|
|
|
private fun buildDialog(): AlertDialog {
|
|
return dialogBuilder
|
|
.newDialog()
|
|
.setView(dialogView)
|
|
.setPositiveButton(android.R.string.ok) { _, _ -> refreshDisplayView() }
|
|
.setOnCancelListener { refreshDisplayView() }
|
|
.create()
|
|
}
|
|
|
|
@OnClick(R.id.timer_container)
|
|
fun timerClicked() {
|
|
if (timerActive()) {
|
|
val task = callback.stopTimer()
|
|
elapsed.setTimeDuration(task.elapsedSeconds)
|
|
timerStarted = 0
|
|
chronometer.stop()
|
|
refreshDisplayView()
|
|
} else {
|
|
val task = callback.startTimer()
|
|
timerStarted = task.timerStart
|
|
chronometer.start()
|
|
}
|
|
updateChronometer()
|
|
}
|
|
|
|
override val layout: Int
|
|
get() = R.layout.control_set_timers
|
|
|
|
override val icon: Int
|
|
get() = R.drawable.ic_outline_timer_24px
|
|
|
|
override fun controlId() = TAG
|
|
|
|
override fun hasChanges(original: Task): Boolean {
|
|
return (elapsed.timeDurationInSeconds != original.elapsedSeconds
|
|
|| estimated.timeDurationInSeconds != original.estimatedSeconds)
|
|
}
|
|
|
|
override fun apply(task: Task) {
|
|
task.elapsedSeconds = elapsed.timeDurationInSeconds
|
|
task.estimatedSeconds = estimated.timeDurationInSeconds
|
|
}
|
|
|
|
private fun refresh() {
|
|
refreshDisplayView()
|
|
updateChronometer()
|
|
}
|
|
|
|
private fun refreshDisplayView() {
|
|
var est: String? = null
|
|
val estimatedSeconds = estimated.timeDurationInSeconds
|
|
if (estimatedSeconds > 0) {
|
|
est = getString(R.string.TEA_timer_est, DateUtils.formatElapsedTime(estimatedSeconds.toLong()))
|
|
}
|
|
var elap: String? = null
|
|
val elapsedSeconds = elapsed.timeDurationInSeconds
|
|
if (elapsedSeconds > 0) {
|
|
elap = getString(R.string.TEA_timer_elap, DateUtils.formatElapsedTime(elapsedSeconds.toLong()))
|
|
}
|
|
val toDisplay: String?
|
|
toDisplay = if (!isNullOrEmpty(est) && !isNullOrEmpty(elap)) {
|
|
"$est, $elap" // $NON-NLS-1$
|
|
} else if (!isNullOrEmpty(est)) {
|
|
est
|
|
} else if (!isNullOrEmpty(elap)) {
|
|
elap
|
|
} else {
|
|
null
|
|
}
|
|
displayEdit.text = toDisplay
|
|
}
|
|
|
|
private fun updateChronometer() {
|
|
timerButton.setImageResource(
|
|
if (timerActive()) R.drawable.ic_outline_pause_24px else R.drawable.ic_outline_play_arrow_24px)
|
|
var elapsed = elapsed.timeDurationInSeconds * 1000L
|
|
if (timerActive()) {
|
|
chronometer.visibility = View.VISIBLE
|
|
elapsed += DateUtilities.now() - timerStarted
|
|
chronometer.base = SystemClock.elapsedRealtime() - elapsed
|
|
if (elapsed > DateUtilities.ONE_DAY) {
|
|
chronometer.onChronometerTickListener = OnChronometerTickListener { cArg: Chronometer ->
|
|
val t = SystemClock.elapsedRealtime() - cArg.base
|
|
cArg.text = DateFormat.format("d'd' h:mm", t) // $NON-NLS-1$
|
|
}
|
|
}
|
|
chronometer.start()
|
|
} else {
|
|
chronometer.visibility = View.GONE
|
|
chronometer.stop()
|
|
}
|
|
}
|
|
|
|
private fun timerActive(): Boolean {
|
|
return timerStarted > 0
|
|
}
|
|
|
|
interface TimerControlSetCallback {
|
|
fun stopTimer(): Task
|
|
fun startTimer(): Task
|
|
}
|
|
|
|
companion object {
|
|
const val TAG = R.string.TEA_ctrl_timer_pref
|
|
private const val EXTRA_STARTED = "extra_started"
|
|
private const val EXTRA_ESTIMATED = "extra_estimated"
|
|
private const val EXTRA_ELAPSED = "extra_elapsed"
|
|
}
|
|
} |