diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7f4be0f..6d7e26d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -29,7 +29,7 @@ android { minSdk = 31 targetSdk = 35 versionCode = ciRunNumber ?: 1 - versionName = "0.8.1" + (ciRunNumber?.let { "+build.$it" } ?: "-dev") + versionName = "0.8.2" + (ciRunNumber?.let { "+build.$it" } ?: "-dev") } signingConfigs { diff --git a/app/src/main/java/eu/brassepc/fitnessdroid/data/SettingsStore.kt b/app/src/main/java/eu/brassepc/fitnessdroid/data/SettingsStore.kt index 448f2e8..228e88b 100644 --- a/app/src/main/java/eu/brassepc/fitnessdroid/data/SettingsStore.kt +++ b/app/src/main/java/eu/brassepc/fitnessdroid/data/SettingsStore.kt @@ -32,6 +32,8 @@ data class AppSettings( val birthYear: Int? = null, /** null = inte satt, false = man, true = kvinna */ val isFemale: Boolean? = null, + /** Visa teknisk logg på spårskärmen (felsökning) */ + val trackLogEnabled: Boolean = false, ) class SettingsStore(private val context: Context) { @@ -58,9 +60,14 @@ class SettingsStore(private val context: Context) { heightCm = prefs[KEY_HEIGHT_CM]?.toDoubleOrNull(), birthYear = prefs[KEY_BIRTH_YEAR], isFemale = prefs[KEY_IS_FEMALE]?.toBooleanStrictOrNull(), + trackLogEnabled = prefs[KEY_TRACK_LOG]?.toBooleanStrictOrNull() ?: false, ) } + suspend fun setTrackLogEnabled(value: Boolean) { + context.settingsDataStore.edit { it[KEY_TRACK_LOG] = value.toString() } + } + suspend fun setScale(address: String?, name: String?, driver: String?) { context.settingsDataStore.edit { prefs -> if (address == null) { @@ -132,5 +139,6 @@ class SettingsStore(private val context: Context) { private val KEY_HEIGHT_CM = stringPreferencesKey("height_cm") private val KEY_BIRTH_YEAR = intPreferencesKey("birth_year") private val KEY_IS_FEMALE = stringPreferencesKey("is_female") + private val KEY_TRACK_LOG = stringPreferencesKey("track_log_enabled") } } diff --git a/app/src/main/java/eu/brassepc/fitnessdroid/data/TrackingService.kt b/app/src/main/java/eu/brassepc/fitnessdroid/data/TrackingService.kt index b706f71..31ae986 100644 --- a/app/src/main/java/eu/brassepc/fitnessdroid/data/TrackingService.kt +++ b/app/src/main/java/eu/brassepc/fitnessdroid/data/TrackingService.kt @@ -251,10 +251,13 @@ class TrackingService : Service(), LocationListener { } lastLocation = location - _state.value = s.copy( + // Utgå från AKTUELLT state (inte snapshotet från funktionens start) — + // annars skrivs t.ex. fasbytet till ACTIVE över och klockan står still. + val cur = _state.value + _state.value = cur.copy( distanceMeters = distance, elevationGainMeters = elevGain, - points = s.points + (location.latitude to location.longitude), + points = cur.points + (location.latitude to location.longitude), currentSpeedKmh = if (location.hasSpeed()) location.speed * 3.6 else null, gpsFix = true, ) diff --git a/app/src/main/java/eu/brassepc/fitnessdroid/ui/settings/SettingsScreen.kt b/app/src/main/java/eu/brassepc/fitnessdroid/ui/settings/SettingsScreen.kt index f2e6939..0747516 100644 --- a/app/src/main/java/eu/brassepc/fitnessdroid/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/eu/brassepc/fitnessdroid/ui/settings/SettingsScreen.kt @@ -71,6 +71,8 @@ class SettingsViewModel( fun addCustomBar(value: Double) = viewModelScope.launch { store.addCustomBarWeight(value) } fun removeCustomBar(value: Double) = viewModelScope.launch { store.removeCustomBarWeight(value) } + fun setTrackLog(value: Boolean) = viewModelScope.launch { store.setTrackLogEnabled(value) } + fun setAutoRelogin(value: Boolean) = viewModelScope.launch { store.setAutoRelogin(value) // Stängs funktionen av slängs de sparade uppgifterna direkt. @@ -145,6 +147,28 @@ fun SettingsScreen( } } + SettingsCard(title = "Felsökning") { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Column(modifier = Modifier.weight(1f)) { + Text("Teknisk spårningslogg", style = MaterialTheme.typography.bodyLarge) + Text( + "Visar GPS-loggen på aktivitetsskärmen (för felsökning).", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + } + androidx.compose.material3.Switch( + checked = settings.trackLogEnabled, + onCheckedChange = viewModel::setTrackLog, + ) + } + } + SettingsCard(title = "Vilotimerns utseende") { RadioRow( label = "Helskärm", diff --git a/app/src/main/java/eu/brassepc/fitnessdroid/ui/track/TrackScreen.kt b/app/src/main/java/eu/brassepc/fitnessdroid/ui/track/TrackScreen.kt index 2c9429a..1969187 100644 --- a/app/src/main/java/eu/brassepc/fitnessdroid/ui/track/TrackScreen.kt +++ b/app/src/main/java/eu/brassepc/fitnessdroid/ui/track/TrackScreen.kt @@ -67,6 +67,7 @@ import eu.brassepc.fitnessdroid.ui.appContainer import eu.brassepc.fitnessdroid.ui.common.compact import eu.brassepc.fitnessdroid.ui.common.openAppSettings import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.TileSourceFactory @@ -79,8 +80,11 @@ import java.time.Instant class TrackViewModel( private val gymApi: GymApi, private val repo: GymRepository, + settingsStore: eu.brassepc.fitnessdroid.data.SettingsStore, ) : ViewModel() { val tracking = TrackingService.state + /** Teknisk logg visas bara om den slagits på i inställningarna. */ + val logEnabled = settingsStore.settings.map { it.trackLogEnabled } val message = MutableStateFlow(null) val saved = MutableStateFlow(false) /** Sammanfattningen som visas efter stopp (null = spårning pågår/ej startad) */ @@ -168,7 +172,7 @@ class TrackViewModel( val Factory: ViewModelProvider.Factory = viewModelFactory { initializer { val c = appContainer() - TrackViewModel(c.gymApi, c.gymRepository) + TrackViewModel(c.gymApi, c.gymRepository, c.settingsStore) } } } @@ -186,6 +190,7 @@ fun TrackScreen( val summary by viewModel.summary.collectAsStateWithLifecycle() val saved by viewModel.saved.collectAsStateWithLifecycle() val message by viewModel.message.collectAsStateWithLifecycle() + val logEnabled by viewModel.logEnabled.collectAsStateWithLifecycle(false) val pendingType by viewModel.pendingType.collectAsStateWithLifecycle() val typeLoadError by viewModel.typeLoadError.collectAsStateWithLifecycle() @@ -276,6 +281,7 @@ fun TrackScreen( message = message, onSave = { rpe, overrideId -> viewModel.save(rpe, overrideId) }, onDone = onBack, + showLog = logEnabled, ) permissionDenied -> Column( modifier = Modifier.padding(16.dp), @@ -323,6 +329,7 @@ fun TrackScreen( tracking = tracking, onStop = { viewModel.stop(context) }, onStartAnyway = { TrackingService.startNow(context) }, + showLog = logEnabled, ) } } @@ -334,6 +341,7 @@ private fun LiveContent( tracking: TrackingState, onStop: () -> Unit, onStartAnyway: () -> Unit, + showLog: Boolean, ) { Column(modifier = Modifier.fillMaxSize()) { if (tracking.isDistanceBased) { @@ -424,7 +432,7 @@ private fun LiveContent( Icon(Icons.Default.Stop, contentDescription = null) Text("Avsluta aktiviteten", modifier = Modifier.padding(start = 6.dp)) } - TechLogSection() + if (showLog) TechLogSection() } } } @@ -561,6 +569,7 @@ private fun SummaryContent( message: String?, onSave: (Double?, Int?) -> Unit, onDone: () -> Unit, + showLog: Boolean, ) { var rpe by remember { mutableStateOf(5f) } @@ -635,7 +644,7 @@ private fun SummaryContent( message?.let { Text(it, color = MaterialTheme.colorScheme.error) } - TechLogSection() + if (showLog) TechLogSection() if (saved) { Text(