diff --git a/app/build.gradle b/app/build.gradle index 42e0fd07..fc0117cd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -65,7 +65,6 @@ dependencies { implementation "androidx.compose.compiler:compiler:$compose_compiler_version" implementation "androidx.compose.material3:material3:$material3_version" implementation "androidx.compose.runtime:runtime:$compose_version" - implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version" implementation "androidx.navigation:navigation-compose:$navigation_version" diff --git a/app/src/main/java/com/rtbishop/look4sat/MainApplication.kt b/app/src/main/java/com/rtbishop/look4sat/MainApplication.kt index d5f2b55b..6877d711 100644 --- a/app/src/main/java/com/rtbishop/look4sat/MainApplication.kt +++ b/app/src/main/java/com/rtbishop/look4sat/MainApplication.kt @@ -18,6 +18,7 @@ package com.rtbishop.look4sat import android.app.Application +import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -29,13 +30,13 @@ class MainApplication : Application() { override fun onCreate() { super.onCreate() container = MainContainer(this) - checkAutoUpdate() + container.mainScope.launch { checkAutoUpdate() } } - private fun checkAutoUpdate() { + private suspend fun checkAutoUpdate() { val settingsRepo = container.settingsRepo - if (settingsRepo.isUpdateEnabled()) { - val timeDelta = System.currentTimeMillis() - settingsRepo.getLastUpdateTime() + if (settingsRepo.otherSettings.value.updateState) { + val timeDelta = System.currentTimeMillis() - settingsRepo.databaseState.value.timestamp if (timeDelta > 172800000) { // 48 hours in ms val sdf = SimpleDateFormat("d MMM yyyy - HH:mm:ss", Locale.getDefault()) println("Started periodic data update on ${sdf.format(Date())}") diff --git a/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt b/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt index e38aa4b7..c56c98e5 100644 --- a/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt +++ b/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt @@ -23,6 +23,7 @@ import com.rtbishop.look4sat.framework.data.DataSource import com.rtbishop.look4sat.framework.data.LocalStorage import com.rtbishop.look4sat.framework.data.MIGRATION_1_2 import com.rtbishop.look4sat.framework.data.MainDatabase +import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -33,10 +34,13 @@ class MainContainer(private val context: Context) { private val database = Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb") .addMigrations(MIGRATION_1_2).fallbackToDestructiveMigration().build() private val localStorage = LocalStorage(database.storageDao()) + private val mainHandler = CoroutineExceptionHandler { _, error -> println("Look4Sat: $error") } + val mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + mainHandler) val settingsRepo = provideSettingsRepo() - val databaseRepo = provideDatabaseRepo(settingsRepo) - val sensorsRepo = provideSensorRepo() + val databaseRepo = provideDatabaseRepo() val satelliteRepo = provideSatelliteRepo() + val selectionRepo = provideSelectionRepo() + val sensorsRepo = provideSensorsRepo() fun provideBluetoothReporter(): BluetoothReporter { val btManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager @@ -47,27 +51,26 @@ class MainContainer(private val context: Context) { return NetworkReporter(CoroutineScope(Dispatchers.IO)) } - private fun provideDatabaseRepo(settingsRepo: ISettingsRepo): IDatabaseRepo { + private fun provideDatabaseRepo(): IDatabaseRepo { val dataParser = DataParser(Dispatchers.Default) val dataSource = DataSource(context.contentResolver, Dispatchers.IO) - val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default) - return DatabaseRepo(dataParser, localStorage, dataSource, scope, settingsRepo) - } - - fun provideSelectionRepo(): ISelectionRepo { - return SelectionRepo(Dispatchers.Default, localStorage, settingsRepo) - } - - private fun provideSensorRepo(): ISensorsRepo { - val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager - val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) - return SensorsRepo(sensorManager, sensor) + return DatabaseRepo(Dispatchers.Default, dataParser, dataSource, localStorage, settingsRepo) } private fun provideSatelliteRepo(): ISatelliteRepo { return SatelliteRepo(Dispatchers.Default, localStorage) } + private fun provideSelectionRepo(): ISelectionRepo { + return SelectionRepo(Dispatchers.Default, localStorage, settingsRepo) + } + + private fun provideSensorsRepo(): ISensorsRepo { + val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager + val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) + return SensorsRepo(sensorManager, sensor) + } + private fun provideSettingsRepo(): ISettingsRepo { val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE) diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsRepo.kt b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsRepo.kt index 9049cafb..1366bc36 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsRepo.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsRepo.kt @@ -24,7 +24,9 @@ import androidx.core.content.edit import androidx.core.location.LocationManagerCompat import androidx.core.os.CancellationSignal import com.rtbishop.look4sat.domain.ISettingsRepo +import com.rtbishop.look4sat.model.DatabaseState import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.OtherSettings import com.rtbishop.look4sat.utility.QthConverter import com.rtbishop.look4sat.utility.round import kotlinx.coroutines.flow.MutableStateFlow @@ -36,11 +38,13 @@ class SettingsRepo( ) : ISettingsRepo { private val keyModes = "satModes" - private val keyCompass = "compass" - private val keyRadarSweep = "radarSweep" - private val keyTimeUTC = "timeUTC" - private val keyLastUpdateTime = "lastUpdateTime" - private val keyAutoUpdateEnabled = "autoUpdateEnabled" + private val keyUtcState = "utcState" + private val keyUpdateState = "updateState" + private val keySweepState = "sweepState" + private val keySensorState = "sensorState" + private val keyDataEntries = "dataEntries" + private val keyDataRadios = "dataRadios" + private val keyDataTimestamp = "dataTimestamp" private val keyHoursAhead = "hoursAhead" private val keyMinElevation = "minElevation" private val keyRotator = "isRotatorEnabled" @@ -164,44 +168,52 @@ class SettingsRepo( preferences.edit { putDouble(keyMinElevation, minElevation) } } - override fun isUtcEnabled(): Boolean { - return preferences.getBoolean(keyTimeUTC, false) + private val _databaseState = MutableStateFlow(loadDatabaseState()) + override val databaseState: StateFlow = _databaseState + + override fun saveDatabaseState(state: DatabaseState) = preferences.edit { + putInt(keyDataEntries, state.entriesTotal) + putInt(keyDataRadios, state.radiosTotal) + putLong(keyDataTimestamp, state.timestamp) + _databaseState.value = state } - override fun setUtcState(value: Boolean) { - preferences.edit { putBoolean(keyTimeUTC, value) } + private fun loadDatabaseState(): DatabaseState { + val entriesTotal = preferences.getInt(keyDataEntries, 0) + val radiosTotal = preferences.getInt(keyDataRadios, 0) + val timestamp = preferences.getLong(keyDataTimestamp, 0L) + return DatabaseState(entriesTotal, radiosTotal, timestamp) } - override fun getLastUpdateTime(): Long { - return preferences.getLong(keyLastUpdateTime, 0L) + private val _otherSettings = MutableStateFlow(loadOtherSettings()) + override val otherSettings: StateFlow = _otherSettings + + override fun toggleUtc(value: Boolean) { + preferences.edit { putBoolean(keyUtcState, value) } + _otherSettings.value = otherSettings.value.copy(utcState = value) } - override fun setLastUpdateTime(updateTime: Long) { - preferences.edit { putLong(keyLastUpdateTime, updateTime) } + override fun toggleUpdate(value: Boolean) { + preferences.edit { putBoolean(keyUpdateState, value) } + _otherSettings.value = otherSettings.value.copy(updateState = value) } - override fun isUpdateEnabled(): Boolean { - return preferences.getBoolean(keyAutoUpdateEnabled, true) + override fun toggleSweep(value: Boolean) { + preferences.edit { putBoolean(keySweepState, value) } + _otherSettings.value = otherSettings.value.copy(sweepState = value) } - override fun setUpdateState(value: Boolean) { - preferences.edit { putBoolean(keyAutoUpdateEnabled, value) } + override fun toggleSensor(value: Boolean) { + preferences.edit { putBoolean(keySensorState, value) } + _otherSettings.value = otherSettings.value.copy(sensorState = value) } - override fun isSensorEnabled(): Boolean { - return preferences.getBoolean(keyCompass, true) - } - - override fun setSensorState(value: Boolean) { - preferences.edit { putBoolean(keyCompass, value) } - } - - override fun isSweepEnabled(): Boolean { - return preferences.getBoolean(keyRadarSweep, true) - } - - override fun setSweepState(value: Boolean) { - preferences.edit { putBoolean(keyRadarSweep, value) } + private fun loadOtherSettings(): OtherSettings { + val utcState = preferences.getBoolean(keyUtcState, false) + val updateState = preferences.getBoolean(keyUpdateState, true) + val sweepState = preferences.getBoolean(keySweepState, true) + val sensorState = preferences.getBoolean(keySensorState, true) + return OtherSettings(utcState, updateState, sweepState, sensorState) } override fun saveModesSelection(modes: List) { diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalStorage.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalStorage.kt index ee905e7a..55caf0ea 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalStorage.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalStorage.kt @@ -31,7 +31,7 @@ class LocalStorage(private val storageDao: StorageDao) : ILocalStorage { //region # Entries region - override fun getEntriesTotal() = storageDao.getEntriesTotal() + override suspend fun getEntriesTotal() = storageDao.getEntriesTotal() override suspend fun getEntriesList(): List { return storageDao.getEntriesList().toDomainItems() @@ -64,7 +64,7 @@ class LocalStorage(private val storageDao: StorageDao) : ILocalStorage { //region # Radios region - override fun getRadiosTotal() = storageDao.getRadiosTotal() + override suspend fun getRadiosTotal() = storageDao.getRadiosTotal() override suspend fun getRadiosWithId(id: Int): List { return storageDao.getRadiosWithId(id).toDomainRadios() diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/MainDatabase.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/MainDatabase.kt index 70b70a67..c26a9b18 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/MainDatabase.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/MainDatabase.kt @@ -24,7 +24,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase import com.rtbishop.look4sat.framework.model.SatEntry import com.rtbishop.look4sat.framework.model.SatRadio -@Database(entities = [SatEntry::class, SatRadio::class], version = 2) +@Database(entities = [SatEntry::class, SatRadio::class], version = 2, exportSchema = false) abstract class MainDatabase : RoomDatabase() { abstract fun storageDao(): StorageDao diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDao.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDao.kt index 3b1a4f16..faad00f8 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDao.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDao.kt @@ -21,13 +21,12 @@ import androidx.room.* import com.rtbishop.look4sat.framework.model.SatEntry import com.rtbishop.look4sat.framework.model.SatItem import com.rtbishop.look4sat.framework.model.SatRadio -import kotlinx.coroutines.flow.Flow @Dao interface StorageDao { @Query("SELECT COUNT(*) FROM entries") - fun getEntriesTotal(): Flow + suspend fun getEntriesTotal(): Int //@Transaction @Query("SELECT catnum, name FROM entries ORDER BY name ASC") @@ -44,7 +43,7 @@ interface StorageDao { suspend fun deleteEntries() @Query("SELECT COUNT(*) FROM radios") - fun getRadiosTotal(): Flow + suspend fun getRadiosTotal(): Int @Transaction @Query("SELECT * FROM radios WHERE catnum = :id AND isAlive = 1") diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesViewModel.kt index 988cd148..3b7ea64c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesViewModel.kt @@ -69,7 +69,7 @@ class EntriesViewModel(private val selectionRepo: ISelectionRepo) : ViewModel() val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY initializer { val container = (this[applicationKey] as MainApplication).container - EntriesViewModel(container.provideSelectionRepo()) + EntriesViewModel(container.selectionRepo) } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt index 1803f5da..151e08b3 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt @@ -89,7 +89,7 @@ class PassesViewModel( } } - fun shouldUseUTC() = settingsRepo.isUtcEnabled() + fun shouldUseUTC() = settingsRepo.otherSettings.value.utcState fun calculatePasses( hoursAhead: Int = 1, diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarViewModel.kt index 13053e03..8882d981 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarViewModel.kt @@ -61,7 +61,7 @@ class RadarViewModel( val orientation = mutableStateOf(sensorsRepo.orientation.value) init { - if (settingsRepo.isSensorEnabled()) { + if (settingsRepo.otherSettings.value.sensorState) { viewModelScope.launch { sensorsRepo.enableSensor() sensorsRepo.orientation.collect { data -> @@ -100,9 +100,9 @@ class RadarViewModel( } } - fun getUseCompass(): Boolean = settingsRepo.isSensorEnabled() + fun getUseCompass(): Boolean = settingsRepo.otherSettings.value.sensorState - fun getShowSweep(): Boolean = settingsRepo.isSweepEnabled() + fun getShowSweep(): Boolean = settingsRepo.otherSettings.value.sweepState private fun getMagDeclination(geoPos: GeoPos, time: Long = System.currentTimeMillis()): Float { val latitude = geoPos.latitude.toFloat() diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt index b5fffb3a..80a0b572 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt @@ -38,6 +38,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.rtbishop.look4sat.BuildConfig import com.rtbishop.look4sat.R import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.OtherSettings import com.rtbishop.look4sat.presentation.CardButton import com.rtbishop.look4sat.presentation.MainTheme import com.rtbishop.look4sat.presentation.dialogs.LocatorDialog @@ -76,43 +77,55 @@ fun SettingsScreen() { val locationPermFine = Manifest.permission.ACCESS_FINE_LOCATION val locationRequest = rememberLauncherForActivityResult(locationContract) { permissions -> when { - permissions[locationPermFine] == true -> viewModel.locationSettings.value.setGpsLoc() - permissions[locationPermCoarse] == true -> viewModel.locationSettings.value.setGpsLoc() + permissions[locationPermFine] == true -> viewModel.setGpsPosition() + permissions[locationPermCoarse] == true -> viewModel.setGpsPosition() else -> showToast(context, locationError) } } val contentContract = ActivityResultContracts.GetContent() val contentRequest = rememberLauncherForActivityResult(contentContract) { uri -> - uri?.let { viewModel.dataSettings.value.updateFromFile(uri.toString()) } + uri?.let { viewModel.updateFromFile(uri.toString()) } } - // Location settings - val locSettings = viewModel.locationSettings.value - val setGpsLoc = { locationRequest.launch(arrayOf(locationPermCoarse, locationPermFine)) } - val showPosDialog = rememberSaveable { mutableStateOf(false) } - val togglePosDialog = { showPosDialog.value = showPosDialog.value.not() } - if (showPosDialog.value) { - PositionDialog( - locSettings.stationPos.latitude, - locSettings.stationPos.longitude, - togglePosDialog, - locSettings.setManualLoc - ) + // Position settings + val positionSettings = viewModel.positionSettings.value + val stationPos = positionSettings.stationPos + val setGpsPos = { locationRequest.launch(arrayOf(locationPermCoarse, locationPermFine)) } + val setGeoPos = { lat: Double, lon: Double -> viewModel.setGeoPosition(lat, lon) } + val setQthPos = { locator: String -> viewModel.setQthPosition(locator) } + val dismissPos = { viewModel.dismissPosMessage() } + val posDialogState = rememberSaveable { mutableStateOf(false) } + val showPosDialog = { posDialogState.value = posDialogState.value.not() } + if (posDialogState.value) { + PositionDialog(stationPos.latitude, stationPos.longitude, showPosDialog, setGeoPos) } - val showLocDialog = rememberSaveable { mutableStateOf(false) } - val toggleLocDialog = { showLocDialog.value = showLocDialog.value.not() } - if (showLocDialog.value) { - LocatorDialog(locSettings.stationPos.qthLocator, toggleLocDialog, locSettings.setQthLoc) + val locDialogState = rememberSaveable { mutableStateOf(false) } + val showLocDialog = { locDialogState.value = locDialogState.value.not() } + if (locDialogState.value) { + LocatorDialog(positionSettings.stationPos.qthLocator, showLocDialog, setQthPos) } + // Data settings + val dataSettings = viewModel.dataSettings.value + val updateFromWeb: () -> Unit = { viewModel.updateFromWeb() } + val updateFromFile = { contentRequest.launch("*/*") } + val clearAllData: () -> Unit = { viewModel.clearAllData() } + + // Other settings + val otherSettings = viewModel.otherSettings.value + val toggleUtc = { value: Boolean -> viewModel.toggleUtc(value) } + val toggleUpdate = { value: Boolean -> viewModel.toggleUpdate(value) } + val toggleSweep = { value: Boolean -> viewModel.toggleSweep(value) } + val toggleSensor = { value: Boolean -> viewModel.toggleSensor(value) } + // Screen setup LazyColumn( modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp) ) { item { CardAbout(BuildConfig.VERSION_NAME) } - item { LocationCard(locSettings, setGpsLoc, togglePosDialog, toggleLocDialog) } - item { DataCard(viewModel.dataSettings.value) { contentRequest.launch("*/*") } } - item { OtherCard(viewModel.otherSettings.value) } + item { LocationCard(positionSettings, setGpsPos, showPosDialog, showLocDialog, dismissPos) } + item { DataCard(dataSettings, updateFromWeb, updateFromFile, clearAllData) } + item { OtherCard(otherSettings, toggleUtc, toggleUpdate, toggleSweep, toggleSensor) } item { CardCredits() } } } @@ -181,16 +194,17 @@ private fun CardAbout(version: String, modifier: Modifier = Modifier) { @Composable private fun LocationCardPreview() = MainTheme { val stationPos = GeoPos(0.0, 0.0, 0.0, "IO91vl", 0L) - val settings = LocationSettings(true, stationPos, 0, {}, { _, _ -> }, {}, {}) - LocationCard(settings = settings, setGpsLoc = {}, togglePosDialog = {}) {} + val settings = PositionSettings(true, stationPos, 0) + LocationCard(settings = settings, setGpsPos = {}, showPosDialog = {}, {}) {} } @Composable private fun LocationCard( - settings: LocationSettings, - setGpsLoc: () -> Unit, - togglePosDialog: () -> Unit, - toggleLocDialog: () -> Unit + settings: PositionSettings, + setGpsPos: () -> Unit, + showPosDialog: () -> Unit, + showLocDialog: () -> Unit, + dismissPosMessage: () -> Unit ) { ElevatedCard(modifier = Modifier.fillMaxWidth()) { Column( @@ -227,19 +241,19 @@ private fun LocationCard( Spacer(modifier = Modifier.height(1.dp)) Row(horizontalArrangement = Arrangement.SpaceEvenly) { CardButton( - onClick = setGpsLoc, + onClick = setGpsPos, text = stringResource(id = R.string.btn_gps), modifier = Modifier.weight(1f) ) Spacer(modifier = Modifier.width(6.dp)) CardButton( - onClick = togglePosDialog, + onClick = showPosDialog, text = stringResource(id = R.string.btn_manual), modifier = Modifier.weight(1f) ) Spacer(modifier = Modifier.width(6.dp)) CardButton( - onClick = toggleLocDialog, + onClick = showLocDialog, text = stringResource(id = R.string.btn_qth), modifier = Modifier.weight(1f) ) @@ -251,7 +265,7 @@ private fun LocationCard( val errorString = stringResource(id = settings.messageResId) LaunchedEffect(key1 = settings.messageResId) { showToast(context, errorString) - settings.dismissMessage() + dismissPosMessage() } } } @@ -259,12 +273,17 @@ private fun LocationCard( @Preview(showBackground = true) @Composable private fun DataCardPreview() = MainTheme { - val settings = DataSettings(true, 0L, 5000, 2500, {}, {}, {}) - DataCard(settings = settings) {} + val settings = DataSettings(true, 5000, 2500, 0L) + DataCard(settings = settings, {}, {}) {} } @Composable -private fun DataCard(settings: DataSettings, updateFromFile: () -> Unit) { +private fun DataCard( + settings: DataSettings, + updateFromWeb: () -> Unit, + updateFromFile: () -> Unit, + clearAllData: () -> Unit +) { ElevatedCard(modifier = Modifier.fillMaxWidth()) { Column( horizontalAlignment = Alignment.CenterHorizontally, @@ -278,29 +297,29 @@ private fun DataCard(settings: DataSettings, updateFromFile: () -> Unit) { UpdateIndicator(isUpdating = settings.isUpdating, Modifier.weight(1f)) } Spacer(modifier = Modifier.height(2.dp)) - Text(text = setUpdateTime(updateTime = settings.lastUpdated)) + Text(text = setUpdateTime(updateTime = settings.timestamp)) Spacer(modifier = Modifier.height(2.dp)) Row(horizontalArrangement = Arrangement.SpaceBetween) { - Text(text = "Satellites: ${settings.satsTotal}") + Text(text = "Satellites: ${settings.entriesTotal}") Spacer(modifier = Modifier.weight(1f)) Text(text = "Transceivers: ${settings.radiosTotal}") } Spacer(modifier = Modifier.height(1.dp)) Row(horizontalArrangement = Arrangement.SpaceEvenly) { CardButton( - onClick = settings.updateFromWeb, + onClick = { updateFromWeb() }, text = stringResource(id = R.string.btn_web), modifier = Modifier.weight(1f) ) Spacer(modifier = Modifier.width(6.dp)) CardButton( - onClick = updateFromFile, + onClick = { updateFromFile() }, text = stringResource(id = R.string.btn_file), modifier = Modifier.weight(1f) ) Spacer(modifier = Modifier.width(6.dp)) CardButton( - onClick = settings.clearAllData, + onClick = { clearAllData() }, text = stringResource(id = R.string.btn_clear), modifier = Modifier.weight(1f) ) @@ -357,14 +376,19 @@ private fun DataCard(settings: DataSettings, updateFromFile: () -> Unit) { @Preview(showBackground = true) @Composable private fun OtherCardPreview() = MainTheme { - val settings = OtherSettings( - getUtc = false, getUpdate = true, getSweep = true, getSensor = true, - setUtc = {}, setUpdate = {}, setSweep = {}, setSensor = {}) - OtherCard(settings = settings) + val values = + OtherSettings(utcState = false, updateState = true, sweepState = true, sensorState = true) + OtherCard(settings = values, {}, {}, {}, {}) } @Composable -private fun OtherCard(settings: OtherSettings) { +private fun OtherCard( + settings: OtherSettings, + toggleUtc: (Boolean) -> Unit, + toggleUpdate: (Boolean) -> Unit, + toggleSweep: (Boolean) -> Unit, + toggleSensor: (Boolean) -> Unit +) { ElevatedCard(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 2.dp)) { Row( @@ -373,7 +397,7 @@ private fun OtherCard(settings: OtherSettings) { modifier = Modifier.fillMaxWidth() ) { Text(text = stringResource(id = R.string.other_switch_utc)) - Switch(checked = settings.getUtc, onCheckedChange = { settings.setUtc(it) }) + Switch(checked = settings.utcState, onCheckedChange = { toggleUtc(it) }) } Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -381,7 +405,7 @@ private fun OtherCard(settings: OtherSettings) { modifier = Modifier.fillMaxWidth() ) { Text(text = stringResource(id = R.string.other_switch_update)) - Switch(checked = settings.getUpdate, onCheckedChange = { settings.setUpdate(it) }) + Switch(checked = settings.updateState, onCheckedChange = { toggleUpdate(it) }) } Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -389,7 +413,7 @@ private fun OtherCard(settings: OtherSettings) { modifier = Modifier.fillMaxWidth() ) { Text(text = stringResource(id = R.string.other_switch_sweep)) - Switch(checked = settings.getSweep, onCheckedChange = { settings.setSweep(it) }) + Switch(checked = settings.sweepState, onCheckedChange = { toggleSweep(it) }) } Row( horizontalArrangement = Arrangement.SpaceBetween, @@ -397,7 +421,7 @@ private fun OtherCard(settings: OtherSettings) { modifier = Modifier.fillMaxWidth() ) { Text(text = stringResource(id = R.string.other_switch_sensors)) - Switch(checked = settings.getSensor, onCheckedChange = { settings.setSensor(it) }) + Switch(checked = settings.sensorState, onCheckedChange = { toggleSensor(it) }) } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsUiState.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsUiState.kt index ab7e34d8..800dffd0 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsUiState.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsUiState.kt @@ -2,33 +2,8 @@ package com.rtbishop.look4sat.presentation.settings import com.rtbishop.look4sat.model.GeoPos -data class LocationSettings( - val isUpdating: Boolean, - val stationPos: GeoPos, - val messageResId: Int, - val setGpsLoc: () -> Unit, - val setManualLoc: (Double, Double) -> Unit, - val setQthLoc: (String) -> Unit, - val dismissMessage: () -> Unit -) +data class PositionSettings(val isUpdating: Boolean, val stationPos: GeoPos, val messageResId: Int) data class DataSettings( - val isUpdating: Boolean, - val lastUpdated: Long, - val satsTotal: Int, - val radiosTotal: Int, - val updateFromWeb: () -> Unit, - val updateFromFile: (String) -> Unit, - val clearAllData: () -> Unit -) - -data class OtherSettings( - val getUtc: Boolean, - val getUpdate: Boolean, - val getSweep: Boolean, - val getSensor: Boolean, - val setUtc: (Boolean) -> Unit, - val setUpdate: (Boolean) -> Unit, - val setSweep: (Boolean) -> Unit, - val setSensor: (Boolean) -> Unit + val isUpdating: Boolean, val entriesTotal: Int, val radiosTotal: Int, val timestamp: Long ) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsViewModel.kt index f74cd4ec..e674c4f6 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsViewModel.kt @@ -17,6 +17,7 @@ */ package com.rtbishop.look4sat.presentation.settings +import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider @@ -27,121 +28,107 @@ import com.rtbishop.look4sat.MainApplication import com.rtbishop.look4sat.R import com.rtbishop.look4sat.domain.IDatabaseRepo import com.rtbishop.look4sat.domain.ISettingsRepo -import com.rtbishop.look4sat.model.DataState -import kotlinx.coroutines.flow.combine +import com.rtbishop.look4sat.model.OtherSettings import kotlinx.coroutines.launch class SettingsViewModel( private val databaseRepo: IDatabaseRepo, private val settingsRepo: ISettingsRepo ) : ViewModel() { - private val defaultLocationSettings = LocationSettings(false, - settingsRepo.stationPosition.value, - 0, - { setGpsPosition() }, - { latitude, longitude -> setGeoPosition(latitude, longitude) }, - { locator -> setQthPosition(locator) }, - { dismissLocationMessage() }) - val locationSettings = mutableStateOf(defaultLocationSettings) + private val defaultPosSettings = PositionSettings(false, settingsRepo.stationPosition.value, 0) + private val _positionSettings = mutableStateOf(defaultPosSettings) + val positionSettings: State = _positionSettings - private val defaultDataSettings = DataSettings(false, - settingsRepo.getLastUpdateTime(), - 0, - 0, - { databaseRepo.updateFromWeb() }, - { databaseRepo.updateFromFile(it) }, - { databaseRepo.clearAllData() }) - val dataSettings = mutableStateOf(defaultDataSettings) + private val defaultDataSettings = DataSettings(false, 0, 0, 0L) + private val _dataSettings = mutableStateOf(defaultDataSettings) + val dataSettings: State = _dataSettings - private val defaultOtherSettings = OtherSettings(settingsRepo.isUtcEnabled(), - settingsRepo.isUpdateEnabled(), - settingsRepo.isSweepEnabled(), - settingsRepo.isSensorEnabled(), - { setUtc(it) }, - { setUpdate(it) }, - { setSweep(it) }, - { setSensor(it) }) - val otherSettings = mutableStateOf(defaultOtherSettings) + private val _otherSettings = mutableStateOf(settingsRepo.otherSettings.value) + val otherSettings: State = _otherSettings init { viewModelScope.launch { - settingsRepo.stationPosition.collect { stationPos -> - locationSettings.value = locationSettings.value.copy( - isUpdating = false, stationPos = stationPos + settingsRepo.stationPosition.collect { geoPos -> + _positionSettings.value = + _positionSettings.value.copy(isUpdating = false, stationPos = geoPos) + } + } + viewModelScope.launch { + settingsRepo.databaseState.collect { state -> + _dataSettings.value = _dataSettings.value.copy( + isUpdating = false, + entriesTotal = state.entriesTotal, + radiosTotal = state.radiosTotal, + timestamp = state.timestamp ) } } viewModelScope.launch { - databaseRepo.updateState.collect { - val isUpdating = it is DataState.Loading - dataSettings.value = dataSettings.value.copy( - isUpdating = isUpdating, lastUpdated = settingsRepo.getLastUpdateTime() - ) - } - } - viewModelScope.launch { - combine( - databaseRepo.getEntriesTotal(), databaseRepo.getRadiosTotal() - ) { sats, radios -> - dataSettings.value = dataSettings.value.copy(satsTotal = sats, radiosTotal = radios) - }.collect {} + settingsRepo.otherSettings.collect { _otherSettings.value = it } } } - private fun setGpsPosition() { + fun setGpsPosition() { if (settingsRepo.setGpsPosition()) { val messageResId = R.string.location_success - locationSettings.value = - locationSettings.value.copy(isUpdating = true, messageResId = messageResId) + _positionSettings.value = + _positionSettings.value.copy(isUpdating = true, messageResId = messageResId) } else { val errorResId = R.string.location_gps_error - locationSettings.value = locationSettings.value.copy(messageResId = errorResId) + _positionSettings.value = _positionSettings.value.copy(messageResId = errorResId) } } - private fun setGeoPosition(latitude: Double, longitude: Double) { + fun setGeoPosition(latitude: Double, longitude: Double) { if (settingsRepo.setGeoPosition(latitude, longitude)) { val messageResId = R.string.location_success - locationSettings.value = locationSettings.value.copy(messageResId = messageResId) + _positionSettings.value = _positionSettings.value.copy(messageResId = messageResId) } else { val errorResId = R.string.location_manual_error - locationSettings.value = locationSettings.value.copy(messageResId = errorResId) + _positionSettings.value = _positionSettings.value.copy(messageResId = errorResId) } } - private fun setQthPosition(locator: String) { + fun setQthPosition(locator: String) { if (settingsRepo.setQthPosition(locator)) { val messageResId = R.string.location_success - locationSettings.value = locationSettings.value.copy(messageResId = messageResId) + _positionSettings.value = _positionSettings.value.copy(messageResId = messageResId) } else { val errorResId = R.string.location_qth_error - locationSettings.value = locationSettings.value.copy(messageResId = errorResId) + _positionSettings.value = _positionSettings.value.copy(messageResId = errorResId) } } - private fun dismissLocationMessage() { - locationSettings.value = locationSettings.value.copy(messageResId = 0) + fun dismissPosMessage() { + _positionSettings.value = _positionSettings.value.copy(messageResId = 0) } - private fun setUtc(value: Boolean) { - settingsRepo.setUtcState(value) - otherSettings.value = otherSettings.value.copy(getUtc = value) + fun updateFromWeb() = viewModelScope.launch { + try { + _dataSettings.value = _dataSettings.value.copy(isUpdating = true) + databaseRepo.updateFromWeb() + } catch (exception: Exception) { + _dataSettings.value = _dataSettings.value.copy(isUpdating = false) + println(exception.printStackTrace()) + } } - private fun setUpdate(value: Boolean) { - settingsRepo.setUpdateState(value) - otherSettings.value = otherSettings.value.copy(getUpdate = value) + fun updateFromFile(uri: String) = viewModelScope.launch { + try { + _dataSettings.value = _dataSettings.value.copy(isUpdating = true) + databaseRepo.updateFromFile(uri) + } catch (exception: Exception) { + _dataSettings.value = _dataSettings.value.copy(isUpdating = false) + println(exception.printStackTrace()) + } } - private fun setSweep(value: Boolean) { - settingsRepo.setSweepState(value) - otherSettings.value = otherSettings.value.copy(getSweep = value) - } + fun clearAllData() = viewModelScope.launch { databaseRepo.clearAllData() } - private fun setSensor(value: Boolean) { - settingsRepo.setSensorState(value) - otherSettings.value = otherSettings.value.copy(getSensor = value) - } + fun toggleUtc(value: Boolean) = settingsRepo.toggleUtc(value) + fun toggleUpdate(value: Boolean) = settingsRepo.toggleUpdate(value) + fun toggleSweep(value: Boolean) = settingsRepo.toggleSweep(value) + fun toggleSensor(value: Boolean) = settingsRepo.toggleSensor(value) // fun getRotatorEnabled(): Boolean = settings.getRotatorEnabled() // fun setRotatorEnabled(value: Boolean) = settings.setRotatorEnabled(value) diff --git a/base/src/main/java/com/rtbishop/look4sat/data/DatabaseRepo.kt b/base/src/main/java/com/rtbishop/look4sat/data/DatabaseRepo.kt index 347122b2..a3a656fa 100644 --- a/base/src/main/java/com/rtbishop/look4sat/data/DatabaseRepo.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/DatabaseRepo.kt @@ -19,112 +19,85 @@ package com.rtbishop.look4sat.data import com.rtbishop.look4sat.domain.IDatabaseRepo import com.rtbishop.look4sat.domain.ISettingsRepo -import com.rtbishop.look4sat.model.DataState +import com.rtbishop.look4sat.model.DatabaseState import com.rtbishop.look4sat.model.SatEntry -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.CoroutineScope +import com.rtbishop.look4sat.model.SatRadio +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.async -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.InputStream import java.util.zip.ZipInputStream class DatabaseRepo( + private val dispatcher: CoroutineDispatcher, private val dataParser: DataParser, - private val localStorage: ILocalStorage, private val dataSource: IDataSource, - private val repositoryScope: CoroutineScope, + private val localStorage: ILocalStorage, private val settingsRepository: ISettingsRepo ) : IDatabaseRepo { - private val exceptionHandler = CoroutineExceptionHandler { _, exception -> - _updateState.value = DataState.Exception(exception.message) - } - private val updateStateDelay = 875L - private val _updateState = MutableStateFlow>(DataState.Handled) - override val updateState: StateFlow> = _updateState - - override fun getEntriesTotal() = localStorage.getEntriesTotal() - - override fun getRadiosTotal() = localStorage.getRadiosTotal() - - override fun updateFromFile(uri: String) { - repositoryScope.launch(exceptionHandler) { - _updateState.value = DataState.Loading - dataSource.getFileStream(uri)?.let { stream -> - delay(updateStateDelay) - localStorage.insertEntries(importSatellites(stream)) - } - setUpdateSuccessful() - } + override suspend fun updateFromFile(uri: String) = withContext(dispatcher) { + val importedSatellites = dataSource.getFileStream(uri)?.let { importSatellites(it) } + importedSatellites?.let { localStorage.insertEntries(it) } + setUpdateSuccessful(System.currentTimeMillis()) } - override fun updateFromWeb() { - _updateState.value = DataState.Loading - repositoryScope.launch(exceptionHandler) { - val importedEntries = mutableListOf() - val sourcesMap = settingsRepository.satelliteSourcesMap - val jobsMap = sourcesMap.mapValues { async { dataSource.getNetworkStream(it.value) } } - jobsMap.mapValues { job -> job.value.await() }.forEach { entry -> - entry.value?.let { stream -> - when (val type = entry.key) { - "Amsat", "R4UAB" -> { - // parse tle stream - val satellites = importSatellites(stream) - val catnums = satellites.map { it.data.catnum } - settingsRepository.saveSatType(type, catnums) - importedEntries.addAll(satellites) - } + override suspend fun updateFromWeb() = withContext(dispatcher) { + val sourcesMap = settingsRepository.satelliteSourcesMap + val importedEntries = mutableListOf() + val importedRadios = mutableListOf() + // fetch + val jobsMap = sourcesMap.mapValues { async { dataSource.getNetworkStream(it.value) } } + val jobRadios = async { dataSource.getNetworkStream(settingsRepository.radioSourceUrl) } + // parse + jobsMap.mapValues { job -> job.value.await() }.forEach { entry -> + entry.value?.let { stream -> + when (val type = entry.key) { + "AMSAT", "R4UAB" -> { + // parse tle stream + val satellites = importSatellites(stream) + val catnums = satellites.map { it.data.catnum } + settingsRepository.saveSatType(type, catnums) + importedEntries.addAll(satellites) + } - "McCants", "Classified" -> { - // unzip and parse tle stream - val unzipped = ZipInputStream(stream).apply { nextEntry } - val satellites = importSatellites(unzipped) - val catnums = satellites.map { it.data.catnum } - settingsRepository.saveSatType(type, catnums) - importedEntries.addAll(satellites) - } + "McCants", "Classified" -> { + // unzip and parse tle stream + val unzipped = ZipInputStream(stream).apply { nextEntry } + val satellites = importSatellites(unzipped) + val catnums = satellites.map { it.data.catnum } + settingsRepository.saveSatType(type, catnums) + importedEntries.addAll(satellites) + } - else -> { - // parse csv stream - val parsed = dataParser.parseCSVStream(stream) - val satellites = parsed.map { data -> SatEntry(data) } - val catnums = satellites.map { it.data.catnum } - settingsRepository.saveSatType(type, catnums) - importedEntries.addAll(satellites) - } + else -> { + // parse csv stream + val parsed = dataParser.parseCSVStream(stream) + val satellites = parsed.map { data -> SatEntry(data) } + val catnums = satellites.map { it.data.catnum } + settingsRepository.saveSatType(type, catnums) + importedEntries.addAll(satellites) } } } - localStorage.insertEntries(importedEntries) - setUpdateSuccessful() - } - repositoryScope.launch(exceptionHandler) { - dataSource.getNetworkStream(settingsRepository.radioSourceUrl)?.let { stream -> - localStorage.insertRadios(dataParser.parseJSONStream(stream)) - } } + jobRadios.await()?.let { importedRadios.addAll(dataParser.parseJSONStream(it)) } + // insert + localStorage.insertEntries(importedEntries) + localStorage.insertRadios(importedRadios) + setUpdateSuccessful(System.currentTimeMillis()) } - override fun setUpdateStateHandled() { - _updateState.value = DataState.Handled + override suspend fun clearAllData() = withContext(dispatcher) { + localStorage.deleteEntries() + localStorage.deleteRadios() + setUpdateSuccessful(0L) } - override fun clearAllData() { - repositoryScope.launch { - _updateState.value = DataState.Loading - delay(updateStateDelay) - localStorage.deleteEntries() - localStorage.deleteRadios() - setUpdateSuccessful(0L) - } - } - - private fun setUpdateSuccessful(updateTime: Long = System.currentTimeMillis()) { - settingsRepository.setLastUpdateTime(updateTime) - _updateState.value = DataState.Success(updateTime) + private suspend fun setUpdateSuccessful(timestamp: Long) = withContext(dispatcher) { + val satellitesTotal = localStorage.getEntriesTotal() + val radiosTotal = localStorage.getRadiosTotal() + settingsRepository.saveDatabaseState(DatabaseState(satellitesTotal, radiosTotal, timestamp)) } private suspend fun importSatellites(stream: InputStream): List { diff --git a/base/src/main/java/com/rtbishop/look4sat/data/ILocalStorage.kt b/base/src/main/java/com/rtbishop/look4sat/data/ILocalStorage.kt index eac86014..0be3378e 100644 --- a/base/src/main/java/com/rtbishop/look4sat/data/ILocalStorage.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/ILocalStorage.kt @@ -21,11 +21,10 @@ import com.rtbishop.look4sat.domain.Satellite import com.rtbishop.look4sat.model.SatEntry import com.rtbishop.look4sat.model.SatItem import com.rtbishop.look4sat.model.SatRadio -import kotlinx.coroutines.flow.Flow interface ILocalStorage { - fun getEntriesTotal(): Flow + suspend fun getEntriesTotal(): Int suspend fun getEntriesList(): List @@ -35,7 +34,7 @@ interface ILocalStorage { suspend fun deleteEntries() - fun getRadiosTotal(): Flow + suspend fun getRadiosTotal(): Int suspend fun getRadiosWithId(id: Int): List diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/IDatabaseRepo.kt b/base/src/main/java/com/rtbishop/look4sat/domain/IDatabaseRepo.kt index c74f38ec..6485c577 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/IDatabaseRepo.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/IDatabaseRepo.kt @@ -17,23 +17,11 @@ */ package com.rtbishop.look4sat.domain -import com.rtbishop.look4sat.model.DataState -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.StateFlow - interface IDatabaseRepo { - val updateState: StateFlow> + suspend fun updateFromFile(uri: String) - fun getEntriesTotal(): Flow + suspend fun updateFromWeb() - fun getRadiosTotal(): Flow - - fun updateFromFile(uri: String) - - fun updateFromWeb() - - fun setUpdateStateHandled() - - fun clearAllData() + suspend fun clearAllData() } diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsRepo.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsRepo.kt index aec77462..e853e722 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsRepo.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsRepo.kt @@ -17,7 +17,9 @@ */ package com.rtbishop.look4sat.domain +import com.rtbishop.look4sat.model.DatabaseState import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.OtherSettings import kotlinx.coroutines.flow.StateFlow interface ISettingsRepo { @@ -72,25 +74,19 @@ interface ISettingsRepo { fun setMinElevation(minElevation: Double) - fun isUtcEnabled(): Boolean + val databaseState: StateFlow - fun setUtcState(value: Boolean) + fun saveDatabaseState(state: DatabaseState) - fun getLastUpdateTime(): Long + val otherSettings: StateFlow - fun setLastUpdateTime(updateTime: Long) + fun toggleUtc(value: Boolean) - fun isUpdateEnabled(): Boolean + fun toggleUpdate(value: Boolean) - fun setUpdateState(value: Boolean) + fun toggleSweep(value: Boolean) - fun isSensorEnabled(): Boolean - - fun setSensorState(value: Boolean) - - fun isSweepEnabled(): Boolean - - fun setSweepState(value: Boolean) + fun toggleSensor(value: Boolean) fun saveModesSelection(modes: List) diff --git a/base/src/main/java/com/rtbishop/look4sat/model/Settings.kt b/base/src/main/java/com/rtbishop/look4sat/model/Settings.kt new file mode 100644 index 00000000..513cedb4 --- /dev/null +++ b/base/src/main/java/com/rtbishop/look4sat/model/Settings.kt @@ -0,0 +1,10 @@ +package com.rtbishop.look4sat.model + +data class OtherSettings( + val utcState: Boolean, + val updateState: Boolean, + val sweepState: Boolean, + val sensorState: Boolean +) + +data class DatabaseState(val entriesTotal: Int, val radiosTotal: Int, val timestamp: Long) diff --git a/build.gradle b/build.gradle index f353a1e2..cab1902a 100644 --- a/build.gradle +++ b/build.gradle @@ -6,13 +6,13 @@ buildscript { kotlin_android_version = '1.8.10' // Android splashscreen_version = '1.0.0' - room_version = '2.5.0' + room_version = '2.5.1' // Compose - activity_compose_version = '1.6.1' - compose_version = '1.3.3' - compose_compiler_version = '1.4.3' + activity_compose_version = '1.7.0' + compose_version = '1.4.0' + compose_compiler_version = '1.4.4' material3_version = '1.0.1' - lifecycle_version = '2.6.0' + lifecycle_version = '2.6.1' navigation_version = '2.5.3' // Utility osmdroid_version = '6.1.14' diff --git a/gradle.properties b/gradle.properties index cc04f364..b08d9e91 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,9 +24,6 @@ android.enableJetifier=false android.nonTransitiveRClass=true android.useAndroidX=true -kapt.include.compile.classpath=true -kapt.incremental.apt=true -kapt.use.worker.api=true kotlin.code.style=official kotlin.daemon.jvm.options=-Xmx4096M kotlin.incremental=true