Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions android/app/src/main/java/com/noop/data/WhoopDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ interface WhoopDao {
@Upsert
suspend fun upsertSleepSessions(rows: List<SleepSession>)

@Query("DELETE FROM sleepSession WHERE deviceId = :deviceId AND startTs = :startTs")
suspend fun deleteSleepSession(deviceId: String, startTs: Long)

@Upsert
suspend fun upsertMetricSeries(rows: List<MetricSeriesRow>)

Expand Down
6 changes: 6 additions & 0 deletions android/app/src/main/java/com/noop/data/WhoopRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ class WhoopRepository(private val dao: WhoopDao) {

suspend fun upsertDailyMetrics(days: List<DailyMetric>) = dao.upsertDailyMetrics(days)
suspend fun upsertSleepSessions(sessions: List<SleepSession>) = dao.upsertSleepSessions(sessions)

/** Adjust start/end of an existing sleep session (delete + re-insert preserves all other fields). */
suspend fun updateSleepSessionTimes(session: SleepSession, newStartTs: Long, newEndTs: Long) {
dao.deleteSleepSession(session.deviceId, session.startTs)
dao.upsertSleepSessions(listOf(session.copy(startTs = newStartTs, endTs = newEndTs)))
}
suspend fun upsertMetricSeries(rows: List<MetricSeriesRow>) = dao.upsertMetricSeries(rows)
suspend fun upsertJournal(rows: List<JournalEntry>) = dao.upsertJournal(rows)
suspend fun upsertWorkouts(rows: List<WorkoutRow>) = dao.upsertWorkouts(rows)
Expand Down
7 changes: 6 additions & 1 deletion android/app/src/main/java/com/noop/ui/AppRoot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,12 @@ fun AppRoot(viewModel: AppViewModel = viewModel()) {
)
}
composable(Destination.Live.route) { LiveScreen(viewModel) }
composable(Destination.Sleep.route) { SleepScreen(viewModel) }
composable(Destination.Sleep.route) {
SleepScreen(
vm = viewModel,
onOpenJournal = { nav.navigateTopLevel(Destination.Insights.route) },
)
}
composable(Destination.Intervals.route) { IntervalsScreen(viewModel) }
composable(Destination.Breathe.route) { BreatheScreen(viewModel) }
composable(Destination.Coach.route) { CoachScreen() }
Expand Down
4 changes: 4 additions & 0 deletions android/app/src/main/java/com/noop/ui/AppViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,10 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
/** All workouts for the Workouts screen (newest first), dismissed detected bouts removed. */
val workouts: StateFlow<List<WorkoutRow>> = _workouts.asStateFlow()

suspend fun updateSleepSessionTimes(session: com.noop.data.SleepSession, newStartTs: Long, newEndTs: Long) {
runCatching { repository.updateSleepSessionTimes(session, newStartTs, newEndTs) }
}

/** Re-read every source + the dismissed markers and republish [workouts]. */
fun loadWorkouts() {
viewModelScope.launch {
Expand Down
3 changes: 3 additions & 0 deletions android/app/src/main/java/com/noop/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ object NoopPrefs {
/** "Keep connected in the background" — drives [com.noop.ble.WhoopConnectionService]. Default on. */
const val KEY_BACKGROUND_CONNECTION = "noop.backgroundConnection"

/** The calendar day (yyyy-MM-dd) on which the morning-journal prompt was last shown. */
const val KEY_LAST_JOURNAL_PROMPT = "noop.lastJournalPromptDay"

/** "Debug logging" — when on, the strap log is also written to logcat (`adb`). Default OFF so a
* normal user never emits the connection log to the system log; the in-app ring buffer (and the
* "Share strap log" export) work regardless. See [com.noop.ble.WhoopBleClient.debugLogcat]. */
Expand Down
Loading