mirror of
https://github.com/SimpleMobileTools/Simple-Clock.git
synced 2025-02-22 06:37:52 +01:00
handle multiple timer states
- feat: separate timer actions from states by adding a new class TimerEvent to hold actions Reset, Start, Pause, Finish, Refesh that could be performed on a timer. - feat: handle multiple countdown timers in the App file by creating a map of the timer id to the countdown timer. - fix: use gson instance from TypeAdapter in Room's Converters class - ref: remove scroll view parent from each timer item, a fix for the keyboard obscuring a label will be implemented in a future commit
This commit is contained in:
parent
921ca92885
commit
8474e6a800
@ -5,16 +5,18 @@ import android.app.NotificationManager
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
|
import android.util.Log
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleObserver
|
import androidx.lifecycle.LifecycleObserver
|
||||||
import androidx.lifecycle.OnLifecycleEvent
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import com.facebook.stetho.Stetho
|
import com.facebook.stetho.Stetho
|
||||||
import com.simplemobiletools.clock.extensions.config
|
|
||||||
import com.simplemobiletools.clock.extensions.getOpenTimerTabIntent
|
import com.simplemobiletools.clock.extensions.getOpenTimerTabIntent
|
||||||
import com.simplemobiletools.clock.extensions.getTimerNotification
|
import com.simplemobiletools.clock.extensions.getTimerNotification
|
||||||
|
import com.simplemobiletools.clock.extensions.timerHelper
|
||||||
import com.simplemobiletools.clock.helpers.TIMER_NOTIF_ID
|
import com.simplemobiletools.clock.helpers.TIMER_NOTIF_ID
|
||||||
|
import com.simplemobiletools.clock.models.TimerEvent
|
||||||
import com.simplemobiletools.clock.models.TimerState
|
import com.simplemobiletools.clock.models.TimerState
|
||||||
import com.simplemobiletools.clock.services.TimerStopService
|
import com.simplemobiletools.clock.services.TimerStopService
|
||||||
import com.simplemobiletools.clock.services.startTimerService
|
import com.simplemobiletools.clock.services.startTimerService
|
||||||
@ -25,8 +27,7 @@ import org.greenrobot.eventbus.ThreadMode
|
|||||||
|
|
||||||
class App : Application(), LifecycleObserver {
|
class App : Application(), LifecycleObserver {
|
||||||
|
|
||||||
private var timer: CountDownTimer? = null
|
private var timers = mutableMapOf<Long, CountDownTimer>()
|
||||||
private var lastTick = 0L
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
@ -48,63 +49,83 @@ class App : Application(), LifecycleObserver {
|
|||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
||||||
private fun onAppBackgrounded() {
|
private fun onAppBackgrounded() {
|
||||||
if (config.timerState is TimerState.Running) {
|
timerHelper.getTimers { timers ->
|
||||||
startTimerService(this)
|
if (timers.any { it.state is TimerState.Running }) {
|
||||||
|
startTimerService(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnLifecycleEvent(Lifecycle.Event.ON_START)
|
@OnLifecycleEvent(Lifecycle.Event.ON_START)
|
||||||
private fun onAppForegrounded() {
|
private fun onAppForegrounded() {
|
||||||
EventBus.getDefault().post(TimerStopService)
|
EventBus.getDefault().post(TimerStopService)
|
||||||
|
timerHelper.getTimers { timers ->
|
||||||
|
val runningTimers = timers.filter { it.state is TimerState.Running }
|
||||||
|
runningTimers.forEach { timer ->
|
||||||
|
EventBus.getDefault().post(TimerEvent.Start(timer.id!!, (timer.state as TimerState.Running).tick))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onMessageEvent(state: TimerState.Idle) {
|
fun onMessageEvent(event: TimerEvent.Reset) {
|
||||||
config.timerState = state
|
Log.w(TAG, "onMessageEvent: $event")
|
||||||
timer?.cancel()
|
updateTimerState(event.timerId, TimerState.Idle)
|
||||||
|
timers[event.timerId]?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onMessageEvent(state: TimerState.Start) {
|
fun onMessageEvent(event: TimerEvent.Start) {
|
||||||
timer = object : CountDownTimer(state.duration, 1000) {
|
Log.w(TAG, "onMessageEvent: $event")
|
||||||
|
val countDownTimer = object : CountDownTimer(event.duration, 1000) {
|
||||||
override fun onTick(tick: Long) {
|
override fun onTick(tick: Long) {
|
||||||
lastTick = tick
|
Log.d(TAG, "onMessageEvent--> $tick")
|
||||||
|
updateTimerState(event.timerId, TimerState.Running(event.duration, tick))
|
||||||
val newState = TimerState.Running(state.duration, tick)
|
|
||||||
EventBus.getDefault().post(newState)
|
|
||||||
config.timerState = newState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFinish() {
|
override fun onFinish() {
|
||||||
EventBus.getDefault().post(TimerState.Finish(state.duration))
|
EventBus.getDefault().post(TimerEvent.Finish(event.timerId, event.duration))
|
||||||
EventBus.getDefault().post(TimerStopService)
|
EventBus.getDefault().post(TimerStopService)
|
||||||
}
|
}
|
||||||
}.start()
|
}.start()
|
||||||
|
timers[event.timerId] = countDownTimer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onMessageEvent(event: TimerState.Finish) {
|
fun onMessageEvent(event: TimerEvent.Finish) {
|
||||||
val pendingIntent = getOpenTimerTabIntent()
|
Log.w(TAG, "onMessageEvent: $event")
|
||||||
val notification = getTimerNotification(pendingIntent, false)
|
timerHelper.getTimer(event.timerId) { timer ->
|
||||||
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val pendingIntent = getOpenTimerTabIntent(event.timerId)
|
||||||
notificationManager.notify(TIMER_NOTIF_ID, notification)
|
val notification = getTimerNotification(timer, pendingIntent, false)
|
||||||
|
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
EventBus.getDefault().post(TimerState.Finished)
|
notificationManager.notify(TIMER_NOTIF_ID, notification)
|
||||||
|
updateTimerState(event.timerId, TimerState.Finished)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onMessageEvent(state: TimerState.Finished) {
|
fun onMessageEvent(event: TimerEvent.Pause) {
|
||||||
config.timerState = state
|
Log.w(TAG, "onMessageEvent: $event")
|
||||||
|
timerHelper.getTimer(event.timerId) { timer ->
|
||||||
|
updateTimerState(event.timerId, TimerState.Paused(event.duration, (timer.state as TimerState.Running).tick))
|
||||||
|
timers[event.timerId]?.cancel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
private fun updateTimerState(timerId: Long, state: TimerState) {
|
||||||
fun onMessageEvent(event: TimerState.Pause) {
|
timerHelper.getTimer(timerId) { timer ->
|
||||||
EventBus.getDefault().post(TimerState.Paused(event.duration, lastTick))
|
val newTimer = timer.copy(state = state)
|
||||||
|
Log.w(TAG, "updateTimerState: $newTimer")
|
||||||
|
timerHelper.insertOrUpdateTimer(newTimer) {
|
||||||
|
EventBus.getDefault().post(TimerEvent.Refresh(timerId))
|
||||||
|
timerHelper.getTimer(timerId) {
|
||||||
|
Log.e(TAG, "updated timer $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
companion object {
|
||||||
fun onMessageEvent(state: TimerState.Paused) {
|
private const val TAG = "App"
|
||||||
config.timerState = state
|
|
||||||
timer?.cancel()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.simplemobiletools.clock.adapters
|
|||||||
|
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.RingtoneManager
|
import android.media.RingtoneManager
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -11,7 +12,10 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.simplemobiletools.clock.R
|
import com.simplemobiletools.clock.R
|
||||||
import com.simplemobiletools.clock.activities.SimpleActivity
|
import com.simplemobiletools.clock.activities.SimpleActivity
|
||||||
import com.simplemobiletools.clock.dialogs.MyTimePickerDialogDialog
|
import com.simplemobiletools.clock.dialogs.MyTimePickerDialogDialog
|
||||||
import com.simplemobiletools.clock.extensions.*
|
import com.simplemobiletools.clock.extensions.checkAlarmsWithDeletedSoundUri
|
||||||
|
import com.simplemobiletools.clock.extensions.colorLeftDrawable
|
||||||
|
import com.simplemobiletools.clock.extensions.config
|
||||||
|
import com.simplemobiletools.clock.extensions.timerHelper
|
||||||
import com.simplemobiletools.clock.helpers.PICK_AUDIO_FILE_INTENT_ID
|
import com.simplemobiletools.clock.helpers.PICK_AUDIO_FILE_INTENT_ID
|
||||||
import com.simplemobiletools.clock.models.Timer
|
import com.simplemobiletools.clock.models.Timer
|
||||||
import com.simplemobiletools.clock.models.TimerState
|
import com.simplemobiletools.clock.models.TimerState
|
||||||
@ -20,16 +24,13 @@ import com.simplemobiletools.commons.extensions.getDefaultAlarmSound
|
|||||||
import com.simplemobiletools.commons.extensions.getFormattedDuration
|
import com.simplemobiletools.commons.extensions.getFormattedDuration
|
||||||
import com.simplemobiletools.commons.extensions.onTextChangeListener
|
import com.simplemobiletools.commons.extensions.onTextChangeListener
|
||||||
import com.simplemobiletools.commons.models.AlarmSound
|
import com.simplemobiletools.commons.models.AlarmSound
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import kotlinx.android.synthetic.main.item_timer.view.*
|
import kotlinx.android.synthetic.main.item_timer.view.*
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
|
|
||||||
class TimerAdapter(
|
class TimerAdapter(
|
||||||
private val activity: SimpleActivity,
|
private val activity: SimpleActivity,
|
||||||
private val onRefresh: () -> Unit,
|
private val onRefresh: () -> Unit,
|
||||||
|
) : ListAdapter<Timer, TimerAdapter.TimerViewHolder>(diffUtil) {
|
||||||
) : ListAdapter<Timer, TimerAdapter.TimerViewHolder>(diffUtil) {
|
|
||||||
|
|
||||||
private val config = activity.config
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimerViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimerViewHolder {
|
||||||
return TimerViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_timer, parent, false))
|
return TimerViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_timer, parent, false))
|
||||||
@ -45,28 +46,32 @@ class TimerAdapter(
|
|||||||
|
|
||||||
inner class TimerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class TimerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemView.timer_label.onTextChangeListener { text ->
|
||||||
|
Log.w(TAG, "timer_label")
|
||||||
|
updateTimer(getItemAt(adapterPosition).copy(label = text), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
itemView.post {
|
||||||
|
val textColor = activity.config.textColor
|
||||||
|
itemView.timer_initial_time.colorLeftDrawable(textColor)
|
||||||
|
itemView.timer_vibrate.colorLeftDrawable(textColor)
|
||||||
|
itemView.timer_sound.colorLeftDrawable(textColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun bind(timer: Timer) {
|
fun bind(timer: Timer) {
|
||||||
itemView.apply {
|
itemView.apply {
|
||||||
timer_time.text = timer.seconds.getFormattedDuration()
|
//only update when different to prevent flickering and unnecessary updates
|
||||||
timer_label.setText(timer.label)
|
if (timer_label.text.toString() != timer.label) {
|
||||||
|
timer_label.setText(timer.label)
|
||||||
timer_time.text = timer.seconds.getFormattedDuration()
|
}
|
||||||
timer_label.setText(timer.label)
|
|
||||||
|
|
||||||
val textColor = activity.config.textColor
|
|
||||||
|
|
||||||
timer_initial_time.text = timer.seconds.getFormattedDuration()
|
timer_initial_time.text = timer.seconds.getFormattedDuration()
|
||||||
timer_initial_time.colorLeftDrawable(textColor)
|
|
||||||
|
|
||||||
timer_vibrate.isChecked = timer.vibrate
|
timer_vibrate.isChecked = timer.vibrate
|
||||||
timer_vibrate.colorLeftDrawable(textColor)
|
|
||||||
|
|
||||||
timer_sound.text = timer.soundTitle
|
timer_sound.text = timer.soundTitle
|
||||||
timer_sound.colorLeftDrawable(textColor)
|
|
||||||
|
|
||||||
timer_time.setOnClickListener {
|
|
||||||
stopTimer(timer)
|
|
||||||
}
|
|
||||||
|
|
||||||
timer_time.setOnClickListener {
|
timer_time.setOnClickListener {
|
||||||
changeDuration(timer)
|
changeDuration(timer)
|
||||||
@ -77,12 +82,13 @@ class TimerAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
timer_vibrate_holder.setOnClickListener {
|
timer_vibrate_holder.setOnClickListener {
|
||||||
|
Log.w(TAG, "toggle")
|
||||||
timer_vibrate.toggle()
|
timer_vibrate.toggle()
|
||||||
updateTimer(timer.copy(vibrate = timer_vibrate.isChecked), false)
|
updateTimer(timer.copy(vibrate = timer_vibrate.isChecked), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
timer_sound.setOnClickListener {
|
timer_sound.setOnClickListener {
|
||||||
SelectAlarmSoundDialog(activity, config.timerSoundUri, AudioManager.STREAM_ALARM, PICK_AUDIO_FILE_INTENT_ID,
|
SelectAlarmSoundDialog(activity, timer.soundUri, AudioManager.STREAM_ALARM, PICK_AUDIO_FILE_INTENT_ID,
|
||||||
RingtoneManager.TYPE_ALARM, true,
|
RingtoneManager.TYPE_ALARM, true,
|
||||||
onAlarmPicked = { sound ->
|
onAlarmPicked = { sound ->
|
||||||
if (sound != null) {
|
if (sound != null) {
|
||||||
@ -99,39 +105,52 @@ class TimerAdapter(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
timer_label.onTextChangeListener { text ->
|
|
||||||
updateTimer(timer.copy(label = text), false)
|
when (timer.state) {
|
||||||
|
is TimerState.Finished -> {
|
||||||
|
timer_time.text = 0.getFormattedDuration()
|
||||||
|
}
|
||||||
|
|
||||||
|
is TimerState.Idle -> {
|
||||||
|
timer_time.text = timer.seconds.getFormattedDuration()
|
||||||
|
}
|
||||||
|
|
||||||
|
is TimerState.Paused -> {
|
||||||
|
timer_time.text = timer.state.tick.div(1000F).roundToInt().getFormattedDuration()
|
||||||
|
}
|
||||||
|
|
||||||
|
is TimerState.Running -> {
|
||||||
|
timer_time.text = timer.state.tick.div(1000F).roundToInt().getFormattedDuration()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopTimer(timer: Timer) {
|
|
||||||
EventBus.getDefault().post(TimerState.Idle)
|
|
||||||
activity.hideTimerNotification()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun changeDuration(timer: Timer) {
|
private fun changeDuration(timer: Timer) {
|
||||||
MyTimePickerDialogDialog(activity, timer.seconds) { seconds ->
|
MyTimePickerDialogDialog(activity, timer.seconds) { seconds ->
|
||||||
val timerSeconds = if (seconds <= 0) 10 else seconds
|
val timerSeconds = if (seconds <= 0) 10 else seconds
|
||||||
|
Log.w(TAG, "changeDuration")
|
||||||
updateTimer(timer.copy(seconds = timerSeconds))
|
updateTimer(timer.copy(seconds = timerSeconds))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateAlarmSound(timer: Timer, alarmSound: AlarmSound) {
|
fun updateAlarmSound(timer: Timer, alarmSound: AlarmSound) {
|
||||||
|
Log.w(TAG, "updateAlarmSound: $timer")
|
||||||
updateTimer(timer.copy(soundTitle = alarmSound.title, soundUri = alarmSound.uri))
|
updateTimer(timer.copy(soundTitle = alarmSound.title, soundUri = alarmSound.uri))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateTimer(timer: Timer, refresh: Boolean = true) {
|
private fun updateTimer(timer: Timer, refresh: Boolean = true) {
|
||||||
|
Log.w(TAG, "updateTimer: $timer")
|
||||||
activity.timerHelper.insertOrUpdateTimer(timer)
|
activity.timerHelper.insertOrUpdateTimer(timer)
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
onRefresh.invoke()
|
onRefresh.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val diffUtil = object : DiffUtil.ItemCallback<Timer>() {
|
private const val TAG = "TimerAdapter"
|
||||||
|
private val diffUtil = object : DiffUtil.ItemCallback<Timer>() {
|
||||||
override fun areItemsTheSame(oldItem: Timer, newItem: Timer): Boolean {
|
override fun areItemsTheSame(oldItem: Timer, newItem: Timer): Boolean {
|
||||||
return oldItem.id == newItem.id
|
return oldItem.id == newItem.id
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.simplemobiletools.clock.fragments.TimerFragment
|
|||||||
import com.simplemobiletools.clock.helpers.TABS_COUNT
|
import com.simplemobiletools.clock.helpers.TABS_COUNT
|
||||||
import com.simplemobiletools.clock.helpers.TAB_ALARM
|
import com.simplemobiletools.clock.helpers.TAB_ALARM
|
||||||
import com.simplemobiletools.clock.helpers.TAB_CLOCK
|
import com.simplemobiletools.clock.helpers.TAB_CLOCK
|
||||||
|
import com.simplemobiletools.clock.helpers.TAB_TIMER
|
||||||
import com.simplemobiletools.commons.models.AlarmSound
|
import com.simplemobiletools.commons.models.AlarmSound
|
||||||
|
|
||||||
class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
|
class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
|
||||||
@ -50,6 +51,6 @@ class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateTimerTabAlarmSound(alarmSound: AlarmSound) {
|
fun updateTimerTabAlarmSound(alarmSound: AlarmSound) {
|
||||||
// (fragments[TAB_TIMER] as? TimerFragment)?.updateAlarmSound(alarmSound)
|
(fragments[TAB_TIMER] as? TimerFragment)?.updateAlarmSound(alarmSound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import com.simplemobiletools.clock.helpers.*
|
|||||||
import com.simplemobiletools.clock.interfaces.TimerDao
|
import com.simplemobiletools.clock.interfaces.TimerDao
|
||||||
import com.simplemobiletools.clock.models.Alarm
|
import com.simplemobiletools.clock.models.Alarm
|
||||||
import com.simplemobiletools.clock.models.MyTimeZone
|
import com.simplemobiletools.clock.models.MyTimeZone
|
||||||
|
import com.simplemobiletools.clock.models.Timer
|
||||||
import com.simplemobiletools.clock.receivers.AlarmReceiver
|
import com.simplemobiletools.clock.receivers.AlarmReceiver
|
||||||
import com.simplemobiletools.clock.receivers.DateTimeWidgetUpdateReceiver
|
import com.simplemobiletools.clock.receivers.DateTimeWidgetUpdateReceiver
|
||||||
import com.simplemobiletools.clock.receivers.HideAlarmReceiver
|
import com.simplemobiletools.clock.receivers.HideAlarmReceiver
|
||||||
@ -139,9 +140,10 @@ fun Context.getOpenAlarmTabIntent(): PendingIntent {
|
|||||||
return PendingIntent.getActivity(this, OPEN_ALARMS_TAB_INTENT_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getActivity(this, OPEN_ALARMS_TAB_INTENT_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.getOpenTimerTabIntent(): PendingIntent {
|
fun Context.getOpenTimerTabIntent(timerId: Long): PendingIntent {
|
||||||
val intent = getLaunchIntent() ?: Intent(this, SplashActivity::class.java)
|
val intent = getLaunchIntent() ?: Intent(this, SplashActivity::class.java)
|
||||||
intent.putExtra(OPEN_TAB, TAB_TIMER)
|
intent.putExtra(OPEN_TAB, TAB_TIMER)
|
||||||
|
intent.putExtra(TIMER_ID, timerId)
|
||||||
return PendingIntent.getActivity(this, TIMER_NOTIF_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getActivity(this, TIMER_NOTIF_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,8 +262,8 @@ fun Context.showAlarmNotification(alarm: Alarm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
fun Context.getTimerNotification(pendingIntent: PendingIntent, addDeleteIntent: Boolean): Notification {
|
fun Context.getTimerNotification(timer: Timer, pendingIntent: PendingIntent, addDeleteIntent: Boolean): Notification {
|
||||||
var soundUri = config.timerSoundUri
|
var soundUri = timer.soundUri
|
||||||
if (soundUri == SILENT) {
|
if (soundUri == SILENT) {
|
||||||
soundUri = ""
|
soundUri = ""
|
||||||
} else {
|
} else {
|
||||||
@ -292,7 +294,7 @@ fun Context.getTimerNotification(pendingIntent: PendingIntent, addDeleteIntent:
|
|||||||
lightColor = getAdjustedPrimaryColor()
|
lightColor = getAdjustedPrimaryColor()
|
||||||
setSound(Uri.parse(soundUri), audioAttributes)
|
setSound(Uri.parse(soundUri), audioAttributes)
|
||||||
|
|
||||||
if (!config.timerVibrate) {
|
if (!timer.vibrate) {
|
||||||
vibrationPattern = longArrayOf(0L)
|
vibrationPattern = longArrayOf(0L)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,7 +323,7 @@ fun Context.getTimerNotification(pendingIntent: PendingIntent, addDeleteIntent:
|
|||||||
|
|
||||||
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
|
|
||||||
if (config.timerVibrate) {
|
if (timer.vibrate) {
|
||||||
val vibrateArray = LongArray(2) { 500 }
|
val vibrateArray = LongArray(2) { 500 }
|
||||||
builder.setVibrate(vibrateArray)
|
builder.setVibrate(vibrateArray)
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,8 @@ import com.simplemobiletools.clock.models.TimerState
|
|||||||
|
|
||||||
val timerStates = valueOf<TimerState>()
|
val timerStates = valueOf<TimerState>()
|
||||||
.registerSubtype(TimerState.Idle::class.java)
|
.registerSubtype(TimerState.Idle::class.java)
|
||||||
.registerSubtype(TimerState.Start::class.java)
|
|
||||||
.registerSubtype(TimerState.Running::class.java)
|
.registerSubtype(TimerState.Running::class.java)
|
||||||
.registerSubtype(TimerState.Pause::class.java)
|
|
||||||
.registerSubtype(TimerState.Paused::class.java)
|
.registerSubtype(TimerState.Paused::class.java)
|
||||||
.registerSubtype(TimerState.Finish::class.java)
|
|
||||||
.registerSubtype(TimerState.Finished::class.java)
|
.registerSubtype(TimerState.Finished::class.java)
|
||||||
|
|
||||||
inline fun <reified T : Any> valueOf(): RuntimeTypeAdapterFactory<T> = RuntimeTypeAdapterFactory.of(T::class.java)
|
inline fun <reified T : Any> valueOf(): RuntimeTypeAdapterFactory<T> = RuntimeTypeAdapterFactory.of(T::class.java)
|
||||||
|
@ -2,6 +2,7 @@ package com.simplemobiletools.clock.fragments
|
|||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -10,13 +11,16 @@ import androidx.viewpager2.widget.ViewPager2
|
|||||||
import com.simplemobiletools.clock.R
|
import com.simplemobiletools.clock.R
|
||||||
import com.simplemobiletools.clock.activities.SimpleActivity
|
import com.simplemobiletools.clock.activities.SimpleActivity
|
||||||
import com.simplemobiletools.clock.adapters.TimerAdapter
|
import com.simplemobiletools.clock.adapters.TimerAdapter
|
||||||
import com.simplemobiletools.clock.dialogs.MyTimePickerDialogDialog
|
|
||||||
import com.simplemobiletools.clock.extensions.config
|
import com.simplemobiletools.clock.extensions.config
|
||||||
import com.simplemobiletools.clock.extensions.hideTimerNotification
|
import com.simplemobiletools.clock.extensions.hideTimerNotification
|
||||||
|
import com.simplemobiletools.clock.extensions.secondsToMillis
|
||||||
import com.simplemobiletools.clock.extensions.timerHelper
|
import com.simplemobiletools.clock.extensions.timerHelper
|
||||||
import com.simplemobiletools.clock.models.Timer
|
import com.simplemobiletools.clock.models.Timer
|
||||||
|
import com.simplemobiletools.clock.models.TimerEvent
|
||||||
import com.simplemobiletools.clock.models.TimerState
|
import com.simplemobiletools.clock.models.TimerState
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
|
import com.simplemobiletools.commons.models.AlarmSound
|
||||||
|
import kotlinx.android.synthetic.main.fragment_timer.timer_view_pager
|
||||||
import kotlinx.android.synthetic.main.fragment_timer.view.*
|
import kotlinx.android.synthetic.main.fragment_timer.view.*
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
@ -24,7 +28,7 @@ import org.greenrobot.eventbus.ThreadMode
|
|||||||
|
|
||||||
class TimerFragment : Fragment() {
|
class TimerFragment : Fragment() {
|
||||||
|
|
||||||
lateinit var view: ViewGroup
|
private lateinit var view: ViewGroup
|
||||||
private lateinit var timerAdapter: TimerAdapter
|
private lateinit var timerAdapter: TimerAdapter
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -42,7 +46,10 @@ class TimerFragment : Fragment() {
|
|||||||
timerAdapter = TimerAdapter(requireActivity() as SimpleActivity) {
|
timerAdapter = TimerAdapter(requireActivity() as SimpleActivity) {
|
||||||
refreshTimers()
|
refreshTimers()
|
||||||
}
|
}
|
||||||
|
|
||||||
timer_view_pager.adapter = timerAdapter
|
timer_view_pager.adapter = timerAdapter
|
||||||
|
//set empty page transformer to disable item animations
|
||||||
|
timer_view_pager.setPageTransformer { _, _ -> }
|
||||||
timer_view_pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
timer_view_pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
updateViews(position)
|
updateViews(position)
|
||||||
@ -64,16 +71,13 @@ class TimerFragment : Fragment() {
|
|||||||
timer_play_pause.applyColorFilter(if (activity?.getAdjustedPrimaryColor() == Color.WHITE) Color.BLACK else Color.WHITE)
|
timer_play_pause.applyColorFilter(if (activity?.getAdjustedPrimaryColor() == Color.WHITE) Color.BLACK else Color.WHITE)
|
||||||
timer_reset.applyColorFilter(textColor)
|
timer_reset.applyColorFilter(textColor)
|
||||||
|
|
||||||
|
|
||||||
timer_play_pause.setOnClickListener {
|
timer_play_pause.setOnClickListener {
|
||||||
val timer = timerAdapter.getItemAt(timer_view_pager.currentItem)
|
val timer = timerAdapter.getItemAt(timer_view_pager.currentItem)
|
||||||
when (val state = timer.state) {
|
when (val state = timer.state) {
|
||||||
// is TimerState.Idle -> EventBus.getDefault().post(TimerState.Start(timer.seconds.secondsToMillis))
|
is TimerState.Idle -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, timer.seconds.secondsToMillis))
|
||||||
// is TimerState.Paused -> EventBus.getDefault().post(TimerState.Start(state.tick))
|
is TimerState.Paused -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, state.tick))
|
||||||
// is TimerState.Running -> EventBus.getDefault().post(TimerState.Pause(state.tick))
|
is TimerState.Running -> EventBus.getDefault().post(TimerEvent.Pause(timer.id!!, state.tick))
|
||||||
// is TimerState.Finished -> EventBus.getDefault().post(TimerState.Start(timer.seconds.secondsToMillis))
|
is TimerState.Finished -> EventBus.getDefault().post(TimerEvent.Start(timer.id!!, timer.seconds.secondsToMillis))
|
||||||
else -> {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,67 +99,39 @@ class TimerFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateViews(position: Int) {
|
private fun updateViews(position: Int) {
|
||||||
val timer = timerAdapter.getItemAt(position)
|
activity?.runOnUiThread {
|
||||||
//check if timer is running to update view
|
val timer = timerAdapter.getItemAt(position)
|
||||||
|
updateViewStates(timer.state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshTimers(scrollToLast: Boolean = false) {
|
private fun refreshTimers(scrollToLast: Boolean = false) {
|
||||||
activity?.timerHelper?.getTimers { timers ->
|
activity?.timerHelper?.getTimers { timers ->
|
||||||
timerAdapter.submitList(timers)
|
Log.d(TAG, "refreshTimers: $timers")
|
||||||
activity?.runOnUiThread {
|
timerAdapter.submitList(timers) {
|
||||||
view.timer_delete.beVisibleIf(timers.size > 1)
|
|
||||||
if (scrollToLast) {
|
if (scrollToLast) {
|
||||||
view.timer_view_pager.currentItem = timers.lastIndex
|
view.timer_view_pager.currentItem = timers.lastIndex
|
||||||
}
|
}
|
||||||
|
updateViews(timer_view_pager.currentItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopTimer(timer: Timer) {
|
private fun stopTimer(timer: Timer) {
|
||||||
EventBus.getDefault().post(TimerState.Idle)
|
EventBus.getDefault().post(TimerEvent.Reset(timer.id!!, timer.seconds.secondsToMillis))
|
||||||
activity?.hideTimerNotification()
|
activity?.hideTimerNotification()
|
||||||
// view.timer_time.text = activity?.config?.timerSeconds?.getFormattedDuration()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun changeDuration() {
|
|
||||||
MyTimePickerDialogDialog(activity as SimpleActivity, requireContext().config.timerSeconds) { seconds ->
|
|
||||||
val timerSeconds = if (seconds <= 0) 10 else seconds
|
|
||||||
activity?.config?.timerSeconds = timerSeconds
|
|
||||||
val duration = timerSeconds.getFormattedDuration()
|
|
||||||
// view.timer_initial_time.text = duration
|
|
||||||
|
|
||||||
// if (view.timer_reset.isGone()) {
|
|
||||||
// stopTimer()
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onMessageEvent(state: TimerState.Idle) {
|
fun onMessageEvent(event: TimerEvent.Refresh) {
|
||||||
// view.timer_time.text = requiredActivity.config.timerSeconds.getFormattedDuration()
|
Log.d(TAG, "onMessageEvent: $event")
|
||||||
updateViewStates(state)
|
refreshTimers()
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
fun onMessageEvent(state: TimerState.Running) {
|
|
||||||
// view.timer_time.text = state.tick.div(1000F).roundToInt().getFormattedDuration()
|
|
||||||
updateViewStates(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
fun onMessageEvent(state: TimerState.Paused) {
|
|
||||||
updateViewStates(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
fun onMessageEvent(state: TimerState.Finished) {
|
|
||||||
// view.timer_time.text = 0.getFormattedDuration()
|
|
||||||
updateViewStates(state)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateViewStates(state: TimerState) {
|
private fun updateViewStates(state: TimerState) {
|
||||||
val resetPossible = state is TimerState.Running || state is TimerState.Paused || state is TimerState.Finished
|
val resetPossible = state is TimerState.Running || state is TimerState.Paused || state is TimerState.Finished
|
||||||
view.timer_reset.beVisibleIf(resetPossible)
|
view.timer_reset.beVisibleIf(resetPossible)
|
||||||
|
view.timer_delete.beVisibleIf(!resetPossible && timerAdapter.itemCount > 1)
|
||||||
|
|
||||||
val drawableId = if (state is TimerState.Running) {
|
val drawableId = if (state is TimerState.Running) {
|
||||||
R.drawable.ic_pause_vector
|
R.drawable.ic_pause_vector
|
||||||
@ -171,10 +147,15 @@ class TimerFragment : Fragment() {
|
|||||||
|
|
||||||
view.timer_play_pause.setImageDrawable(resources.getColoredDrawableWithColor(drawableId, iconColor))
|
view.timer_play_pause.setImageDrawable(resources.getColoredDrawableWithColor(drawableId, iconColor))
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// fun updateAlarmSound(alarmSound: AlarmSound) {
|
fun updateAlarmSound(alarmSound: AlarmSound) {
|
||||||
// activity?.config?.timerSoundTitle = alarmSound.title
|
val timer = timerAdapter.getItemAt(timer_view_pager.currentItem)
|
||||||
// activity?.config?.timerSoundUri = alarmSound.uri
|
activity?.timerHelper?.insertOrUpdateTimer(timer.copy(soundTitle = alarmSound.title, soundUri = alarmSound.uri)) {
|
||||||
// view.timer_sound.text = alarmSound.title
|
refreshTimers()
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "TimerFragment"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ const val TAB_CLOCK = 0
|
|||||||
const val TAB_ALARM = 1
|
const val TAB_ALARM = 1
|
||||||
const val TAB_STOPWATCH = 2
|
const val TAB_STOPWATCH = 2
|
||||||
const val TAB_TIMER = 3
|
const val TAB_TIMER = 3
|
||||||
|
const val TIMER_ID = "timer_position"
|
||||||
|
|
||||||
// stopwatch sorting
|
// stopwatch sorting
|
||||||
const val SORT_BY_LAP = 1
|
const val SORT_BY_LAP = 1
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package com.simplemobiletools.clock.helpers
|
package com.simplemobiletools.clock.helpers
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import com.google.gson.Gson
|
import com.simplemobiletools.clock.extensions.gson.gson
|
||||||
import com.simplemobiletools.clock.models.StateWrapper
|
import com.simplemobiletools.clock.models.StateWrapper
|
||||||
import com.simplemobiletools.clock.models.TimerState
|
import com.simplemobiletools.clock.models.TimerState
|
||||||
|
|
||||||
class Converters {
|
class Converters {
|
||||||
private val gson = Gson()
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun jsonToTimerState(value: String): TimerState {
|
fun jsonToTimerState(value: String): TimerState {
|
||||||
|
@ -2,6 +2,7 @@ package com.simplemobiletools.clock.helpers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.RingtoneManager
|
import android.media.RingtoneManager
|
||||||
|
import android.util.Log
|
||||||
import com.simplemobiletools.clock.extensions.timerDb
|
import com.simplemobiletools.clock.extensions.timerDb
|
||||||
import com.simplemobiletools.clock.models.Timer
|
import com.simplemobiletools.clock.models.Timer
|
||||||
import com.simplemobiletools.clock.models.TimerState
|
import com.simplemobiletools.clock.models.TimerState
|
||||||
@ -12,15 +13,22 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
|||||||
class TimerHelper(val context: Context) {
|
class TimerHelper(val context: Context) {
|
||||||
private val timerDao = context.timerDb
|
private val timerDao = context.timerDb
|
||||||
|
|
||||||
fun getTimers(callback: (notes: List<Timer>) -> Unit) {
|
fun getTimers(callback: (timers: List<Timer>) -> Unit) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
callback.invoke(timerDao.getTimers())
|
callback.invoke(timerDao.getTimers())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getTimer(timerId: Long, callback: (timer: Timer) -> Unit) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
callback.invoke(timerDao.getTimer(timerId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun insertOrUpdateTimer(timer: Timer, callback: () -> Unit = {}) {
|
fun insertOrUpdateTimer(timer: Timer, callback: () -> Unit = {}) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
timerDao.insertOrUpdateTimer(timer)
|
val id = timerDao.insertOrUpdateTimer(timer)
|
||||||
|
Log.d(TAG, "insertOrUpdateTimer: $id")
|
||||||
callback.invoke()
|
callback.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,4 +56,8 @@ class TimerHelper(val context: Context) {
|
|||||||
callback.invoke()
|
callback.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "TimerHelper"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,9 @@ interface TimerDao {
|
|||||||
@Query("SELECT * FROM timers")
|
@Query("SELECT * FROM timers")
|
||||||
fun getTimers(): List<Timer>
|
fun getTimers(): List<Timer>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM timers WHERE id=:id")
|
||||||
|
fun getTimer(id: Long): Timer
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insertOrUpdateTimer(timer: Timer): Long
|
fun insertOrUpdateTimer(timer: Timer): Long
|
||||||
|
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.simplemobiletools.clock.models
|
||||||
|
|
||||||
|
sealed class TimerEvent(open val timerId: Long) {
|
||||||
|
data class Reset(override val timerId: Long, val duration: Long) : TimerEvent(timerId)
|
||||||
|
data class Start(override val timerId: Long, val duration: Long) : TimerEvent(timerId)
|
||||||
|
data class Pause(override val timerId: Long, val duration: Long) : TimerEvent(timerId)
|
||||||
|
data class Finish(override val timerId: Long, val duration: Long) : TimerEvent(timerId)
|
||||||
|
data class Refresh(override val timerId: Long) : TimerEvent(timerId)
|
||||||
|
}
|
@ -2,10 +2,7 @@ package com.simplemobiletools.clock.models
|
|||||||
|
|
||||||
sealed class TimerState {
|
sealed class TimerState {
|
||||||
object Idle : TimerState()
|
object Idle : TimerState()
|
||||||
data class Start(val duration: Long) : TimerState()
|
|
||||||
data class Running(val duration: Long, val tick: Long) : TimerState()
|
data class Running(val duration: Long, val tick: Long) : TimerState()
|
||||||
data class Pause(val duration: Long) : TimerState()
|
|
||||||
data class Paused(val duration: Long, val tick: Long) : TimerState()
|
data class Paused(val duration: Long, val tick: Long) : TimerState()
|
||||||
data class Finish(val duration: Long) : TimerState()
|
|
||||||
object Finished : TimerState()
|
object Finished : TimerState()
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ class TimerService : Service() {
|
|||||||
.setContentTitle(label)
|
.setContentTitle(label)
|
||||||
.setContentText(formattedDuration)
|
.setContentText(formattedDuration)
|
||||||
.setSmallIcon(R.drawable.ic_timer)
|
.setSmallIcon(R.drawable.ic_timer)
|
||||||
.setContentIntent(this.getOpenTimerTabIntent())
|
.setContentIntent(this.getOpenTimerTabIntent(0))
|
||||||
.setPriority(Notification.PRIORITY_DEFAULT)
|
.setPriority(Notification.PRIORITY_DEFAULT)
|
||||||
.setSound(null)
|
.setSound(null)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
android:padding="@dimen/normal_margin"
|
android:padding="@dimen/normal_margin"
|
||||||
android:src="@drawable/ic_reset_vector"
|
android:src="@drawable/ic_reset_vector"
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/timer_play_pause"
|
app:layout_constraintBottom_toBottomOf="@+id/timer_play_pause"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/timer_play_pause"
|
app:layout_constraintEnd_toStartOf="@+id/timer_play_pause"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
@ -1,111 +1,103 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:fillViewport="true">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/timer_time"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/normal_margin"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:padding="@dimen/small_margin"
|
||||||
|
android:textSize="@dimen/stopwatch_text_size"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="00:00" />
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MyTextView
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
android:id="@+id/timer_time"
|
android:id="@+id/timer_initial_time"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/activity_margin"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:drawableStart="@drawable/ic_timer"
|
||||||
|
android:drawablePadding="@dimen/normal_margin"
|
||||||
|
android:padding="@dimen/activity_margin"
|
||||||
|
android:textSize="@dimen/bigger_text_size"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/timer_time"
|
||||||
|
tools:text="05:00" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/timer_vibrate_holder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:padding="@dimen/activity_margin"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/timer_initial_time">
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||||
|
android:id="@+id/timer_vibrate"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/normal_margin"
|
android:background="@null"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:clickable="false"
|
||||||
android:gravity="center_horizontal"
|
android:drawableStart="@drawable/ic_vibrate_vector"
|
||||||
android:padding="@dimen/small_margin"
|
|
||||||
android:textSize="@dimen/stopwatch_text_size"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="00:00" />
|
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MyTextView
|
|
||||||
android:id="@+id/timer_initial_time"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/activity_margin"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_timer"
|
|
||||||
android:drawablePadding="@dimen/normal_margin"
|
android:drawablePadding="@dimen/normal_margin"
|
||||||
android:padding="@dimen/activity_margin"
|
android:text="@string/vibrate"
|
||||||
android:textSize="@dimen/bigger_text_size"
|
android:textSize="@dimen/bigger_text_size" />
|
||||||
app:layout_constraintTop_toBottomOf="@+id/timer_time"
|
|
||||||
tools:text="05:00" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
</RelativeLayout>
|
||||||
android:id="@+id/timer_vibrate_holder"
|
|
||||||
|
<com.simplemobiletools.commons.views.MyTextView
|
||||||
|
android:id="@+id/timer_sound"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:drawableStart="@drawable/ic_bell_vector"
|
||||||
|
android:drawablePadding="@dimen/normal_margin"
|
||||||
|
android:padding="@dimen/activity_margin"
|
||||||
|
android:textSize="@dimen/bigger_text_size"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/timer_vibrate_holder"
|
||||||
|
tools:text="Default alarm" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/timer_label_holder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="@dimen/activity_margin"
|
||||||
|
android:paddingTop="@dimen/medium_margin"
|
||||||
|
android:paddingEnd="@dimen/activity_margin"
|
||||||
|
android:paddingBottom="@dimen/medium_margin"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/timer_sound"
|
||||||
|
app:layout_constraintVertical_bias="0"
|
||||||
|
app:layout_constraintVertical_chainStyle="spread_inside">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/timer_label_image"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_label_vector" />
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MyEditText
|
||||||
|
android:id="@+id/timer_label"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:layout_marginStart="10dp"
|
||||||
android:padding="@dimen/activity_margin"
|
android:hint="@string/label"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/timer_initial_time">
|
android:maxLines="1"
|
||||||
|
android:singleLine="true"
|
||||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
android:textCursorDrawable="@null"
|
||||||
android:id="@+id/timer_vibrate"
|
android:textSize="@dimen/normal_text_size" />
|
||||||
android:layout_width="match_parent"
|
</LinearLayout>
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@null"
|
|
||||||
android:clickable="false"
|
|
||||||
android:drawableStart="@drawable/ic_vibrate_vector"
|
|
||||||
android:drawablePadding="@dimen/normal_margin"
|
|
||||||
android:text="@string/vibrate"
|
|
||||||
android:textSize="@dimen/bigger_text_size" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MyTextView
|
|
||||||
android:id="@+id/timer_sound"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:drawableStart="@drawable/ic_bell_vector"
|
|
||||||
android:drawablePadding="@dimen/normal_margin"
|
|
||||||
android:padding="@dimen/activity_margin"
|
|
||||||
android:textSize="@dimen/bigger_text_size"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/timer_vibrate_holder"
|
|
||||||
tools:text="Default alarm" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/timer_label_holder"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingStart="@dimen/activity_margin"
|
|
||||||
android:paddingTop="@dimen/medium_margin"
|
|
||||||
android:paddingEnd="@dimen/activity_margin"
|
|
||||||
android:paddingBottom="@dimen/medium_margin"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/timer_sound"
|
|
||||||
app:layout_constraintVertical_bias="0"
|
|
||||||
app:layout_constraintVertical_chainStyle="spread_inside">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/timer_label_image"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/ic_label_vector" />
|
|
||||||
|
|
||||||
<com.simplemobiletools.commons.views.MyEditText
|
|
||||||
android:id="@+id/timer_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:hint="@string/label"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textCursorDrawable="@null"
|
|
||||||
android:textSize="@dimen/normal_text_size" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user