Skip to content

Commit

Permalink
Merge pull request #246 from SuhasDissa/new-alarm-layout
Browse files Browse the repository at this point in the history
feat: New Alarm Layout
  • Loading branch information
SuhasDissa authored Dec 15, 2023
2 parents 4ce72b4 + 9415769 commit f864638
Show file tree
Hide file tree
Showing 16 changed files with 889 additions and 312 deletions.
136 changes: 136 additions & 0 deletions app/schemas/com.bnyro.clock.db.AppDatabase/6.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"formatVersion": 1,
"database": {
"version": 6,
"identityHash": "7a3e746162031505f993deece80a8c46",
"entities": [
{
"tableName": "timeZones",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `displayName` TEXT NOT NULL, `offset` INTEGER NOT NULL, PRIMARY KEY(`name`))",
"fields": [
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "offset",
"columnName": "offset",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"name"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "alarms",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `time` INTEGER NOT NULL, `label` TEXT, `enabled` INTEGER NOT NULL, `days` TEXT NOT NULL, `vibrate` INTEGER NOT NULL, `soundName` TEXT, `soundUri` TEXT, `repeat` INTEGER NOT NULL DEFAULT 1, `snoozeEnabled` INTEGER NOT NULL DEFAULT 1, `snoozeMinutes` INTEGER NOT NULL DEFAULT 10, `soundEnabled` INTEGER NOT NULL DEFAULT 1)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "time",
"columnName": "time",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "label",
"columnName": "label",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "enabled",
"columnName": "enabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "days",
"columnName": "days",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "vibrate",
"columnName": "vibrate",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "soundName",
"columnName": "soundName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "soundUri",
"columnName": "soundUri",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "repeat",
"columnName": "repeat",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "1"
},
{
"fieldPath": "snoozeEnabled",
"columnName": "snoozeEnabled",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "1"
},
{
"fieldPath": "snoozeMinutes",
"columnName": "snoozeMinutes",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "10"
},
{
"fieldPath": "soundEnabled",
"columnName": "soundEnabled",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "1"
}
],
"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, '7a3e746162031505f993deece80a8c46')"
]
}
}
5 changes: 3 additions & 2 deletions app/src/main/java/com/bnyro/clock/db/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import com.bnyro.clock.obj.TimeZone

@Database(
entities = [TimeZone::class, Alarm::class],
version = 5,
version = 6,
autoMigrations = [
AutoMigration(
from = 2,
to = 3,
spec = AppDatabase.RemoveSoundColumnAutoMigration::class
),
AutoMigration(from = 4, to = 5)
AutoMigration(from = 4, to = 5),
AutoMigration(from = 5, to = 6)
]
)
@TypeConverters(Converters::class)
Expand Down
21 changes: 19 additions & 2 deletions app/src/main/java/com/bnyro/clock/obj/Alarm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ package com.bnyro.clock.obj

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey

