Skip to content

Commit

Permalink
feat(wear): add bedtime mode and fix alarms
Browse files Browse the repository at this point in the history
  • Loading branch information
Turtlepaw committed Jan 26, 2024
1 parent 57eb39a commit c2114b6
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 46 deletions.
1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions wear/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ android {
applicationId = "com.turtlepaw.sleeptools"
minSdk = 30
targetSdk = 33
versionCode = 2
versionCode = 5
versionName = "1.0"
vectorDrawables {
useSupportLibrary = true
}

}

buildTypes {
Expand Down
Binary file modified wear/release/wear-release.aab
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.content.SharedPreferences
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
Expand Down Expand Up @@ -82,6 +83,7 @@ import com.turtlepaw.sleeptools.presentation.pages.WearSettings
import com.turtlepaw.sleeptools.presentation.theme.SleepTheme
import com.turtlepaw.sleeptools.utils.AlarmType
import com.turtlepaw.sleeptools.utils.AlarmsManager
import com.turtlepaw.sleeptools.utils.BedtimeModeManager
import com.turtlepaw.sleeptools.utils.Settings
import com.turtlepaw.sleeptools.utils.TimeManager
import kotlinx.coroutines.delay
Expand Down Expand Up @@ -132,6 +134,10 @@ fun WearPages(sharedPreferences: SharedPreferences, context: Context){
var useAlerts by remember { mutableStateOf(useAlertsBool) }
// Fetches the next alarm from android's alarm manager
val nextAlarm = alarmManager.fetchAlarms(context);
// Uses Settings.Globals to get bedtime mode
val bedtimeModeManager = BedtimeModeManager()
val isBedtimeModeEnabled = bedtimeModeManager.isBedtimeModeEnabled(context, sharedPreferences)
val lastBedtime = bedtimeModeManager.getLastBedtime(sharedPreferences)
// Parses the wake time and decides if it should use
// user defined or system defined
var wakeTime = timeManager.getWakeTime(
Expand All @@ -140,7 +146,7 @@ fun WearPages(sharedPreferences: SharedPreferences, context: Context){
wakeTimeString,
Settings.WAKE_TIME.getDefaultAsLocalTime()
);
val userWakeTime = timeManager.parseTime(wakeTimeString, Settings.WAKE_TIME.getDefaultAsLocalTime());
var userWakeTime = timeManager.parseTime(wakeTimeString, Settings.WAKE_TIME.getDefaultAsLocalTime());

SwipeDismissableNavHost(
navController = navController,
Expand All @@ -153,7 +159,8 @@ fun WearPages(sharedPreferences: SharedPreferences, context: Context){
},
wakeTime,
nextAlarm = nextAlarm ?: wakeTime.first,
timeManager
timeManager,
lastBedtime
)
}
composable(Routes.SETTINGS.getRoute()) {
Expand Down Expand Up @@ -194,6 +201,7 @@ fun WearPages(sharedPreferences: SharedPreferences, context: Context){
if(wakeTime.second === AlarmType.USER_DEFINED)
wakeTime = Pair(value, AlarmType.USER_DEFINED);

userWakeTime = value
val editor = sharedPreferences.edit()
editor.putString("wake_time", value.toString())
editor.apply()
Expand All @@ -204,7 +212,7 @@ fun WearPages(sharedPreferences: SharedPreferences, context: Context){
}
}

@Preview(device = WearDevices.LARGE_ROUND, showSystemUi = true)
@Preview(device = WearDevices.SMALL_ROUND, showSystemUi = true)
@Composable
fun DefaultPreview() {
WearHome(
Expand All @@ -214,11 +222,12 @@ fun DefaultPreview() {
AlarmType.SYSTEM_ALARM
),
nextAlarm = LocalTime.of(7, 30),
timeManager = TimeManager()
timeManager = TimeManager(),
null
)
}

@Preview(device = WearDevices.LARGE_ROUND, showSystemUi = true)
@Preview(device = WearDevices.SMALL_ROUND, showSystemUi = true)
@Composable
fun SettingsPreview() {
WearSettings(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
Expand All @@ -38,6 +39,7 @@ import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material.scrollAway
import androidx.wear.tooling.preview.devices.WearDevices
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.rotaryinput.rotaryWithScroll
import com.turtlepaw.sleeptools.R
Expand All @@ -56,7 +58,8 @@ fun WearHome(
navigate: (route: String) -> Unit,
wakeTime: Pair<LocalTime, AlarmType>,
nextAlarm: LocalTime,
timeManager: TimeManager
timeManager: TimeManager,
lastBedtime: LocalTime?
) {
SleepTheme {
val focusRequester = rememberActiveFocusRequester()
Expand Down Expand Up @@ -152,21 +155,23 @@ fun WearHome(
modifier = Modifier.padding(top = 4.dp)
)
}
item {
Text(
text = "Tip",
textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 4.dp),
color = Color(0xFFE4C6FF)
)
}
item {
Text(
text = "You should go to bed at 1:35 AM to be consistent",
textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 4.dp),
//color = Color(0xFF939AA3)
)
if(lastBedtime != null){
item {
Text(
text = "Tip",
textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 4.dp),
color = Color(0xFFE4C6FF)
)
}
item {
Text(
text = "You should go to bed at ${formatter.format(lastBedtime)} to be consistent",
textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 4.dp),
//color = Color(0xFF939AA3)
)
}
}
item {
Spacer(modifier = Modifier.padding(vertical = 5.dp))
Expand Down Expand Up @@ -197,7 +202,7 @@ fun WearHome(
}
item {
Text(
text = "Made with ♥️ by turtlepaw",
text = "Made with 💤 by turtlepaw",
color = Color.White,
textAlign = TextAlign.Center,
modifier = Modifier
Expand All @@ -216,4 +221,19 @@ fun WearHome(
}
}
}
}

@Preview(device = WearDevices.SMALL_ROUND, showSystemUi = true)
@Composable
fun DefaultPreview() {
WearHome(
navigate = {},
wakeTime = Pair(
LocalTime.of(10, 30),
AlarmType.SYSTEM_ALARM
),
nextAlarm = LocalTime.of(7, 30),
timeManager = TimeManager(),
null
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.turtlepaw.sleeptools.presentation.pages

import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
Expand All @@ -18,6 +19,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
Expand All @@ -34,12 +36,14 @@ import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material.ToggleChip
import androidx.wear.compose.material.ToggleChipDefaults
import androidx.wear.compose.material.scrollAway
import androidx.wear.tooling.preview.devices.WearDevices
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.rotaryinput.rotaryWithScroll
import com.turtlepaw.sleeptools.R
import com.turtlepaw.sleeptools.presentation.components.ItemsListWithModifier
import com.turtlepaw.sleeptools.presentation.theme.SleepTheme
import com.turtlepaw.sleeptools.utils.AlarmType
import com.turtlepaw.sleeptools.utils.Settings
import java.time.LocalTime
import java.time.format.DateTimeFormatter

Expand Down Expand Up @@ -114,7 +118,7 @@ fun WearSettings(
.padding(bottom = 8.dp)
)
Text(
text = "Wake Time: ${userWakeTime.format(formatter)}",
text = "Wake Up ${userWakeTime.format(formatter)}",
color = Color.Black
)
}
Expand All @@ -133,7 +137,7 @@ fun WearSettings(
setAlarm(isEnabled)
},
label = {
Text("Use Alarm", maxLines = 1, overflow = TextOverflow.Ellipsis)
Text("Alarm", maxLines = 1, overflow = TextOverflow.Ellipsis)
},
appIcon = {
Icon(
Expand Down Expand Up @@ -173,7 +177,7 @@ fun WearSettings(
setAlerts(isEnabled)
},
label = {
Text("Notifications", maxLines = 1, overflow = TextOverflow.Ellipsis)
Text("Alerts", maxLines = 1, overflow = TextOverflow.Ellipsis)
},
appIcon = {
Icon(
Expand All @@ -197,7 +201,7 @@ fun WearSettings(
)
)
},
enabled = true,
enabled = false,
colors = ToggleChipDefaults.toggleChipColors(
checkedEndBackgroundColor = Color(0x80E4C6FF)
)
Expand All @@ -206,4 +210,22 @@ fun WearSettings(
}
}
}
}

@Preview(device = WearDevices.SMALL_ROUND, showSystemUi = true)
@Composable
fun SettingsPreview() {
WearSettings(
navigate = {},
openWakeTimePicker = {},
wakeTime = Pair(
Settings.WAKE_TIME.getDefaultAsLocalTime(),
AlarmType.SYSTEM_ALARM
),
userWakeTime = Settings.WAKE_TIME.getDefaultAsLocalTime(),
setAlarm = {},
useAlarm = Settings.ALARM.getDefaultAsBoolean(),
setAlerts = {},
alerts = Settings.ALERTS.getDefaultAsBoolean()
)
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.turtlepaw.sleeptools.presentation.pages

import android.content.SharedPreferences
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.material.Colors
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.tooling.preview.devices.WearDevices
import com.google.android.horologist.composables.TimePickerWith12HourClock
import com.turtlepaw.sleeptools.utils.AlarmType
import com.turtlepaw.sleeptools.presentation.theme.SleepTheme
import com.turtlepaw.sleeptools.utils.Settings
import java.time.LocalTime

@Composable
Expand All @@ -15,12 +17,7 @@ fun WakeTimePicker(
userWakeTime: LocalTime,
setWakeTime: (value: LocalTime) -> Unit
){
MaterialTheme(
colors = Colors(
primary = Color(0xFFE4C6FF),
secondary = Color(0xFFE4C6FF)
)
) {
SleepTheme {
TimePickerWith12HourClock(
time = userWakeTime,
onTimeConfirm = { time ->
Expand All @@ -29,4 +26,14 @@ fun WakeTimePicker(
}
)
}
}

@Preview(device = WearDevices.SMALL_ROUND, showSystemUi = true)
@Composable
fun WakeTimePickerPreview() {
WakeTimePicker(
closePicker = {},
userWakeTime = Settings.WAKE_TIME.getDefaultAsLocalTime(),
setWakeTime = {}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ fun SleepTheme(
content = content,
colors = Colors(
primary = Color(0xFFE4C6FF),
secondary = Color(0xFFE4C6FF)
secondary = Color(0xFFE4C6FF),
background = Color.Black
)
)
}
20 changes: 13 additions & 7 deletions wear/src/main/java/com/turtlepaw/sleeptools/utils/alarm.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.turtlepaw.sleeptools.utils

/*
This file includes code derived from the home-assistant/android (https://github.com/home-assistant/android/blob/master/LICENSE.md)
This file includes code derived from home-assistant/android (https://github.com/home-assistant/android/blob/master/LICENSE.md)
The original code is licensed under the Apache License Version 2.0
*/

Expand All @@ -17,6 +17,9 @@ import java.time.ZonedDateTime
class AlarmsManager {
companion object {
private const val TAG = "NextAlarm"
private val ALLOW_LIST = listOf(
"com.google.android.deskclock"
)
}

fun fetchAlarms(context: Context): LocalTime? {
Expand All @@ -32,13 +35,16 @@ class AlarmsManager {
pendingIntent = alarmClockInfo.showIntent?.creatorPackage ?: "UNKNOWN"
triggerTime = alarmClockInfo.triggerTime

Log.d(TAG, "Next alarm is scheduled by $pendingIntent with trigger time $triggerTime")
if(pendingIntent in ALLOW_LIST){
Log.d(TAG, "Next alarm is scheduled by $pendingIntent with trigger time $triggerTime")
val instant = Instant.ofEpochMilli(triggerTime)
val zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault())
localTime = zonedDateTime.toLocalTime()

val instant = Instant.ofEpochMilli(triggerTime)
val zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault())
localTime = zonedDateTime.toLocalTime()

return localTime
return localTime
} else {
Log.d(TAG, "Alarm creator app is not in ALLOW_LIST, sending unavailable")
}
} else {
Log.d(TAG, "No alarm is scheduled, sending unavailable")
}
Expand Down
Loading

0 comments on commit c2114b6

Please sign in to comment.