Setup adding/removing multiple timers
This commit is contained in:
parent
49f0da8123
commit
921ca92885
|
@ -1,6 +1,7 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
def keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
def keystoreProperties = new Properties()
|
||||
|
@ -76,4 +77,6 @@ dependencies {
|
|||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
|
||||
implementation 'org.greenrobot:eventbus:3.2.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.room:room-runtime:2.3.0'
|
||||
kapt 'androidx.room:room-compiler:2.3.0'
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
package com.simplemobiletools.clock.adapters
|
||||
|
||||
import android.media.AudioManager
|
||||
import android.media.RingtoneManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.simplemobiletools.clock.R
|
||||
import com.simplemobiletools.clock.activities.SimpleActivity
|
||||
import com.simplemobiletools.clock.dialogs.MyTimePickerDialogDialog
|
||||
import com.simplemobiletools.clock.extensions.*
|
||||
import com.simplemobiletools.clock.helpers.PICK_AUDIO_FILE_INTENT_ID
|
||||
import com.simplemobiletools.clock.models.Timer
|
||||
import com.simplemobiletools.clock.models.TimerState
|
||||
import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog
|
||||
import com.simplemobiletools.commons.extensions.getDefaultAlarmSound
|
||||
import com.simplemobiletools.commons.extensions.getFormattedDuration
|
||||
import com.simplemobiletools.commons.extensions.onTextChangeListener
|
||||
import com.simplemobiletools.commons.models.AlarmSound
|
||||
import kotlinx.android.synthetic.main.item_timer.view.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
class TimerAdapter(
|
||||
private val activity: SimpleActivity,
|
||||
private val onRefresh: () -> Unit,
|
||||
|
||||
) : ListAdapter<Timer, TimerAdapter.TimerViewHolder>(diffUtil) {
|
||||
|
||||
private val config = activity.config
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimerViewHolder {
|
||||
return TimerViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_timer, parent, false))
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: TimerViewHolder, position: Int) {
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
|
||||
fun getItemAt(position: Int): Timer {
|
||||
return getItem(position)
|
||||
}
|
||||
|
||||
inner class TimerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
fun bind(timer: Timer) {
|
||||
itemView.apply {
|
||||
timer_time.text = timer.seconds.getFormattedDuration()
|
||||
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.colorLeftDrawable(textColor)
|
||||
|
||||
timer_vibrate.isChecked = timer.vibrate
|
||||
timer_vibrate.colorLeftDrawable(textColor)
|
||||
|
||||
timer_sound.text = timer.soundTitle
|
||||
timer_sound.colorLeftDrawable(textColor)
|
||||
|
||||
timer_time.setOnClickListener {
|
||||
stopTimer(timer)
|
||||
}
|
||||
|
||||
timer_time.setOnClickListener {
|
||||
changeDuration(timer)
|
||||
}
|
||||
|
||||
timer_initial_time.setOnClickListener {
|
||||
changeDuration(timer)
|
||||
}
|
||||
|
||||
timer_vibrate_holder.setOnClickListener {
|
||||
timer_vibrate.toggle()
|
||||
updateTimer(timer.copy(vibrate = timer_vibrate.isChecked), false)
|
||||
}
|
||||
|
||||
timer_sound.setOnClickListener {
|
||||
SelectAlarmSoundDialog(activity, config.timerSoundUri, AudioManager.STREAM_ALARM, PICK_AUDIO_FILE_INTENT_ID,
|
||||
RingtoneManager.TYPE_ALARM, true,
|
||||
onAlarmPicked = { sound ->
|
||||
if (sound != null) {
|
||||
updateAlarmSound(timer, sound)
|
||||
}
|
||||
},
|
||||
onAlarmSoundDeleted = { sound ->
|
||||
if (timer.soundUri == sound.uri) {
|
||||
val defaultAlarm = context.getDefaultAlarmSound(RingtoneManager.TYPE_ALARM)
|
||||
updateAlarmSound(timer, defaultAlarm)
|
||||
}
|
||||
|
||||
context.checkAlarmsWithDeletedSoundUri(sound.uri)
|
||||
})
|
||||
}
|
||||
|
||||
timer_label.onTextChangeListener { text ->
|
||||
updateTimer(timer.copy(label = text), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopTimer(timer: Timer) {
|
||||
EventBus.getDefault().post(TimerState.Idle)
|
||||
activity.hideTimerNotification()
|
||||
}
|
||||
|
||||
private fun changeDuration(timer: Timer) {
|
||||
MyTimePickerDialogDialog(activity, timer.seconds) { seconds ->
|
||||
val timerSeconds = if (seconds <= 0) 10 else seconds
|
||||
updateTimer(timer.copy(seconds = timerSeconds))
|
||||
}
|
||||
}
|
||||
|
||||
fun updateAlarmSound(timer: Timer, alarmSound: AlarmSound) {
|
||||
updateTimer(timer.copy(soundTitle = alarmSound.title, soundUri = alarmSound.uri))
|
||||
}
|
||||
|
||||
private fun updateTimer(timer: Timer, refresh: Boolean = true) {
|
||||
activity.timerHelper.insertOrUpdateTimer(timer)
|
||||
if (refresh) {
|
||||
onRefresh.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
val diffUtil = object : DiffUtil.ItemCallback<Timer>() {
|
||||
override fun areItemsTheSame(oldItem: Timer, newItem: Timer): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: Timer, newItem: Timer): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ import com.simplemobiletools.clock.fragments.TimerFragment
|
|||
import com.simplemobiletools.clock.helpers.TABS_COUNT
|
||||
import com.simplemobiletools.clock.helpers.TAB_ALARM
|
||||
import com.simplemobiletools.clock.helpers.TAB_CLOCK
|
||||
import com.simplemobiletools.clock.helpers.TAB_TIMER
|
||||
import com.simplemobiletools.commons.models.AlarmSound
|
||||
|
||||
class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
|
||||
|
@ -51,6 +50,6 @@ class ViewPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
|
|||
}
|
||||
|
||||
fun updateTimerTabAlarmSound(alarmSound: AlarmSound) {
|
||||
(fragments[TAB_TIMER] as? TimerFragment)?.updateAlarmSound(alarmSound)
|
||||
// (fragments[TAB_TIMER] as? TimerFragment)?.updateAlarmSound(alarmSound)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.simplemobiletools.clock.databases
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import com.simplemobiletools.clock.helpers.Converters
|
||||
import com.simplemobiletools.clock.interfaces.TimerDao
|
||||
import com.simplemobiletools.clock.models.Timer
|
||||
|
||||
@Database(entities = [Timer::class], version = 1)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun TimerDao(): TimerDao
|
||||
|
||||
companion object {
|
||||
private var db: AppDatabase? = null
|
||||
|
||||
fun getInstance(context: Context): AppDatabase {
|
||||
if (db == null) {
|
||||
synchronized(AppDatabase::class) {
|
||||
if (db == null) {
|
||||
db = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "app.db")
|
||||
.build()
|
||||
db!!.openHelper.setWriteAheadLoggingEnabled(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
return db!!
|
||||
}
|
||||
|
||||
fun destroyInstance() {
|
||||
db = null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,9 @@ import com.simplemobiletools.clock.R
|
|||
import com.simplemobiletools.clock.activities.ReminderActivity
|
||||
import com.simplemobiletools.clock.activities.SnoozeReminderActivity
|
||||
import com.simplemobiletools.clock.activities.SplashActivity
|
||||
import com.simplemobiletools.clock.databases.AppDatabase
|
||||
import com.simplemobiletools.clock.helpers.*
|
||||
import com.simplemobiletools.clock.interfaces.TimerDao
|
||||
import com.simplemobiletools.clock.models.Alarm
|
||||
import com.simplemobiletools.clock.models.MyTimeZone
|
||||
import com.simplemobiletools.clock.receivers.AlarmReceiver
|
||||
|
@ -39,6 +41,8 @@ import kotlin.math.pow
|
|||
val Context.config: Config get() = Config.newInstance(applicationContext)
|
||||
|
||||
val Context.dbHelper: DBHelper get() = DBHelper.newInstance(applicationContext)
|
||||
val Context.timerDb: TimerDao get() = AppDatabase.getInstance(applicationContext).TimerDao()
|
||||
val Context.timerHelper: TimerHelper get() = TimerHelper(this)
|
||||
|
||||
fun Context.getFormattedDate(calendar: Calendar): String {
|
||||
val dayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7 // make sure index 0 means monday
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
package com.simplemobiletools.clock.fragments
|
||||
|
||||
import android.graphics.Color
|
||||
import android.media.AudioManager
|
||||
import android.media.RingtoneManager
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.simplemobiletools.clock.R
|
||||
import com.simplemobiletools.clock.activities.SimpleActivity
|
||||
import com.simplemobiletools.clock.adapters.TimerAdapter
|
||||
import com.simplemobiletools.clock.dialogs.MyTimePickerDialogDialog
|
||||
import com.simplemobiletools.clock.extensions.*
|
||||
import com.simplemobiletools.clock.helpers.PICK_AUDIO_FILE_INTENT_ID
|
||||
import com.simplemobiletools.clock.extensions.config
|
||||
import com.simplemobiletools.clock.extensions.hideTimerNotification
|
||||
import com.simplemobiletools.clock.extensions.timerHelper
|
||||
import com.simplemobiletools.clock.models.Timer
|
||||
import com.simplemobiletools.clock.models.TimerState
|
||||
import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.models.AlarmSound
|
||||
import kotlinx.android.synthetic.main.fragment_timer.view.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class TimerFragment : Fragment() {
|
||||
|
||||
lateinit var view: ViewGroup
|
||||
private lateinit var timerAdapter: TimerAdapter
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -39,91 +39,82 @@ class TimerFragment : Fragment() {
|
|||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
view = (inflater.inflate(R.layout.fragment_timer, container, false) as ViewGroup).apply {
|
||||
val config = requiredActivity.config
|
||||
val textColor = config.textColor
|
||||
timerAdapter = TimerAdapter(requireActivity() as SimpleActivity) {
|
||||
refreshTimers()
|
||||
}
|
||||
timer_view_pager.adapter = timerAdapter
|
||||
timer_view_pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
updateViews(position)
|
||||
}
|
||||
})
|
||||
|
||||
timer_time.text = config.timerSeconds.getFormattedDuration()
|
||||
timer_label.setText(config.timerLabel)
|
||||
|
||||
activity?.updateTextColors(timer_fragment)
|
||||
timer_play_pause.background = resources.getColoredDrawableWithColor(R.drawable.circle_background_filled, requireContext().getAdjustedPrimaryColor())
|
||||
timer_play_pause.applyColorFilter(if (requireContext().getAdjustedPrimaryColor() == Color.WHITE) Color.BLACK else Color.WHITE)
|
||||
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 {
|
||||
stopTimer()
|
||||
timer_add.setOnClickListener {
|
||||
activity?.hideKeyboard(it)
|
||||
activity?.timerHelper?.insertNewTimer {
|
||||
refreshTimers(true)
|
||||
}
|
||||
}
|
||||
|
||||
timer_play_pause.setOnClickListener {
|
||||
val state = config.timerState
|
||||
activity?.updateTextColors(timer_fragment)
|
||||
|
||||
when (state) {
|
||||
is TimerState.Idle -> EventBus.getDefault().post(TimerState.Start(config.timerSeconds.secondsToMillis))
|
||||
is TimerState.Paused -> EventBus.getDefault().post(TimerState.Start(state.tick))
|
||||
is TimerState.Running -> EventBus.getDefault().post(TimerState.Pause(state.tick))
|
||||
is TimerState.Finished -> EventBus.getDefault().post(TimerState.Start(config.timerSeconds.secondsToMillis))
|
||||
val textColor = requireContext().config.textColor
|
||||
timer_play_pause.background =
|
||||
resources.getColoredDrawableWithColor(R.drawable.circle_background_filled, requireActivity().getAdjustedPrimaryColor())
|
||||
timer_play_pause.applyColorFilter(if (activity?.getAdjustedPrimaryColor() == Color.WHITE) Color.BLACK else Color.WHITE)
|
||||
timer_reset.applyColorFilter(textColor)
|
||||
|
||||
|
||||
timer_play_pause.setOnClickListener {
|
||||
val timer = timerAdapter.getItemAt(timer_view_pager.currentItem)
|
||||
when (val state = timer.state) {
|
||||
// is TimerState.Idle -> EventBus.getDefault().post(TimerState.Start(timer.seconds.secondsToMillis))
|
||||
// is TimerState.Paused -> EventBus.getDefault().post(TimerState.Start(state.tick))
|
||||
// is TimerState.Running -> EventBus.getDefault().post(TimerState.Pause(state.tick))
|
||||
// is TimerState.Finished -> EventBus.getDefault().post(TimerState.Start(timer.seconds.secondsToMillis))
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timer_reset.setOnClickListener {
|
||||
stopTimer()
|
||||
val timer = timerAdapter.getItemAt(timer_view_pager.currentItem)
|
||||
stopTimer(timer)
|
||||
}
|
||||
|
||||
timer_time.setOnClickListener {
|
||||
changeDuration()
|
||||
timer_delete.setOnClickListener {
|
||||
val timer = timerAdapter.getItemAt(timer_view_pager.currentItem)
|
||||
activity?.timerHelper?.deleteTimer(timer.id!!) {
|
||||
refreshTimers()
|
||||
}
|
||||
}
|
||||
|
||||
timer_initial_time.setOnClickListener {
|
||||
changeDuration()
|
||||
}
|
||||
|
||||
timer_vibrate_holder.setOnClickListener {
|
||||
timer_vibrate.toggle()
|
||||
config.timerVibrate = timer_vibrate.isChecked
|
||||
config.timerChannelId = null
|
||||
}
|
||||
|
||||
timer_sound.setOnClickListener {
|
||||
SelectAlarmSoundDialog(activity as SimpleActivity, config.timerSoundUri, AudioManager.STREAM_ALARM, PICK_AUDIO_FILE_INTENT_ID,
|
||||
RingtoneManager.TYPE_ALARM, true,
|
||||
onAlarmPicked = { sound ->
|
||||
if (sound != null) {
|
||||
updateAlarmSound(sound)
|
||||
}
|
||||
},
|
||||
onAlarmSoundDeleted = { sound ->
|
||||
if (config.timerSoundUri == sound.uri) {
|
||||
val defaultAlarm = context.getDefaultAlarmSound(RingtoneManager.TYPE_ALARM)
|
||||
updateAlarmSound(defaultAlarm)
|
||||
}
|
||||
|
||||
context.checkAlarmsWithDeletedSoundUri(sound.uri)
|
||||
})
|
||||
}
|
||||
|
||||
timer_label.onTextChangeListener { text ->
|
||||
config.timerLabel = text
|
||||
}
|
||||
refreshTimers()
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
private fun stopTimer() {
|
||||
private fun updateViews(position: Int) {
|
||||
val timer = timerAdapter.getItemAt(position)
|
||||
//check if timer is running to update view
|
||||
}
|
||||
|
||||
private fun refreshTimers(scrollToLast: Boolean = false) {
|
||||
activity?.timerHelper?.getTimers { timers ->
|
||||
timerAdapter.submitList(timers)
|
||||
activity?.runOnUiThread {
|
||||
view.timer_delete.beVisibleIf(timers.size > 1)
|
||||
if (scrollToLast) {
|
||||
view.timer_view_pager.currentItem = timers.lastIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopTimer(timer: Timer) {
|
||||
EventBus.getDefault().post(TimerState.Idle)
|
||||
activity?.hideTimerNotification()
|
||||
view.timer_time.text = activity?.config?.timerSeconds?.getFormattedDuration()
|
||||
// view.timer_time.text = activity?.config?.timerSeconds?.getFormattedDuration()
|
||||
}
|
||||
|
||||
private fun changeDuration() {
|
||||
|
@ -131,23 +122,23 @@ class TimerFragment : Fragment() {
|
|||
val timerSeconds = if (seconds <= 0) 10 else seconds
|
||||
activity?.config?.timerSeconds = timerSeconds
|
||||
val duration = timerSeconds.getFormattedDuration()
|
||||
view.timer_initial_time.text = duration
|
||||
// view.timer_initial_time.text = duration
|
||||
|
||||
if (view.timer_reset.isGone()) {
|
||||
stopTimer()
|
||||
}
|
||||
// if (view.timer_reset.isGone()) {
|
||||
// stopTimer()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(state: TimerState.Idle) {
|
||||
view.timer_time.text = requiredActivity.config.timerSeconds.getFormattedDuration()
|
||||
// view.timer_time.text = requiredActivity.config.timerSeconds.getFormattedDuration()
|
||||
updateViewStates(state)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(state: TimerState.Running) {
|
||||
view.timer_time.text = state.tick.div(1000F).roundToInt().getFormattedDuration()
|
||||
// view.timer_time.text = state.tick.div(1000F).roundToInt().getFormattedDuration()
|
||||
updateViewStates(state)
|
||||
}
|
||||
|
||||
|
@ -158,7 +149,7 @@ class TimerFragment : Fragment() {
|
|||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(state: TimerState.Finished) {
|
||||
view.timer_time.text = 0.getFormattedDuration()
|
||||
// view.timer_time.text = 0.getFormattedDuration()
|
||||
updateViewStates(state)
|
||||
}
|
||||
|
||||
|
@ -180,10 +171,10 @@ class TimerFragment : Fragment() {
|
|||
|
||||
view.timer_play_pause.setImageDrawable(resources.getColoredDrawableWithColor(drawableId, iconColor))
|
||||
}
|
||||
|
||||
fun updateAlarmSound(alarmSound: AlarmSound) {
|
||||
activity?.config?.timerSoundTitle = alarmSound.title
|
||||
activity?.config?.timerSoundUri = alarmSound.uri
|
||||
view.timer_sound.text = alarmSound.title
|
||||
}
|
||||
//
|
||||
// fun updateAlarmSound(alarmSound: AlarmSound) {
|
||||
// activity?.config?.timerSoundTitle = alarmSound.title
|
||||
// activity?.config?.timerSoundUri = alarmSound.uri
|
||||
// view.timer_sound.text = alarmSound.title
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.simplemobiletools.clock.helpers
|
||||
|
||||
import com.simplemobiletools.clock.models.MyTimeZone
|
||||
import java.util.*
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.TimeZone
|
||||
import kotlin.math.pow
|
||||
|
||||
// shared preferences
|
||||
|
@ -56,6 +58,8 @@ const val SORT_BY_ALARM_TIME = 1
|
|||
const val TODAY_BIT = -1
|
||||
const val TOMORROW_BIT = -2
|
||||
|
||||
const val DEFAULT_TIME = 300
|
||||
|
||||
fun getDefaultTimeZoneTitle(id: Int) = getAllTimeZones().firstOrNull { it.id == id }?.title ?: ""
|
||||
|
||||
fun getMSTillNextMinute(): Long {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package com.simplemobiletools.clock.helpers
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.google.gson.Gson
|
||||
import com.simplemobiletools.clock.models.StateWrapper
|
||||
import com.simplemobiletools.clock.models.TimerState
|
||||
|
||||
class Converters {
|
||||
private val gson = Gson()
|
||||
|
||||
@TypeConverter
|
||||
fun jsonToTimerState(value: String): TimerState {
|
||||
return try {
|
||||
gson.fromJson(value, StateWrapper::class.java).state
|
||||
} catch (e: Exception) {
|
||||
TimerState.Idle
|
||||
}
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun timerStateToJson(state: TimerState) = gson.toJson(StateWrapper(state))
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.simplemobiletools.clock.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.media.RingtoneManager
|
||||
import com.simplemobiletools.clock.extensions.timerDb
|
||||
import com.simplemobiletools.clock.models.Timer
|
||||
import com.simplemobiletools.clock.models.TimerState
|
||||
import com.simplemobiletools.commons.extensions.getDefaultAlarmSound
|
||||
import com.simplemobiletools.commons.extensions.getDefaultAlarmTitle
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
|
||||
class TimerHelper(val context: Context) {
|
||||
private val timerDao = context.timerDb
|
||||
|
||||
fun getTimers(callback: (notes: List<Timer>) -> Unit) {
|
||||
ensureBackgroundThread {
|
||||
callback.invoke(timerDao.getTimers())
|
||||
}
|
||||
}
|
||||
|
||||
fun insertOrUpdateTimer(timer: Timer, callback: () -> Unit = {}) {
|
||||
ensureBackgroundThread {
|
||||
timerDao.insertOrUpdateTimer(timer)
|
||||
callback.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteTimer(id: Long, callback: () -> Unit = {}) {
|
||||
ensureBackgroundThread {
|
||||
timerDao.deleteTimer(id)
|
||||
callback.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun insertNewTimer(callback: () -> Unit = {}) {
|
||||
ensureBackgroundThread {
|
||||
timerDao.insertOrUpdateTimer(
|
||||
Timer(id = null,
|
||||
seconds = DEFAULT_TIME,
|
||||
TimerState.Idle,
|
||||
false,
|
||||
context.getDefaultAlarmSound(RingtoneManager.TYPE_ALARM).uri,
|
||||
context.getDefaultAlarmTitle(RingtoneManager.TYPE_ALARM),
|
||||
"",
|
||||
DEFAULT_MAX_TIMER_REMINDER_SECS.toString())
|
||||
)
|
||||
|
||||
callback.invoke()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.simplemobiletools.clock.interfaces
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.simplemobiletools.clock.models.Timer
|
||||
|
||||
@Dao
|
||||
interface TimerDao {
|
||||
|
||||
@Query("SELECT * FROM timers")
|
||||
fun getTimers(): List<Timer>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertOrUpdateTimer(timer: Timer): Long
|
||||
|
||||
@Query("DELETE FROM timers WHERE id=:id")
|
||||
fun deleteTimer(id: Long)
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.simplemobiletools.clock.models
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "timers")
|
||||
data class Timer(
|
||||
@PrimaryKey(autoGenerate = true) val id: Long?,
|
||||
val seconds: Int,
|
||||
val state: TimerState,
|
||||
val vibrate: Boolean,
|
||||
val soundUri: String,
|
||||
val soundTitle: String,
|
||||
val label: String,
|
||||
val maxReminderSecs: String,
|
||||
)
|
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"
|
||||
android:strokeWidth="1.6"
|
||||
android:strokeColor="#FFFFFFFF" />
|
||||
</vector>
|
|
@ -6,127 +6,16 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/timer_scroll"
|
||||
android:layout_width="0dp"
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/timer_view_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/timer_play_pause"
|
||||
android:layout_marginBottom="@dimen/medium_margin"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@id/timer_play_pause"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/timer_constraint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/timer_time"
|
||||
android:layout_width="match_parent"
|
||||
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
|
||||
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:drawableLeft="@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_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:drawableLeft="@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:drawableLeft="@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_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/timer_sound">
|
||||
|
||||
<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>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timer_play_pause"
|
||||
android:layout_width="@dimen/stopwatch_button_size"
|
||||
android:layout_height="@dimen/stopwatch_button_size"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="@dimen/big_margin"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_play_vector"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timer_reset"
|
||||
|
@ -140,8 +29,53 @@
|
|||
app:layout_constraintEnd_toStartOf="@+id/timer_play_pause"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/timer_play_pause"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timer_delete"
|
||||
android:layout_width="@dimen/stopwatch_button_small_size"
|
||||
android:layout_height="@dimen/stopwatch_button_small_size"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_delete_vector"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/timer_play_pause"
|
||||
app:layout_constraintEnd_toStartOf="@+id/timer_play_pause"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/timer_play_pause"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timer_play_pause"
|
||||
android:layout_width="@dimen/stopwatch_button_size"
|
||||
android:layout_height="@dimen/stopwatch_button_size"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="@dimen/big_margin"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_play_vector"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timer_add"
|
||||
android:layout_width="@dimen/stopwatch_button_size"
|
||||
android:layout_height="@dimen/stopwatch_button_size"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="@dimen/big_margin"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_add_vector"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/timer_play_pause" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView 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"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/timer_time"
|
||||
android:layout_width="match_parent"
|
||||
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
|
||||
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_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>
|
||||
|
||||
|
Loading…
Reference in New Issue