Skip to content
Merged
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
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ android {

buildFeatures {
compose = true
buildConfig = true
}

testOptions {
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/podometer/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class MainActivity : ComponentActivity() {
)
startActivity(intent)
},
onSetUseTestData = viewModel::setUseTestData,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ class PreferencesManager @Inject constructor(

/** Default onboarding complete: false (show onboarding on first launch). */
const val DEFAULT_ONBOARDING_COMPLETE = false

val KEY_USE_TEST_DATA = booleanPreferencesKey("use_test_data")

/** Default use-test-data: false (use real sensor data). */
const val DEFAULT_USE_TEST_DATA = false
}

// ─── Read ────────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -101,6 +106,15 @@ class PreferencesManager @Inject constructor(
prefs[KEY_NOTIFICATION_STYLE] ?: DEFAULT_NOTIFICATION_STYLE
}

/**
* Emits whether the debug test-data mode is enabled.
* Defaults to `false` (use real sensor data).
*/
fun useTestData(): Flow<Boolean> =
dataStore.data.map { prefs ->
prefs[KEY_USE_TEST_DATA] ?: DEFAULT_USE_TEST_DATA
}

/**
* Emits whether the user has completed the onboarding flow.
* Defaults to `false` on first launch so the onboarding screen is shown.
Expand Down Expand Up @@ -163,6 +177,13 @@ class PreferencesManager @Inject constructor(
}
}

/** Persists the given [enabled] flag for the debug test-data mode. */
suspend fun setUseTestData(enabled: Boolean) {
dataStore.edit { prefs ->
prefs[KEY_USE_TEST_DATA] = enabled
}
}

/**
* Persists the given [complete] flag as the onboarding completion status.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.podometer.ui.activities

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.podometer.data.repository.PreferencesManager
import com.podometer.domain.model.ActivitySession
import com.podometer.domain.model.TransitionEvent
import com.podometer.domain.usecase.RecomputeActivitySessionsUseCase
Expand All @@ -13,6 +14,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
import java.time.LocalDate
import javax.inject.Inject
Expand Down Expand Up @@ -43,6 +45,7 @@ data class ActivitiesUiState(
@HiltViewModel
class ActivitiesViewModel @Inject constructor(
private val recomputeActivitySessions: RecomputeActivitySessionsUseCase,
private val preferencesManager: PreferencesManager,
) : ViewModel() {

companion object {
Expand All @@ -56,18 +59,37 @@ class ActivitiesViewModel @Inject constructor(

/** Combined UI state emitted to the Activities screen. */
@OptIn(ExperimentalCoroutinesApi::class)
val uiState: StateFlow<ActivitiesUiState> = _selectedDate.flatMapLatest { date ->
val uiState: StateFlow<ActivitiesUiState> = combine(
_selectedDate,
preferencesManager.useTestData(),
) { date, useTest -> date to useTest }.flatMapLatest { (date, useTestData) ->
val nowMillis = System.currentTimeMillis()
recomputeActivitySessions(date, nowMillis).combine(
MutableStateFlow(date),
) { sessions, selectedDate ->
ActivitiesUiState(
selectedDate = selectedDate,
sessions = sessions,
isToday = selectedDate == LocalDate.now(),
dateLabel = formatDateLabel(selectedDate),
isLoading = false,
)

if (useTestData) {
combine(
flowOf(TestDataGenerator.generateSessions(date)),
flowOf(Unit),
) { sessions, _ ->
ActivitiesUiState(
selectedDate = date,
sessions = sessions,
isToday = date == LocalDate.now(),
dateLabel = formatDateLabel(date),
isLoading = false,
)
}
} else {
recomputeActivitySessions(date, nowMillis).combine(
MutableStateFlow(date),
) { sessions, selectedDate ->
ActivitiesUiState(
selectedDate = selectedDate,
sessions = sessions,
isToday = selectedDate == LocalDate.now(),
dateLabel = formatDateLabel(selectedDate),
isLoading = false,
)
}
}
}.stateIn(
scope = viewModelScope,
Expand Down
Loading
Loading