Merge pull request #506 from esensar/feature/357-new-intents

Add new intents for alarms and timers
This commit is contained in:
Tibor Kaputa 2023-09-05 11:27:25 +02:00 committed by GitHub
commit 35132e7074
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 890 additions and 43 deletions

View file

@ -0,0 +1,88 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "70b55e9d6e9c68ce252a7c25a4809ea3",
"entities": [
{
"tableName": "timers",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `seconds` INTEGER NOT NULL, `state` TEXT NOT NULL, `vibrate` INTEGER NOT NULL, `soundUri` TEXT NOT NULL, `soundTitle` TEXT NOT NULL, `label` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `channelId` TEXT, `oneShot` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "seconds",
"columnName": "seconds",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "vibrate",
"columnName": "vibrate",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "soundUri",
"columnName": "soundUri",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "soundTitle",
"columnName": "soundTitle",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "label",
"columnName": "label",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "createdAt",
"columnName": "createdAt",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "channelId",
"columnName": "channelId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "oneShot",
"columnName": "oneShot",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '70b55e9d6e9c68ce252a7c25a4809ea3')"
]
}
}

View file

@ -44,11 +44,29 @@
<intent-filter>
<action android:name="com.simplemobiletools.clock.TOGGLE_STOPWATCH" />
<action android:name="android.intent.action.SHOW_ALARMS" />
<action android:name="android.intent.action.SHOW_TIMERS" />
<action android:name="android.intent.action.SET_ALARM" />
<action android:name="android.intent.action.SET_TIMER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DISMISS_ALARM" />
<action android:name="android.intent.action.DISMISS_TIMER" />
<data android:scheme="id" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activities.IntentHandlerActivity"
android:configChanges="orientation"
android:exported="false"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustPan" />
<activity
android:name=".activities.MainActivity"
android:configChanges="orientation"
@ -63,7 +81,13 @@
android:exported="false"
android:launchMode="singleTask"
android:showOnLockScreen="true"
android:taskAffinity=".ReminderActivity" />
android:taskAffinity=".ReminderActivity">
<intent-filter>
<action android:name="android.intent.action.SNOOZE_ALARM" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activities.SettingsActivity"
@ -123,13 +147,17 @@
<service
android:name=".services.TimerService"
android:foregroundServiceType="specialUse">
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="Used to notify the user that timers are running"/>
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Used to notify the user that timers are running" />
</service>
<service
android:name=".services.StopwatchService"
android:foregroundServiceType="specialUse">
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="Used to notify the user that stopwatch is running"/>
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Used to notify the user that stopwatch is running" />
</service>
<receiver android:name=".receivers.AlarmReceiver" />

View file