/**
* @param days The days of the week to ring the alarm. Sunday-0, Monday-1 ,... ,Saturday-6
* @param snoozeMinutes How long the snooze should last in minutes (default 10).
*/
@Entity(tableName = "alarms")
data class Alarm(
@PrimaryKey(autoGenerate = true) var id: Long = 0,
Expand All @@ -14,5 +19,17 @@ data class Alarm(
var vibrate: Boolean = false,
var soundName: String? = null,
var soundUri: String? = null,
@ColumnInfo(defaultValue = "1") var repeat: Boolean = false
)
@ColumnInfo(defaultValue = "1") var repeat: Boolean = false,
@ColumnInfo(defaultValue = "1") var snoozeEnabled: Boolean = true,
@ColumnInfo(defaultValue = "10") var snoozeMinutes: Int = 10,
@ColumnInfo(defaultValue = "1") var soundEnabled: Boolean = true
) {
@Ignore
val isWeekends: Boolean = days == listOf(0, 6)

@Ignore
val isWeekdays: Boolean = days == listOf(1, 2, 3, 4, 5)

@Ignore
val isRepeatEveryday: Boolean = days.size == 7
}
34 changes: 18 additions & 16 deletions app/src/main/java/com/bnyro/clock/services/AlarmService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,24 @@ class AlarmService : Service() {
private fun play(alarm: Alarm) {
// stop() checks to see if we are already playing.
stop()
val alert: Uri? = alarm.soundUri?.toUri() ?: RingtoneManager.getDefaultUri(
RingtoneManager.TYPE_ALARM
)
mediaPlayer = MediaPlayer()
mediaPlayer!!.setOnErrorListener { mp, _, _ ->
Log.e("Media Player", "Error occurred while playing audio.")
mp.stop()
mp.release()
mediaPlayer = null
true
}
try {
mediaPlayer!!.setDataSource(this, alert!!)
startAlarm(mediaPlayer!!)
} catch (e: Exception) {
Log.e("Failed to play ringtone", e.message, e)
if (alarm.soundEnabled) {
val alert: Uri? = alarm.soundUri?.toUri() ?: RingtoneManager.getDefaultUri(
RingtoneManager.TYPE_ALARM
)
mediaPlayer = MediaPlayer()
mediaPlayer!!.setOnErrorListener { mp, _, _ ->
Log.e("Media Player", "Error occurred while playing audio.")
mp.stop()
mp.release()
mediaPlayer = null
true
}
try {
mediaPlayer!!.setDataSource(this, alert!!)
startAlarm(mediaPlayer!!)
} catch (e: Exception) {
Log.e("Failed to play ringtone", e.message, e)
}
}

/* Start the vibrator after everything is ok with the media player */
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/bnyro/clock/ui/AlarmActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class AlarmActivity : ComponentActivity() {
AlarmAlertScreen(
onDismiss = this@AlarmActivity::dismiss,
onSnooze = this@AlarmActivity::snooze,
label = alarm.label
label = alarm.label,
snoozeEnabled = alarm.snoozeEnabled
)
}

Expand Down
146 changes: 146 additions & 0 deletions app/src/main/java/com/bnyro/clock/ui/common/SwitchWithDivider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package com.bnyro.clock.ui.common

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Divider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

@Composable
fun SwitchWithDivider(
title: String,
description: String? = null,
icon: ImageVector? = null,
isChecked: Boolean = true,
onClick: (() -> Unit) = {},
onChecked: (Boolean) -> Unit = {}
) {
Surface(
modifier = Modifier.clickable(
onClick = onClick
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp, 16.dp)
.height(IntrinsicSize.Min),
verticalAlignment = Alignment.CenterVertically
) {
icon?.let {
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier
.padding(start = 8.dp, end = 16.dp)
.size(24.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Column(
modifier = Modifier.weight(1f)
) {
Text(text = title, style = MaterialTheme.typography.titleLarge)
if (!description.isNullOrEmpty()) {
Text(
text = description,
style = MaterialTheme.typography.bodyMedium
)
}
}
Divider(
modifier = Modifier
.height(32.dp)
.padding(horizontal = 8.dp)
.width(1.dp)
.align(Alignment.CenterVertically),
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
)
Switch(
checked = isChecked,
onCheckedChange = onChecked,
modifier = Modifier
.padding(horizontal = 6.dp)
.semantics {
contentDescription = title
}
)
}
}
}

@Composable
fun SwitchItem(
title: String,
description: String? = null,
icon: ImageVector? = null,
isChecked: Boolean = true,
onClick: (Boolean) -> Unit
) {
Surface(
modifier = Modifier.toggleable(
value = isChecked,
onValueChange = onClick
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp, 16.dp)
.padding(start = if (icon == null) 12.dp else 0.dp),
verticalAlignment = Alignment.CenterVertically
) {
icon?.let {
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier
.padding(start = 8.dp, end = 16.dp)
.size(24.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Column(
modifier = Modifier.weight(1f)
) {
Text(text = title, style = MaterialTheme.typography.titleLarge)
if (!description.isNullOrEmpty()) {
Text(
text = description,
style = MaterialTheme.typography.bodyMedium
)
}
}
Switch(
checked = isChecked,
onCheckedChange = null,
modifier = Modifier.padding(start = 20.dp, end = 6.dp)
)
}
}
}

@Preview
@Composable
fun SwitchWithDividerPreview() {
SwitchWithDivider(title = "My setting", description = "My description")
}
Loading

0 comments on commit f864638

Please sign in to comment.