diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt b/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt index 9447f4f8..b8fe52cf 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/fragments/TimerFragment.kt @@ -10,7 +10,6 @@ import android.media.AudioManager import android.os.Build import android.os.Bundle import android.os.CountDownTimer -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -26,10 +25,7 @@ import com.simplemobiletools.clock.extensions.* import com.simplemobiletools.clock.helpers.Config import com.simplemobiletools.clock.helpers.PICK_AUDIO_FILE_INTENT_ID import com.simplemobiletools.clock.helpers.TIMER_NOTIF_ID -import com.simplemobiletools.clock.workers.TIMER_WORKER_KEY -import com.simplemobiletools.clock.workers.cancelTimerWorker -import com.simplemobiletools.clock.workers.enqueueTimerWorker -import com.simplemobiletools.clock.workers.timerRequestId +import com.simplemobiletools.clock.workers.* import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.ALARM_SOUND_TYPE_ALARM @@ -38,24 +34,53 @@ import com.simplemobiletools.commons.models.AlarmSound import kotlinx.android.synthetic.main.fragment_timer.view.* import java.util.concurrent.TimeUnit + class TimerFragment : Fragment() { lateinit var view: ViewGroup private var timer: CountDownTimer? = null + private var isRunning = false override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - val config = requiredActivity.config view = (inflater.inflate(R.layout.fragment_timer, container, false) as ViewGroup).apply { + val config = requiredActivity.config + val textColor = config.textColor + + requiredActivity.updateTextColors(timer_fragment) + timer_play_pause.background = resources.getColoredDrawableWithColor(R.drawable.circle_background_filled, context!!.getAdjustedPrimaryColor()) + timer_reset.applyColorFilter(textColor) + + timer_initial_time.text = config.timerSeconds.getFormattedDuration() + timer_initial_time.colorLeftDrawable(textColor) + + timer_vibrate.isChecked = config.timerVibrate + timer_vibrate.colorLeftDrawable(textColor) + + timer_sound.text = config.timerSoundTitle + timer_sound.colorLeftDrawable(textColor) + timer_time.setOnClickListener { - startTimer(config) + if (isRunning) { + pauseTimer(config) + } else { + startTimer(config) + } } timer_play_pause.setOnClickListener { - startTimer(config) + if (isRunning) { + pauseTimer(config) + } else { + startTimer(config) + } } timer_reset.setOnClickListener { cancelTimerWorker() + requiredActivity.hideTimerNotification() + + config.timerTickStamp = 0L + config.timerStartStamp = 0L requiredActivity.toast(R.string.timer_stopped) } @@ -63,7 +88,6 @@ class TimerFragment : Fragment() { MyTimePickerDialogDialog(activity as SimpleActivity, config.timerSeconds) { seconds -> val timerSeconds = if (seconds <= 0) 10 else seconds config.timerSeconds = timerSeconds - config.timerTimeStamp = System.currentTimeMillis() + timerSeconds timer_initial_time.text = timerSeconds.getFormattedDuration() } } @@ -92,15 +116,20 @@ class TimerFragment : Fragment() { } WorkManager.getInstance(requiredActivity).getWorkInfosByTagLiveData(TIMER_WORKER_KEY).observe(requiredActivity, Observer { workInfo -> - workInfo.log("log") - val workerState = workInfo?.firstOrNull()?.state + isRunning = (workerState == WorkInfo.State.ENQUEUED) + + updateIcons(isRunning) + timer_reset.beVisibleIf(isRunning) + timer?.cancel() + when (workerState) { WorkInfo.State.ENQUEUED -> { - timer?.cancel() - timer = object : CountDownTimer(config.timerSeconds.toLong().times(1000), 1000) { + val duration = config.timerSeconds.toLong() * 1000 //MS + + timer = object : CountDownTimer(duration, 1000) { override fun onTick(millisUntilFinished: Long) { - timer_time.text = millisUntilFinished.div(1000).toInt().getFormattedDuration() + timer_time.text = TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished).toInt().getFormattedDuration() } override fun onFinish() {} @@ -111,34 +140,46 @@ class TimerFragment : Fragment() { timer_time.text = 0.getFormattedDuration() } } - - updateIcons(workerState == WorkInfo.State.ENQUEUED) - timer_reset.beVisibleIf(workerState == WorkInfo.State.ENQUEUED) }) + + cancelTimerWorker() } return view } private fun startTimer(config: Config) { - val selectedDuration = config.timerSeconds - val formattedTimestamp = config.timerTimeStamp.timestampFormat("HH:mm:ss") - enqueueTimerWorker(TimeUnit.SECONDS.toMillis(selectedDuration.toLong())) - showNotification("(${selectedDuration.getFormattedDuration()}) $formattedTimestamp") + val isTimerNoTick = config.timerTickStamp == 0L + + if (isTimerNoTick) { + config.timerStartStamp = System.currentTimeMillis() + + val selectedDuration = config.timerSeconds + val formattedTimestamp = config.timerStartStamp.timestampFormat("HH:mm:ss") + + enqueueTimerWorker(TimeUnit.SECONDS.toMillis(selectedDuration.toLong())) + showNotification("(${selectedDuration.getFormattedDuration()}) $formattedTimestamp") + } else { + val duration = config.timerSeconds.toLong() * 1000 //MS + val selectedDuration = (config.timerStartStamp + duration) - (config.timerTickStamp - config.timerStartStamp) + val formattedTimestamp = config.timerStartStamp.timestampFormat("HH:mm:ss") + + enqueueTimerWorker(TimeUnit.SECONDS.toMillis(selectedDuration.toLong())) + showNotification("(${selectedDuration.toInt().getFormattedDuration()}) $formattedTimestamp") + } } - override fun onResume() { - super.onResume() - setupViews() - } + private fun pauseTimer(config: Config) { + cancelTimerWorker() + requiredActivity.hideTimerNotification() - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState.apply {}) - } + config.timerTickStamp = System.currentTimeMillis() - override fun onViewStateRestored(savedInstanceState: Bundle?) { - super.onViewStateRestored(savedInstanceState) - savedInstanceState?.apply {} + val tick = config.timerTickStamp + val duration = config.timerSeconds.toLong() * 1000 //MS + val startedAt = config.timerStartStamp + val distance = duration - (tick - startedAt) + view.timer_time.text = distance.toInt().getFormattedDuration() } fun updateAlarmSound(alarmSound: AlarmSound) { @@ -147,30 +188,6 @@ class TimerFragment : Fragment() { view.timer_sound.text = alarmSound.title } -// private val isRunning -// get(): Boolean = -// WorkManager.getInstance(requiredActivity).getWorkInfosByTagLiveData(TIMER_WORKER_KEY).value?.firstOrNull()?.state == WorkInfo.State.ENQUEUED - - private fun setupViews() { - val config = requiredActivity.config - val textColor = config.textColor - - view.apply { - requiredActivity.updateTextColors(timer_fragment) - timer_play_pause.background = resources.getColoredDrawableWithColor(R.drawable.circle_background_filled, context!!.getAdjustedPrimaryColor()) - timer_reset.applyColorFilter(textColor) - - timer_initial_time.text = config.timerSeconds.getFormattedDuration() - timer_initial_time.colorLeftDrawable(textColor) - - timer_vibrate.isChecked = config.timerVibrate - timer_vibrate.colorLeftDrawable(textColor) - - timer_sound.text = config.timerSoundTitle - timer_sound.colorLeftDrawable(textColor) - } - } - private fun updateIcons(isRunning: Boolean) { val drawableId = if (isRunning) R.drawable.ic_pause_vector else R.drawable.ic_play_vector val iconColor = if (requiredActivity.getAdjustedPrimaryColor() == Color.WHITE) Color.BLACK else requiredActivity.config.textColor diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Config.kt index 06f9ab40..9f2f8ab1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Config.kt @@ -5,7 +5,6 @@ import com.simplemobiletools.commons.extensions.getDefaultAlarmTitle import com.simplemobiletools.commons.extensions.getDefaultAlarmUri import com.simplemobiletools.commons.helpers.ALARM_SOUND_TYPE_ALARM import com.simplemobiletools.commons.helpers.BaseConfig -import java.util.concurrent.TimeUnit class Config(context: Context) : BaseConfig(context) { companion object { @@ -28,9 +27,13 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getInt(TIMER_SECONDS, 300) set(lastTimerSeconds) = prefs.edit().putInt(TIMER_SECONDS, lastTimerSeconds).apply() - var timerTimeStamp: Long - get() = prefs.getLong(TIMER_TIMESTAMP, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(timerSeconds.toLong())) - set(timestamp) = prefs.edit().putLong(TIMER_TIMESTAMP, timestamp).apply() + var timerStartStamp: Long + get() = prefs.getLong(TIMER_START_TIMESTAMP, 0L) + set(timestamp) = prefs.edit().putLong(TIMER_START_TIMESTAMP, timestamp).apply() + + var timerTickStamp: Long + get() = prefs.getLong(TIMER_TICK_TIMESTAMP, 0L) + set(timestamp) = prefs.edit().putLong(TIMER_TICK_TIMESTAMP, timestamp).apply() var timerVibrate: Boolean get() = prefs.getBoolean(TIMER_VIBRATE, false) diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt index 613c4227..f383d54b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/helpers/Constants.kt @@ -8,7 +8,8 @@ const val SHOW_SECONDS = "show_seconds" const val SELECTED_TIME_ZONES = "selected_time_zones" const val EDITED_TIME_ZONE_TITLES = "edited_time_zone_titles" const val TIMER_SECONDS = "timer_seconds" -const val TIMER_TIMESTAMP = "timer_timetamp" +const val TIMER_START_TIMESTAMP = "timer_timetamp" +const val TIMER_TICK_TIMESTAMP = "timer_tick" const val TIMER_VIBRATE = "timer_vibrate" const val TIMER_SOUND_URI = "timer_sound_uri" const val TIMER_SOUND_TITLE = "timer_sound_title" diff --git a/app/src/main/kotlin/com/simplemobiletools/clock/workers/timerWorker.kt b/app/src/main/kotlin/com/simplemobiletools/clock/workers/timerWorker.kt index c3bd62fa..1bb655cd 100644 --- a/app/src/main/kotlin/com/simplemobiletools/clock/workers/timerWorker.kt +++ b/app/src/main/kotlin/com/simplemobiletools/clock/workers/timerWorker.kt @@ -11,34 +11,31 @@ private const val TIMER_REQUEST_ID = "TIMER_REQUEST_ID" const val TIMER_WORKER_KEY = "TIMER_WORKER_KEY" private fun Fragment.saveTimerRequestId(uuid: UUID) = - preferences.edit().putString(TIMER_REQUEST_ID, uuid.toString()).apply() + preferences.edit().putString(TIMER_REQUEST_ID, uuid.toString()).apply() -val Fragment.timerRequestId: UUID? get() = - preferences.getString(TIMER_REQUEST_ID, UUID.randomUUID().toString())?.let { UUID.fromString(it) } +val Fragment.timerRequestId: UUID? + get() = + preferences.getString(TIMER_REQUEST_ID, UUID.randomUUID().toString())?.let { UUID.fromString(it) } fun Fragment.cancelTimerWorker() = - WorkManager.getInstance(requiredActivity).cancelAllWorkByTag(TIMER_WORKER_KEY) + WorkManager.getInstance(requiredActivity).cancelAllWorkByTag(TIMER_WORKER_KEY) fun Fragment.enqueueTimerWorker(delay: Long) = - WorkManager.getInstance(requiredActivity).enqueueUniqueWork(TIMER_WORKER_KEY, ExistingWorkPolicy.REPLACE, timerRequest(delay)) + WorkManager.getInstance(requiredActivity).enqueueUniqueWork(TIMER_WORKER_KEY, ExistingWorkPolicy.REPLACE, timerRequest(delay)) -private fun Fragment.timerRequest(delay: Long) = - OneTimeWorkRequestBuilder().setInitialDelay(delay, TimeUnit.MILLISECONDS).addTag(TIMER_WORKER_KEY).build().also { +private fun Fragment.timerRequest(delay: Long): OneTimeWorkRequest = + OneTimeWorkRequestBuilder().setInitialDelay(delay, TimeUnit.MILLISECONDS).addTag(TIMER_WORKER_KEY).build().also { saveTimerRequestId(it.id) - } +} class TimerWorker(val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { override fun doWork(): Result = - try { - context.showTimerNotification(false) - Result.success() - } catch (exception: Exception) { - Result.failure() - } - - override fun onStopped() { - super.onStopped() - context.hideTimerNotification() - } + try { + context.showTimerNotification(false) + context.config.timerTickStamp = 0L + context.config.timerStartStamp = 0L + Result.success() + } catch (exception: Exception) { + Result.failure() + } } -