@ -135,8 +135,14 @@ class App : Application(), LifecycleObserver {
private fun updateTimerState(timerId: Int, state: TimerState) {
timerHelper.getTimer(timerId) { timer ->
val newTimer = timer.copy(state = state)
timerHelper.insertOrUpdateTimer(newTimer) {
EventBus.getDefault().post(TimerEvent.Refresh)
if (newTimer.oneShot && state is TimerState.Idle) {
timerHelper.deleteTimer(newTimer.id!!) {
EventBus.getDefault().post(TimerEvent.Refresh)
}
} else {
timerHelper.insertOrUpdateTimer(newTimer) {
EventBus.getDefault().post(TimerEvent.Refresh)
}
}
}
}

View file

@ -0,0 +1,375 @@
package com.simplemobiletools.clock.activities
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.os.Bundle
import android.provider.AlarmClock
import com.simplemobiletools.clock.R
import com.simplemobiletools.clock.dialogs.EditAlarmDialog
import com.simplemobiletools.clock.dialogs.EditTimerDialog
import com.simplemobiletools.clock.dialogs.SelectAlarmDialog
import com.simplemobiletools.clock.extensions.*
import com.simplemobiletools.clock.helpers.*
import com.simplemobiletools.clock.models.*
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.extensions.getDefaultAlarmSound
import com.simplemobiletools.commons.extensions.getFilenameFromUri
import com.simplemobiletools.commons.extensions.openNotificationSettings
import com.simplemobiletools.commons.helpers.SILENT
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.AlarmSound
import org.greenrobot.eventbus.EventBus
import java.util.concurrent.TimeUnit
class IntentHandlerActivity : SimpleActivity() {
companion object {
@SuppressLint("InlinedApi")
val HANDLED_ACTIONS = listOf(
AlarmClock.ACTION_SET_ALARM,
AlarmClock.ACTION_SET_TIMER,
AlarmClock.ACTION_DISMISS_ALARM,
AlarmClock.ACTION_DISMISS_TIMER
)
private const val URI_SCHEME = "id"
}
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intentToHandle: Intent) {
intentToHandle.apply {
when (action) {
AlarmClock.ACTION_SET_ALARM -> setNewAlarm()
AlarmClock.ACTION_SET_TIMER -> setNewTimer()
AlarmClock.ACTION_DISMISS_ALARM -> dismissAlarm()
AlarmClock.ACTION_DISMISS_TIMER -> dismissTimer()
else -> finish()
}
}
}
private fun Intent.setNewAlarm() {
val hour = getIntExtra(AlarmClock.EXTRA_HOUR, 0).coerceIn(0, 23)
val minute = getIntExtra(AlarmClock.EXTRA_MINUTES, 0).coerceIn(0, 59)
val days = getIntegerArrayListExtra(AlarmClock.EXTRA_DAYS) ?: getIntArrayExtra(AlarmClock.EXTRA_DAYS)?.toList()
val message = getStringExtra(AlarmClock.EXTRA_MESSAGE)
val ringtone = getStringExtra(AlarmClock.EXTRA_RINGTONE)
val vibrate = getBooleanExtra(AlarmClock.EXTRA_VIBRATE, true)
val skipUi = getBooleanExtra(AlarmClock.EXTRA_SKIP_UI, false)
val defaultAlarmSound = getDefaultAlarmSound(RingtoneManager.TYPE_ALARM)
var weekDays = 0
days?.forEach {
weekDays += getBitForCalendarDay(it)
}
val soundToUse = ringtone?.let {
if (it == AlarmClock.VALUE_RINGTONE_SILENT) {
AlarmSound(0, getString(com.simplemobiletools.commons.R.string.no_sound), SILENT)
} else {
try {
val uri = Uri.parse(it)
var filename = getFilenameFromUri(uri)
if (filename.isEmpty()) {
filename = getString(com.simplemobiletools.commons.R.string.alarm)
}
AlarmSound(0, filename, it)
} catch (e: Exception) {
null
}
}
} ?: defaultAlarmSound
// We don't want to accidentally edit existing alarm, so allow reuse only when skipping UI
if (hasExtra(AlarmClock.EXTRA_HOUR) && skipUi) {
var daysToCompare = weekDays
val timeInMinutes = hour * 60 + minute
if (weekDays <= 0) {
daysToCompare = if (timeInMinutes > getCurrentDayMinutes()) {
TODAY_BIT
} else {
TOMORROW_BIT
}
}
val existingAlarm = dbHelper.getAlarms().firstOrNull {
it.days == daysToCompare
&& it.vibrate == vibrate
&& it.soundTitle == soundToUse.title
&& it.soundUri == soundToUse.uri
&& it.label == (message ?: "")
&& it.timeInMinutes == timeInMinutes
}
if (existingAlarm != null && !existingAlarm.isEnabled) {
existingAlarm.isEnabled = true
startAlarm(existingAlarm)
finish()
}
}
val newAlarm = createNewAlarm(DEFAULT_ALARM_MINUTES, 0)
newAlarm.isEnabled = true
newAlarm.days = weekDays
newAlarm.vibrate = vibrate
newAlarm.soundTitle = soundToUse.title
newAlarm.soundUri = soundToUse.uri
if (message != null) {
newAlarm.label = message
}
if (!hasExtra(AlarmClock.EXTRA_HOUR) || !skipUi) {
newAlarm.id = -1
newAlarm.timeInMinutes += minute
openEditAlarm(newAlarm)
} else {
newAlarm.timeInMinutes = hour * 60 + minute
if (newAlarm.days <= 0) {
newAlarm.days = if (newAlarm.timeInMinutes > getCurrentDayMinutes()) {
TODAY_BIT
} else {
TOMORROW_BIT
}
newAlarm.oneShot = true
}
ensureBackgroundThread {
newAlarm.id = dbHelper.insertAlarm(newAlarm)
runOnUiThread {
startAlarm(newAlarm)
finish()
}
}
}
}
private fun Intent.setNewTimer() {
val length = getIntExtra(AlarmClock.EXTRA_LENGTH, -1)
val message = getStringExtra(AlarmClock.EXTRA_MESSAGE)
val skipUi = getBooleanExtra(AlarmClock.EXTRA_SKIP_UI, false)
fun createAndStartNewTimer() {
val newTimer = createNewTimer()
if (message != null) {
newTimer.label = message
}
if (length < 0 || !skipUi) {
newTimer.id = -1
openEditTimer(newTimer)
} else {
newTimer.seconds = length
newTimer.oneShot = true
timerHelper.insertOrUpdateTimer(newTimer) {
config.timerLastConfig = newTimer
newTimer.id = it.toInt()
startTimer(newTimer)
}
}
}
if (hasExtra(AlarmClock.EXTRA_LENGTH)) {
timerHelper.findTimers(length, message ?: "") {
val existingTimer = it.firstOrNull { it.state is TimerState.Idle }
// We don't want to accidentally edit existing timer, so allow reuse only when skipping UI
if (existingTimer != null
&& skipUi
&& (existingTimer.state is TimerState.Idle || (existingTimer.state is TimerState.Finished && !existingTimer.oneShot))) {
startTimer(existingTimer)
} else {
createAndStartNewTimer()
}
}
} else {
createAndStartNewTimer()
}
}
private fun Intent.dismissAlarm() {
val searchMode = getStringExtra(AlarmClock.EXTRA_ALARM_SEARCH_MODE)
val uri = data
if (uri != null) {
if (uri.scheme == URI_SCHEME) {
val id = uri.schemeSpecificPart.toIntOrNull()
if (id != null) {
val alarm = dbHelper.getAlarmWithId(id)
if (alarm != null) {
getDismissAlarmPendingIntent(alarm.id, EARLY_ALARM_NOTIF_ID).send()
EventBus.getDefault().post(AlarmEvent.Refresh)
finish()
}
}
}
finish()
} else {
var alarms = dbHelper.getAlarms().filter { it.isEnabled }
if (searchMode != null) {
when (searchMode) {
AlarmClock.ALARM_SEARCH_MODE_TIME -> {
if (hasExtra(AlarmClock.EXTRA_HOUR)) {
val hour = getIntExtra(AlarmClock.EXTRA_HOUR, -1).coerceIn(0, 23)
alarms = alarms.filter { it.timeInMinutes / 60 == hour || it.timeInMinutes / 60 == hour + 12 }
}
if (hasExtra(AlarmClock.EXTRA_MINUTES)) {
val minute = getIntExtra(AlarmClock.EXTRA_MINUTES, -1).coerceIn(0, 59)
alarms = alarms.filter { it.timeInMinutes % 60 == minute }
}
if (hasExtra(AlarmClock.EXTRA_IS_PM)) {
val isPm = getBooleanExtra(AlarmClock.EXTRA_IS_PM, false)
alarms = alarms.filter {
val hour = it.timeInMinutes / 60
if (isPm) {
hour in 12..23
} else {
hour in 0..11
}
}
}
}
AlarmClock.ALARM_SEARCH_MODE_NEXT -> {
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val next = alarmManager.nextAlarmClock
val timeInMinutes = TimeUnit.MILLISECONDS.toMinutes(next.triggerTime).toInt()
val dayBitToLookFor = if (timeInMinutes <= getCurrentDayMinutes()) {
getTomorrowBit()
} else {
getTodayBit()
}
val dayToLookFor = if (timeInMinutes <= getCurrentDayMinutes()) {
TOMORROW_BIT
} else {
TODAY_BIT
}
alarms = alarms.filter {
it.timeInMinutes == timeInMinutes && (it.days.isBitSet(dayBitToLookFor) || it.days == dayToLookFor)
}
}
AlarmClock.ALARM_SEARCH_MODE_LABEL -> {
val messageToSearchFor = getStringExtra(AlarmClock.EXTRA_MESSAGE)
if (messageToSearchFor != null) {
alarms = alarms.filter { it.label.contains(messageToSearchFor, ignoreCase = true) }
}
}
AlarmClock.ALARM_SEARCH_MODE_ALL -> {
// no-op - no further filtering needed
}
}
}
if (alarms.count() == 1) {
getDismissAlarmPendingIntent(alarms.first().id, EARLY_ALARM_NOTIF_ID).send()
EventBus.getDefault().post(AlarmEvent.Refresh)
finish()
} else if (alarms.count() > 1) {
SelectAlarmDialog(this@IntentHandlerActivity, alarms, R.string.select_alarm_to_dismiss) {
if (it != null) {
getDismissAlarmPendingIntent(it.id, EARLY_ALARM_NOTIF_ID).send()
}
EventBus.getDefault().post(AlarmEvent.Refresh)
finish()
}
} else {
finish()
}
}
}
private fun Intent.dismissTimer() {
val uri = data
if (uri == null) {
timerHelper.getTimers {
it.filter { it.state == TimerState.Finished }.forEach {
getHideTimerPendingIntent(it.id!!).send()
}
EventBus.getDefault().post(TimerEvent.Refresh)
finish()
}
return
} else if (uri.scheme == URI_SCHEME) {
val id = uri.schemeSpecificPart.toIntOrNull()
if (id != null) {
timerHelper.tryGetTimer(id) {
if (it != null) {
getHideTimerPendingIntent(it.id!!).send()
EventBus.getDefault().post(TimerEvent.Refresh)
finish()
} else {
finish()
}
}
return
}
}
finish()
}
private fun openEditAlarm(alarm: Alarm) {
EditAlarmDialog(this, alarm, onDismiss = { finish() }) {
alarm.id = it
startAlarm(alarm)
finish()
}
}
private fun openEditTimer(timer: Timer) {
EditTimerDialog(this, timer) {
timer.id = it.toInt()
startTimer(timer)
}
}
private fun startAlarm(alarm: Alarm) {
scheduleNextAlarm(alarm, true)
EventBus.getDefault().post(AlarmEvent.Refresh)
}
private fun startTimer(timer: Timer) {
handleNotificationPermission { granted ->
val newState = TimerState.Running(timer.seconds.secondsToMillis, timer.seconds.secondsToMillis)
val newTimer = timer.copy(state = newState)
fun notifyAndStartTimer() {
EventBus.getDefault().post(TimerEvent.Start(newTimer.id!!, newTimer.seconds.secondsToMillis))
EventBus.getDefault().post(TimerEvent.Refresh)
}
if (granted) {
timerHelper.insertOrUpdateTimer(newTimer) {
notifyAndStartTimer()
finish()
}
} else {
PermissionRequiredDialog(
this,
com.simplemobiletools.commons.R.string.allow_notifications_reminders,
positiveActionCallback = {
openNotificationSettings()
timerHelper.insertOrUpdateTimer(newTimer) {
notifyAndStartTimer()
finish()
}
},
negativeActionCallback = {
finish()
})
}
}
}
}

View file

@ -7,6 +7,7 @@ import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.*
import android.provider.AlarmClock
import android.view.MotionEvent
import android.view.WindowManager
import android.view.animation.AnimationUtils
@ -220,7 +221,16 @@ class ReminderActivity : SimpleActivity() {
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
finishActivity()
if (intent?.action == AlarmClock.ACTION_SNOOZE_ALARM) {
val durationMinutes = intent.getIntExtra(AlarmClock.EXTRA_ALARM_SNOOZE_DURATION, -1)
if (durationMinutes == -1) {
snoozeAlarm()
} else {
snoozeAlarm(durationMinutes)
}
} else {
finishActivity()
}
}
override fun onDestroy() {
@ -244,9 +254,13 @@ class ReminderActivity : SimpleActivity() {
vibrator = null
}
private fun snoozeAlarm() {
private fun snoozeAlarm(overrideSnoozeDuration: Int? = null) {
destroyEffects()
if (config.useSameSnooze) {
if (overrideSnoozeDuration != null) {
setupAlarmClock(alarm!!, overrideSnoozeDuration * MINUTE_SECONDS)
wasAlarmSnoozed = true
finishActivity()
} else if (config.useSameSnooze) {
setupAlarmClock(alarm!!, config.snoozeTime * MINUTE_SECONDS)
wasAlarmSnoozed = true
finishActivity()
@ -262,12 +276,17 @@ class ReminderActivity : SimpleActivity() {
private fun finishActivity() {
if (!wasAlarmSnoozed && alarm != null) {
cancelAlarmClock(alarm!!)
if (alarm!!.days > 0) {
scheduleNextAlarm(alarm!!, false)
}
if (alarm!!.days < 0) {
dbHelper.updateAlarmEnabledState(alarm!!.id, false)
if (alarm!!.oneShot) {
alarm!!.isEnabled = false
dbHelper.deleteAlarms(arrayListOf(alarm!!))
} else {
dbHelper.updateAlarmEnabledState(alarm!!.id, false)
}
updateWidgets()
}
}

View file

@ -14,6 +14,13 @@ class SplashActivity : BaseSplashActivity() {
}
}
intent?.action == "android.intent.action.SHOW_TIMERS" -> {
Intent(this, MainActivity::class.java).apply {
putExtra(OPEN_TAB, TAB_TIMER)
startActivity(this)
}
}
intent?.action == STOPWATCH_TOGGLE_ACTION -> {
Intent(this, MainActivity::class.java).apply {
putExtra(OPEN_TAB, TAB_STOPWATCH)
@ -30,6 +37,13 @@ class SplashActivity : BaseSplashActivity() {
}
}
IntentHandlerActivity.HANDLED_ACTIONS.contains(intent?.action) -> {
Intent(intent).apply {
setClass(this@SplashActivity, IntentHandlerActivity::class.java)
startActivity(this)
}
}
else -> startActivity(Intent(this, MainActivity::class.java))
}
finish()

View file

@ -5,6 +5,7 @@ import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.simplemobiletools.clock.extensions.config
import com.simplemobiletools.clock.helpers.Converters
@ -13,7 +14,7 @@ import com.simplemobiletools.clock.models.Timer
import com.simplemobiletools.clock.models.TimerState
import java.util.concurrent.Executors
@Database(entities = [Timer::class], version = 1)
@Database(entities = [Timer::class], version = 2)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
@ -28,6 +29,7 @@ abstract class AppDatabase : RoomDatabase() {
if (db == null) {
db = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "app.db")
.fallbackToDestructiveMigration()
.addMigrations(MIGRATION_1_2)
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
@ -59,5 +61,11 @@ abstract class AppDatabase : RoomDatabase() {
)
}
}
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE `timers` ADD COLUMN `oneShot` INTEGER NOT NULL DEFAULT 0")
}
}
}
}

View file

@ -23,7 +23,7 @@ import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.models.AlarmSound
class EditAlarmDialog(val activity: SimpleActivity, val alarm: Alarm, val callback: (alarmId: Int) -> Unit) {
class EditAlarmDialog(val activity: SimpleActivity, val alarm: Alarm, val onDismiss: () -> Unit = {}, val callback: (alarmId: Int) -> Unit) {
private val binding = DialogEditAlarmBinding.inflate(activity.layoutInflater)
private val textColor = activity.getProperTextColor()
@ -127,6 +127,7 @@ class EditAlarmDialog(val activity: SimpleActivity, val alarm: Alarm, val callba
}
activity.getAlertDialogBuilder()
.setOnDismissListener { onDismiss() }
.setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
@ -156,6 +157,7 @@ class EditAlarmDialog(val activity: SimpleActivity, val alarm: Alarm, val callba
alarm.label = binding.editAlarm.value
alarm.isEnabled = true
alarm.oneShot = false
var alarmId = alarm.id
activity.handleFullScreenNotificationsPermission { granted ->

View file

@ -12,7 +12,7 @@ import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.models.AlarmSound
class EditTimerDialog(val activity: SimpleActivity, val timer: Timer, val callback: () -> Unit) {
class EditTimerDialog(val activity: SimpleActivity, val timer: Timer, val callback: (id: Long) -> Unit) {
private val binding = DialogEditTimerBinding.inflate(activity.layoutInflater)
private val textColor = activity.getProperTextColor()
@ -70,7 +70,7 @@ class EditTimerDialog(val activity: SimpleActivity, val timer: Timer, val callba
timer.label = binding.editTimer.value
activity.timerHelper.insertOrUpdateTimer(timer) {
activity.config.timerLastConfig = timer
callback()
callback(it)
alertDialog.dismiss()
}
}

View file

@ -0,0 +1,55 @@
package com.simplemobiletools.clock.dialogs
import android.view.ViewGroup
import android.widget.RadioGroup
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.clock.databinding.DialogSelectAlarmBinding
import com.simplemobiletools.clock.databinding.ItemRadioButtonBinding
import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.*
class SelectAlarmDialog(
val activity: BaseSimpleActivity,
val alarms: List<Alarm>,
val titleResId: Int,
val onAlarmPicked: (alarm: Alarm?) -> Unit
) {
private val binding = DialogSelectAlarmBinding.inflate(activity.layoutInflater, null, false)
private var dialog: AlertDialog? = null
init {
addYourAlarms()
activity.getAlertDialogBuilder()
.setOnDismissListener { onAlarmPicked(null) }
.setPositiveButton(com.simplemobiletools.commons.R.string.ok) { _, _ -> dialogConfirmed() }
.setNegativeButton(com.simplemobiletools.commons.R.string.cancel, null)
.apply {
activity.setupDialogStuff(binding.root, this, titleResId) { alertDialog ->
dialog = alertDialog
}
}
}
private fun addYourAlarms() {
binding.dialogSelectAlarmRadio.removeAllViews()
alarms.forEach { addAlarm(it) }
}
private fun addAlarm(alarm: Alarm) {
val radioButton = ItemRadioButtonBinding.inflate(activity.layoutInflater).root.apply {
text = alarm.label
isChecked = false
id = alarm.id
setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())
}
binding.dialogSelectAlarmRadio.addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
}
private fun dialogConfirmed() {
val checkedId = binding.dialogSelectAlarmRadio.checkedRadioButtonId
onAlarmPicked(alarms.firstOrNull { it.id == checkedId })
}
}

View file

@ -15,6 +15,7 @@ import com.simplemobiletools.clock.extensions.*
import com.simplemobiletools.clock.helpers.*
import com.simplemobiletools.clock.interfaces.ToggleAlarmInterface
import com.simplemobiletools.clock.models.Alarm
import com.simplemobiletools.clock.models.AlarmEvent
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.extensions.toast
@ -22,6 +23,9 @@ import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.helpers.SORT_BY_DATE_CREATED
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.AlarmSound
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
class AlarmFragment : Fragment(), ToggleAlarmInterface {
private var alarms = ArrayList<Alarm>()
@ -34,6 +38,16 @@ class AlarmFragment : Fragment(), ToggleAlarmInterface {
return binding.root
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
EventBus.getDefault().register(this)
}
override fun onDestroy() {
EventBus.getDefault().unregister(this)
super.onDestroy()
}
override fun onResume() {
super.onResume()
setupViews()
@ -73,14 +87,22 @@ class AlarmFragment : Fragment(), ToggleAlarmInterface {
}
context?.getEnabledAlarms { enabledAlarms ->
if (enabledAlarms.isNullOrEmpty()) {
val removedAlarms = mutableListOf<Alarm>()
alarms.forEach {
if (it.days == TODAY_BIT && it.isEnabled && it.timeInMinutes <= getCurrentDayMinutes()) {
it.isEnabled = false
ensureBackgroundThread {
context?.dbHelper?.updateAlarmEnabledState(it.id, false)
if (it.oneShot) {
it.isEnabled = false
context?.dbHelper?.deleteAlarms(arrayListOf(it))
removedAlarms.add(it)
} else {
context?.dbHelper?.updateAlarmEnabledState(it.id, false)
}
}
}
}
alarms.removeAll(removedAlarms)
}
}
@ -117,6 +139,10 @@ class AlarmFragment : Fragment(), ToggleAlarmInterface {
val alarm = alarms.firstOrNull { it.id == id } ?: return@handleFullScreenNotificationsPermission
alarm.isEnabled = isEnabled
checkAlarmState(alarm)
if (!alarm.isEnabled && alarm.oneShot) {
requireContext().dbHelper.deleteAlarms(arrayListOf(alarm))
setupAlarms()
}
} else {
requireActivity().toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
}
@ -139,4 +165,9 @@ class AlarmFragment : Fragment(), ToggleAlarmInterface {
fun updateAlarmSound(alarmSound: AlarmSound) {
currentEditAlarmDialog?.updateSelectedAlarmSound(alarmSound)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: AlarmEvent.Refresh) {
setupAlarms()
}
}

View file

@ -2,7 +2,7 @@ package com.simplemobiletools.clock.helpers
import com.simplemobiletools.clock.extensions.isBitSet
import com.simplemobiletools.clock.models.MyTimeZone
import com.simplemobiletools.commons.extensions.addBit
import com.simplemobiletools.commons.helpers.*
import java.util.Calendar
import java.util.Date
import java.util.TimeZone
@ -74,6 +74,16 @@ const val TOMORROW_BIT = -2
const val STOPWATCH_SHORTCUT_ID = "stopwatch_shortcut_id"
const val STOPWATCH_TOGGLE_ACTION = "com.simplemobiletools.clock.TOGGLE_STOPWATCH"
val DAY_BIT_MAP = mapOf(
Calendar.SUNDAY to SUNDAY_BIT,
Calendar.MONDAY to MONDAY_BIT,
Calendar.TUESDAY to TUESDAY_BIT,
Calendar.WEDNESDAY to WEDNESDAY_BIT,
Calendar.THURSDAY to THURSDAY_BIT,
Calendar.FRIDAY to FRIDAY_BIT,
Calendar.SATURDAY to SATURDAY_BIT,
)
fun getDefaultTimeZoneTitle(id: Int) = getAllTimeZones().firstOrNull { it.id == id }?.title ?: ""
fun getPassedSeconds(): Int {
@ -105,6 +115,16 @@ fun getTomorrowBit(): Int {
return 2.0.pow(dayOfWeek).toInt()
}
fun getTodayBit(): Int {
val calendar = Calendar.getInstance()
val dayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7
return 2.0.pow(dayOfWeek).toInt()
}
fun getBitForCalendarDay(day: Int): Int {
return DAY_BIT_MAP[day] ?: 0
}
fun getCurrentDayMinutes(): Int {
val calendar = Calendar.getInstance()
return calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE)

View file

@ -23,11 +23,12 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
private val COL_SOUND_TITLE = "sound_title"
private val COL_SOUND_URI = "sound_uri"
private val COL_LABEL = "label"
private val COL_ONE_SHOT = "one_shot"
private val mDb = writableDatabase
companion object {
private const val DB_VERSION = 1
private const val DB_VERSION = 2
const val DB_NAME = "alarms.db"
var dbInstance: DBHelper? = null
@ -47,7 +48,11 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
insertInitialAlarms(db)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
if (oldVersion == 1 && newVersion > oldVersion) {
db.execSQL("ALTER TABLE $ALARMS_TABLE_NAME ADD COLUMN $COL_ONE_SHOT INTEGER NOT NULL DEFAULT 0")
}
}
private fun insertInitialAlarms(db: SQLiteDatabase) {
val weekDays = MONDAY_BIT or TUESDAY_BIT or WEDNESDAY_BIT or THURSDAY_BIT or FRIDAY_BIT
@ -102,6 +107,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
put(COL_SOUND_TITLE, alarm.soundTitle)
put(COL_SOUND_URI, alarm.soundUri)
put(COL_LABEL, alarm.label)
put(COL_ONE_SHOT, alarm.oneShot)
}
}
@ -109,7 +115,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
fun getAlarms(): ArrayList<Alarm> {
val alarms = ArrayList<Alarm>()
val cols = arrayOf(COL_ID, COL_TIME_IN_MINUTES, COL_DAYS, COL_IS_ENABLED, COL_VIBRATE, COL_SOUND_TITLE, COL_SOUND_URI, COL_LABEL)
val cols = arrayOf(COL_ID, COL_TIME_IN_MINUTES, COL_DAYS, COL_IS_ENABLED, COL_VIBRATE, COL_SOUND_TITLE, COL_SOUND_URI, COL_LABEL, COL_ONE_SHOT)
var cursor: Cursor? = null
try {
cursor = mDb.query(ALARMS_TABLE_NAME, cols, null, null, null, null, null)
@ -124,8 +130,9 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
val soundTitle = cursor.getStringValue(COL_SOUND_TITLE)
val soundUri = cursor.getStringValue(COL_SOUND_URI)
val label = cursor.getStringValue(COL_LABEL)
val oneShot = cursor.getIntValue(COL_ONE_SHOT) == 1
val alarm = Alarm(id, timeInMinutes, days, isEnabled, vibrate, soundTitle, soundUri, label)
val alarm = Alarm(id, timeInMinutes, days, isEnabled, vibrate, soundTitle, soundUri, label, oneShot)
alarms.add(alarm)
} catch (e: Exception) {
continue

View file

@ -15,15 +15,27 @@ class TimerHelper(val context: Context) {
}
fun getTimer(timerId: Int, callback: (timer: Timer) -> Unit) {
ensureBackgroundThread {
callback.invoke(timerDao.getTimer(timerId)!!)
}
}
fun tryGetTimer(timerId: Int, callback: (timer: Timer?) -> Unit) {
ensureBackgroundThread {
callback.invoke(timerDao.getTimer(timerId))
}
}
fun insertOrUpdateTimer(timer: Timer, callback: () -> Unit = {}) {
fun findTimers(seconds: Int, label: String, callback: (timers: List<Timer>) -> Unit) {
ensureBackgroundThread {
timerDao.insertOrUpdateTimer(timer)
callback.invoke()
callback.invoke(timerDao.findTimers(seconds, label))
}
}
fun insertOrUpdateTimer(timer: Timer, callback: (id: Long) -> Unit = {}) {
ensureBackgroundThread {
val id = timerDao.insertOrUpdateTimer(timer)
callback.invoke(id)
}
}

View file

@ -10,7 +10,10 @@ interface TimerDao {
fun getTimers(): List<Timer>
@Query("SELECT * FROM timers WHERE id=:id")
fun getTimer(id: Int): Timer
fun getTimer(id: Int): Timer?
@Query("SELECT * FROM timers WHERE seconds=:seconds AND label=:label")
fun findTimers(seconds: Int, label: String): List<Timer>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdateTimer(timer: Timer): Long

View file

@ -8,5 +8,6 @@ data class Alarm(
var vibrate: Boolean,
var soundTitle: String,
var soundUri: String,
var label: String
var label: String,
var oneShot: Boolean = false
)

View file

@ -0,0 +1,5 @@
package com.simplemobiletools.clock.models
sealed interface AlarmEvent {
object Refresh : AlarmEvent
}

View file

@ -14,4 +14,5 @@ data class Timer(
var label: String,
var createdAt: Long,
var channelId: String? = null,
var oneShot: Boolean = false
)

View file

@ -27,7 +27,12 @@ class DismissAlarmReceiver : BroadcastReceiver() {
context.cancelAlarmClock(alarm)
scheduleNextAlarm(alarm, context)
if (alarm.days < 0) {
context.dbHelper.updateAlarmEnabledState(alarm.id, false)
if (alarm.oneShot) {
alarm.isEnabled = false
context.dbHelper.deleteAlarms(arrayListOf(alarm))
} else {
context.dbHelper.updateAlarmEnabledState(alarm.id, false)
}
context.updateWidgets()
}
}

View file

@ -21,7 +21,12 @@ class HideAlarmReceiver : BroadcastReceiver() {
ensureBackgroundThread {
val alarm = context.dbHelper.getAlarmWithId(id)
if (alarm != null && alarm.days < 0) {
context.dbHelper.updateAlarmEnabledState(alarm.id, false)
if (alarm.oneShot) {
alarm.isEnabled = false
context.dbHelper.deleteAlarms(arrayListOf(alarm))
} else {
context.dbHelper.updateAlarmEnabledState(alarm.id, false)
}
context.updateWidgets()
}
}

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialog_select_alarm_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/dialog_select_alarm_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioGroup
android:id="@+id/dialog_select_alarm_radio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/activity_margin"
android:paddingTop="@dimen/medium_margin"
android:paddingEnd="@dimen/activity_margin" />
</LinearLayout>
</ScrollView>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<com.simplemobiletools.commons.views.MyCompatRadioButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_radio_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin"/>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">ساعة تناظرية</string>
<string name="digital_clock">ساعة رقمية</string>
<string name="alarm_dismissed">تم تجاهل المنبه</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">إنذار غفوة من قبل %s</string>
<string name="no_alarms_found">لم يتم العثور على منبهات</string>
<string name="add_alarm">Add alarm</string>
@ -56,4 +59,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -22,6 +22,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Аналагавы гадзіннік</string>
<string name="digital_clock">Лічбавы гадзіннік</string>
<string name="alarm_dismissed">Будзільнік адхілены</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Будзільнік адкладзены на %s</string>
<string name="no_alarms_found">Будзільнікі не знойдзены</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Аналогов часовник</string>
<string name="digital_clock">Цифров часовник</string>
<string name="alarm_dismissed">Алармата е отхвърлена</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Алармата е отложена от %s</string>
<string name="no_alarms_found">Няма намерени аларми</string>
<string name="add_alarm">Add alarm</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Rellotge analògic</string>
<string name="digital_clock">Rellotge digital</string>
<string name="alarm_dismissed">Alarma descartada</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarma posposada %s</string>
<string name="no_alarms_found">No s\'ha trobat cap alarma</string>
<string name="add_alarm">Add alarm</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analogové hodiny</string>
<string name="digital_clock">Digitální hodiny</string>
<string name="alarm_dismissed">Budík zrušen</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Budík odložen na %s</string>
<string name="no_alarms_found">Nenalezeny žádné budíky</string>
<string name="add_alarm">Přidat budík</string>
@ -53,4 +56,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -22,6 +22,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analoge Uhr</string>
<string name="digital_clock">Digitale Uhr</string>
<string name="alarm_dismissed">Alarm unterdrückt</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm zurückgestellt um %s</string>
<string name="no_alarms_found">Keine Alarme gefunden</string>
<string name="add_alarm">Alarm hinzufügen</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Αναλογικό Ρολόι</string>
<string name="digital_clock">Ψηφιακό Ρολόι</string>
<string name="alarm_dismissed">Η αφύπνιση απορρίφθηκε</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Η αφύπνιση σε αναμονή από %s</string>
<string name="no_alarms_found">Δεν βρέθηκαν αφυπνίσεις</string>
<string name="add_alarm">Προσθήκη αφύπνισης</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Reloj analógico</string>
<string name="digital_clock">Reloj digital</string>
<string name="alarm_dismissed">Alarma desechada</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Repetir alarma en %s</string>
<string name="no_alarms_found">No se encontraron alarmas</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Sihverplaadiga kell</string>
<string name="digital_clock">Numbritega kell</string>
<string name="alarm_dismissed">Äratus on tühistatud</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">%s lükkas äratuse edasi</string>
<string name="no_alarms_found">Äratusi ei leidu</string>
<string name="add_alarm">Lisa äratus</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Erloju analogikoa</string>
<string name="digital_clock">Erloju digitala</string>
<string name="alarm_dismissed">Alarma baztertu da</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Jo alarma berriro %s barru</string>
<string name="no_alarms_found">Ez da alarmarik aurkitu</string>
<string name="add_alarm">Gehitu alarma</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analoginen kello</string>
<string name="digital_clock">Digitaalinen kello</string>
<string name="alarm_dismissed">Herätys lopetettiin</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Herätys torkutettiin %s</string>
<string name="no_alarms_found">Herätyksiä ei ole</string>
<string name="add_alarm">Lisää herätys</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Horloge analogique</string>
<string name="digital_clock">Horloge numérique</string>
<string name="alarm_dismissed">Alarme ignorée</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarme ignorée par %s</string>
<string name="no_alarms_found">Aucune alarme trouvée</string>
<string name="add_alarm">Ajouter une alarme</string>
@ -53,4 +56,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Reloxo analóxico</string>
<string name="digital_clock">Reloxo dixital</string>
<string name="alarm_dismissed">Alarma descartada</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarma posposta por %s</string>
<string name="no_alarms_found">Non se atoparon alarmas</string>
<string name="add_alarm">Engadir alarma</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analogni sat</string>
<string name="digital_clock">Digitalni sat</string>
<string name="alarm_dismissed">Alarm odbačen</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm odgođen za %s</string>
<string name="no_alarms_found">Nema alarma</string>
<string name="add_alarm">Dodaj alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analóg óra</string>
<string name="digital_clock">Digitális óra</string>
<string name="alarm_dismissed">Riasztás eltüntetve</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Az ébresztés ennyivel elhalasztva: %s</string>
<string name="no_alarms_found">Nincsenek riasztások</string>
<string name="add_alarm">Riasztás hozzáadása</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Jam analog</string>
<string name="digital_clock">Jam digital</string>
<string name="alarm_dismissed">Alarm diabaikan</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm ditunda selama %s</string>
<string name="no_alarms_found">Tidak ada alarm yang ditemukan</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Orologio analogico</string>
<string name="digital_clock">Orologio digitale</string>
<string name="alarm_dismissed">Allarme disattivato</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Allarme posticipato da %s</string>
<string name="no_alarms_found">Nessun allarme trovato</string>
<string name="add_alarm">Aggiungi allarme</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">שעון אנלוגי</string>
<string name="digital_clock">שעון דיגיטלי</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">アナログ時計</string>
<string name="digital_clock">デジタル時計</string>
<string name="alarm_dismissed">アラームが破棄されました</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">アラームが見つかりません</string>
<string name="add_alarm">アラームを追加</string>

View file

@ -22,6 +22,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">അനലോഗ് ക്ലോക്ക്</string>
<string name="digital_clock">ഡിജിറ്റൽ ക്ലോക്ക്</string>
<string name="alarm_dismissed">അലാറം ഒഴിവാക്കി</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">അലാറം %s സ്‌നൂസ് ചെയ്‌തു</string>
<string name="no_alarms_found">അലാറങ്ങളൊന്നും കണ്ടെത്തിയില്ല</string>
<string name="add_alarm">പുതിയ അലാറം ചേർക്കുക</string>

View file

@ -25,6 +25,9 @@
<string name="analogue_clock">တိုင်ကပ်နာရီ</string>
<string name="digital_clock">ဒီဂျစ်တယ်နာရီ</string>
<string name="alarm_dismissed">နှိုးစက်အားဖယ်ရှားပြီး</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">နှိုးစက်အားရပ်တန့်ပြီး %s</string>
<string name="no_alarms_found">နှိုးစက်မရှိပါ</string>
<string name="add_alarm">နှိုးစက်ထည့်မည်</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analog klokke</string>
<string name="digital_clock">Digital klokke</string>
<string name="alarm_dismissed">Alarm slått av</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm - Slumre %s</string>
<string name="no_alarms_found">Ingen alarmer funnet</string>
<string name="add_alarm">Add alarm</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analoge klok</string>
<string name="digital_clock">Digitale klok</string>
<string name="alarm_dismissed">Wekker uitgezet</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Wekker uitgesteld met %s</string>
<string name="no_alarms_found">Geen wekkers</string>
<string name="add_alarm">Wekker toevoegen</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -24,6 +24,9 @@
<string name="analogue_clock">اینولوگ گھڑی</string>
<string name="digital_clock">ڈیجیٹل گھڑی</string>
<string name="alarm_dismissed">الارم بند کیتا گیا</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">؜%s الارم نوں فیر بدلیا گیا</string>
<string name="no_alarms_found">کوئی الارم نہیں لبھے</string>
<string name="add_alarm">نواں الارم پایو</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Zegar analogowy</string>
<string name="digital_clock">Zegar cyfrowy</string>
<string name="alarm_dismissed">Alarm odrzucony</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm odłożony o %s</string>
<string name="no_alarms_found">Nie znaleziono alarmów</string>
<string name="add_alarm">Dodaj alarm</string>
@ -54,4 +57,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Relógio analógico</string>
<string name="digital_clock">Relógio digital</string>
<string name="alarm_dismissed">Alarme descartado</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarme adiado por %s</string>
<string name="no_alarms_found">Nenhum alarme encontrado</string>
<string name="add_alarm">Adicionar alarme</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Relógio analógico</string>
<string name="digital_clock">Relógio digital</string>
<string name="alarm_dismissed">Alarme descartado</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarme adiado por %s</string>
<string name="no_alarms_found">Nenhum alarme encontrado</string>
<string name="add_alarm">Adicionar alarme</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Ceas analogic</string>
<string name="digital_clock">Ceas digital</string>
<string name="alarm_dismissed">Alarmă ignorată</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarma a fost amânată cu %s</string>
<string name="no_alarms_found">Nu au fost găsite alarme</string>
<string name="add_alarm">Adaugă alarmă</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Аналоговые часы</string>
<string name="digital_clock">Цифровые часы</string>
<string name="alarm_dismissed">Будильник отключён</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Будильник отложен на %s</string>
<string name="no_alarms_found">Будильники отсутствуют</string>
<string name="add_alarm">Добавить будильник</string>
@ -54,4 +57,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analógové hodiny</string>
<string name="digital_clock">Digitálne hodiny</string>
<string name="alarm_dismissed">Budík bol zastavený</string>
<string name="select_timer_to_dismiss">Zvoľte časovač na zrušenie</string>
<string name="select_alarm_to_dismiss">Zvoľte budík na zrušenie</string>
<string name="alarm_created">Budík vytvorený</string>
<string name="alarm_snoozed">Budík bol preložený o %s</string>
<string name="no_alarms_found">Nenašli sa žiadne budíky</string>
<string name="add_alarm">Pridať budík</string>
@ -53,4 +56,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analogna ura</string>
<string name="digital_clock">Digitalna ura</string>
<string name="alarm_dismissed">Prekinjen alarm</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm je odložen s strani %s</string>
<string name="no_alarms_found">Ni alarmov</string>
<string name="add_alarm">Dodajte alarm</string>

View file

@ -24,6 +24,9 @@
<string name="alarm_snoozed">Аларм је одложен %s</string>
<string name="digital_clock">Дигитални сат</string>
<string name="alarm_dismissed">Аларм одбачен</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="no_alarms_found">Није пронађен ниједан аларм</string>
<string name="add_alarm">Додајте аларм</string>
<string name="no_timers_found">Тајмери нису пронађени</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analog klocka</string>
<string name="digital_clock">Digital klocka</string>
<string name="alarm_dismissed">Alarmet har avvisats</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarmet snoozar %s</string>
<string name="no_alarms_found">Inga alarm hittades</string>
<string name="add_alarm">Lägg till alarm</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analog saat</string>
<string name="digital_clock">Dijital saat</string>
<string name="alarm_dismissed">Alarm kapatıldı</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm %s ertelendi</string>
<string name="no_alarms_found">Alarm bulunamadı</string>
<string name="add_alarm">Alarm ekle</string>
@ -52,4 +55,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Аналоговий годинник</string>
<string name="digital_clock">Цифровий годинник</string>
<string name="alarm_dismissed">Будильник вимкнено</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Будильник відкладено %s</string>
<string name="no_alarms_found">Немає будильників</string>
<string name="add_alarm">Додати будильник</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">指针式时钟</string>
<string name="digital_clock">数字时钟</string>
<string name="alarm_dismissed">闹钟已停止</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">闹钟延后了 %s</string>
<string name="no_alarms_found">未找到闹铃</string>
<string name="add_alarm">添加闹钟</string>
@ -51,4 +54,4 @@
Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
-->
</resources>
</resources>

View file

@ -22,6 +22,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>

View file

@ -23,6 +23,9 @@
<string name="analogue_clock">Analogue clock</string>
<string name="digital_clock">Digital clock</string>
<string name="alarm_dismissed">Alarm dismissed</string>
<string name="select_timer_to_dismiss">Select timer to dismiss</string>
<string name="select_alarm_to_dismiss">Select alarm to dismiss</string>
<string name="alarm_created">Alarm created</string>
<string name="alarm_snoozed">Alarm snoozed by %s</string>
<string name="no_alarms_found">No alarms found</string>
<string name="add_alarm">Add alarm</string>