Replaced Google Hilt with manual DI

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:33 +00:00
1 parent 622d4e3632
commit 4c13cc98a1
17 files changed
+231 -148

No files matched your search

+8 -23
View File
@@ -1,12 +1,11 @@
plugins {
id "com.android.application"
id "com.google.devtools.ksp"
id "org.jetbrains.kotlin.android"
id "org.jetbrains.kotlin.kapt"
id "dagger.hilt.android.plugin"
}
android {
namespace 'com.rtbishop.look4sat'
namespace "com.rtbishop.look4sat"
compileSdk 33
defaultConfig {
@@ -14,20 +13,9 @@ android {
minSdk 21
targetSdk 33
versionCode 312
versionName '3.1.2'
versionName "3.1.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas")
arg("room.incremental", "true")
arg("room.expandProjection", "true")
}
correctErrorTypes true
}
}
buildFeatures {
compose true
@@ -40,14 +28,14 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
composeOptions {
kotlinCompilerExtensionVersion compose_compiler_version
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
jvmTarget = JavaVersion.VERSION_17.toString()
}
packagingOptions {
resources {
@@ -61,7 +49,7 @@ android {
}
kotlin {
jvmToolchain(11)
jvmToolchain(17)
}
dependencies {
@@ -70,9 +58,7 @@ dependencies {
implementation "androidx.core:core-splashscreen:$splashscreen_version"
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "com.google.dagger:hilt-android:$hilt_android_version"
kapt "com.google.dagger:hilt-compiler:$hilt_android_version"
ksp "androidx.room:room-compiler:$room_version"
// Compose
implementation "androidx.activity:activity-compose:$activity_compose_version"
implementation "androidx.compose.animation:animation:$compose_version"
@@ -81,7 +67,6 @@ dependencies {
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.hilt:hilt-navigation-compose:$hilt_compose_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
implementation "androidx.navigation:navigation-compose:$navigation_version"
// Utility
@@ -25,9 +25,7 @@ import androidx.activity.compose.setContent
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.rtbishop.look4sat.presentation.MainScreen
import com.rtbishop.look4sat.presentation.MainTheme
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -18,25 +18,18 @@
package com.rtbishop.look4sat
import android.app.Application
import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ISettingsRepository
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber
import java.text.SimpleDateFormat
import java.util.*
import javax.inject.Inject
import java.util.Date
import java.util.Locale
@HiltAndroidApp
class MainApplication : Application() {
@Inject
lateinit var dataRepository: IDataRepository
@Inject
lateinit var settingsRepository: ISettingsRepository
lateinit var container: MainContainer
override fun onCreate() {
super.onCreate()
container = MainContainer(this)
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
@@ -44,12 +37,13 @@ class MainApplication : Application() {
}
private fun checkAutoUpdate() {
val settingsRepository = container.settingsRepository
if (settingsRepository.isUpdateEnabled()) {
val timeDelta = System.currentTimeMillis() - settingsRepository.getLastUpdateTime()
if (timeDelta > 172800000) { // 48 hours in ms
val sdf = SimpleDateFormat("d MMM yyyy - HH:mm:ss", Locale.getDefault())
Timber.d("Started periodic data update on ${sdf.format(Date())}")
dataRepository.updateFromWeb()
container.dataRepository.updateFromWeb()
}
}
}
@@ -1,20 +1,3 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2022 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat
import android.bluetooth.BluetoothManager
@@ -26,45 +9,43 @@ import androidx.room.Room
import com.rtbishop.look4sat.data.DataParser
import com.rtbishop.look4sat.data.DataRepository
import com.rtbishop.look4sat.data.SatelliteRepository
import com.rtbishop.look4sat.domain.*
import com.rtbishop.look4sat.framework.*
import com.rtbishop.look4sat.framework.data.*
import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ISatelliteRepository
import com.rtbishop.look4sat.domain.ISensorRepository
import com.rtbishop.look4sat.domain.ISettingsRepository
import com.rtbishop.look4sat.framework.BluetoothReporter
import com.rtbishop.look4sat.framework.NetworkReporter
import com.rtbishop.look4sat.framework.SensorRepository
import com.rtbishop.look4sat.framework.SettingsRepository
import com.rtbishop.look4sat.framework.data.MIGRATION_1_2
import com.rtbishop.look4sat.framework.data.MainDatabase
import com.rtbishop.look4sat.framework.data.local.EntriesStorage
import com.rtbishop.look4sat.framework.data.local.RadiosStorage
import com.rtbishop.look4sat.framework.data.remote.FileSource
import com.rtbishop.look4sat.framework.data.remote.NetworkSource
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object MainModule {
class MainContainer(private val context: Context) {
@Provides
@Singleton
fun provideBluetoothReporter(@ApplicationContext context: Context): BluetoothReporter {
val bluetoothReporter = provideBluetoothReporter()
val networkReporter = provideNetworkReporter()
val settingsRepository = provideSettingsRepository()
val dataRepository = provideDataRepository(settingsRepository)
val sensorRepository = provideSensorRepository()
val satelliteRepository = provideSatelliteRepository()
private fun provideBluetoothReporter(): BluetoothReporter {
val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
return BluetoothReporter(manager, CoroutineScope(Dispatchers.IO))
}
@Provides
@Singleton
fun provideNetworkReporter(): NetworkReporter {
private fun provideNetworkReporter(): NetworkReporter {
return NetworkReporter(CoroutineScope(Dispatchers.IO))
}
@Provides
@Singleton
fun provideDataRepository(
@ApplicationContext context: Context, settings: ISettingsRepository
): IDataRepository {
private fun provideDataRepository(settings: ISettingsRepository): IDataRepository {
val db = Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb")
.addMigrations(MIGRATION_1_2).fallbackToDestructiveMigration().build()
val parser = DataParser(Dispatchers.Default)
@@ -76,23 +57,17 @@ object MainModule {
return DataRepository(parser, fileSource, entries, radios, remoteSource, scope, settings)
}
@Provides
@Singleton
fun provideSensorRepository(@ApplicationContext context: Context): ISensorRepository {
private fun provideSensorRepository(): ISensorRepository {
val manager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensor = manager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
return SensorRepository(manager, sensor)
}
@Provides
@Singleton
fun provideSatelliteRepository(): ISatelliteRepository {
private fun provideSatelliteRepository(): ISatelliteRepository {
return SatelliteRepository(Dispatchers.Default)
}
@Provides
@Singleton
fun provideSettingsRepository(@ApplicationContext context: Context): ISettingsRepository {
private fun provideSettingsRepository(): ISettingsRepository {
val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE)
return SettingsRepository(manager, preferences)
@@ -26,7 +26,7 @@ import com.rtbishop.look4sat.framework.data.dao.RadiosDao
import com.rtbishop.look4sat.framework.model.SatEntry
import com.rtbishop.look4sat.framework.model.SatRadio
@Database(entities = [SatEntry::class, SatRadio::class], version = 2, exportSchema = true)
@Database(entities = [SatEntry::class, SatRadio::class], version = 2)
abstract class MainDatabase : RoomDatabase() {
abstract fun entriesDao(): EntriesDao
@@ -21,7 +21,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.model.DataState
import com.rtbishop.look4sat.model.SatItem
@@ -31,7 +31,8 @@ import com.rtbishop.look4sat.presentation.dialogs.TypesDialog
import com.rtbishop.look4sat.presentation.onClick
@Composable
fun EntriesScreen(navToPasses: () -> Unit, viewModel: EntriesViewModel = hiltViewModel()) {
fun EntriesScreen(navToPasses: () -> Unit) {
val viewModel = viewModel(EntriesViewModel::class.java, factory = EntriesViewModel.Factory)
val state = viewModel.satData.collectAsState(initial = DataState.Loading)
val showDialog = rememberSaveable { mutableStateOf(false) }
@@ -227,6 +228,7 @@ fun EntriesCard(state: DataState<List<SatItem>>, onSelected: (List<Int>, Boolean
}
}
}
else -> CardLoadingIndicator()
}
}
@@ -18,23 +18,24 @@
package com.rtbishop.look4sat.presentation.entries
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.rtbishop.look4sat.MainApplication
import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ISatelliteRepository
import com.rtbishop.look4sat.domain.ISettingsRepository
import com.rtbishop.look4sat.model.DataState
import com.rtbishop.look4sat.model.SatItem
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.util.*
import javax.inject.Inject
@OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel
class EntriesViewModel @Inject constructor(
class EntriesViewModel(
private val dataRepository: IDataRepository,
private val satelliteRepository: ISatelliteRepository,
private val settingsRepository: ISettingsRepository
@@ -113,4 +114,18 @@ class EntriesViewModel @Inject constructor(
}
}
}
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY
initializer {
val container = (this[applicationKey] as MainApplication).container
EntriesViewModel(
container.dataRepository,
container.satelliteRepository,
container.settingsRepository
)
}
}
}
}
@@ -1,7 +1,13 @@
package com.rtbishop.look4sat.presentation.map
import android.content.Context
import android.graphics.*
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import androidx.compose.foundation.layout.Arrangement
@@ -19,9 +25,9 @@ import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.Satellite
import com.rtbishop.look4sat.model.GeoPos
@@ -59,7 +65,8 @@ private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
private val labelRect = Rect()
@Composable
fun MapScreen(viewModel: MapViewModel = hiltViewModel()) {
fun MapScreen() {
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
val context = LocalContext.current
val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE)
Configuration.getInstance().load(context, preferences)
@@ -18,7 +18,11 @@
package com.rtbishop.look4sat.presentation.map
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.rtbishop.look4sat.MainApplication
import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ISatelliteRepository
import com.rtbishop.look4sat.domain.ISettingsRepository
@@ -28,19 +32,20 @@ import com.rtbishop.look4sat.model.SatPos
import com.rtbishop.look4sat.utility.QthConverter
import com.rtbishop.look4sat.utility.toDegrees
import com.rtbishop.look4sat.utility.toTimerString
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.flow
import java.util.*
import javax.inject.Inject
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.util.Date
import kotlin.collections.set
import kotlin.math.max
import kotlin.math.min
@HiltViewModel
class MapViewModel @Inject constructor(
class MapViewModel(
private val dataRepository: IDataRepository,
private val satelliteRepository: ISatelliteRepository,
private val settingsRepository: ISettingsRepository
@@ -221,4 +226,18 @@ class MapViewModel @Inject constructor(
private fun clip(currentValue: Double, minValue: Double, maxValue: Double): Double {
return min(max(currentValue, minValue), maxValue)
}
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY
initializer {
val container = (this[applicationKey] as MainApplication).container
MapViewModel(
container.dataRepository,
container.satelliteRepository,
container.settingsRepository
)
}
}
}
}
@@ -20,7 +20,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.*
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.NearEarthSatellite
import com.rtbishop.look4sat.model.DataState
@@ -38,7 +38,8 @@ import java.util.*
private val sdf = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
@Composable
fun PassesScreen(navToRadar: (Int, Long) -> Unit, viewModel: PassesViewModel = hiltViewModel()) {
fun PassesScreen(navToRadar: (Int, Long) -> Unit) {
val viewModel = viewModel(PassesViewModel::class.java, factory = PassesViewModel.Factory)
val state = viewModel.passes.collectAsState(initial = null)
val timerText = viewModel.timerText.collectAsState(initial = null)
val isRefreshing = state.value is DataState.Loading
@@ -18,21 +18,26 @@
package com.rtbishop.look4sat.presentation.passes
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.rtbishop.look4sat.MainApplication
import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ISatelliteRepository
import com.rtbishop.look4sat.domain.ISettingsRepository
import com.rtbishop.look4sat.model.DataState
import com.rtbishop.look4sat.model.SatPass
import com.rtbishop.look4sat.utility.toTimerString
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
@HiltViewModel
class PassesViewModel @Inject constructor(
class PassesViewModel(
private val dataRepository: IDataRepository,
private val satelliteRepository: ISatelliteRepository,
private val settingsRepository: ISettingsRepository
@@ -113,4 +118,18 @@ class PassesViewModel @Inject constructor(
)
}
}
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY
initializer {
val container = (this[applicationKey] as MainApplication).container
PassesViewModel(
container.dataRepository,
container.satelliteRepository,
container.settingsRepository
)
}
}
}
}
@@ -1,10 +1,21 @@
package com.rtbishop.look4sat.presentation.radar
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
@@ -16,12 +27,13 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.model.SatRadio
@Composable
fun RadarScreen(viewModel: RadarViewModel = hiltViewModel()) {
fun RadarScreen() {
val viewModel = viewModel(RadarViewModel::class.java, factory = RadarViewModel.Factory)
val currentPass = viewModel.getPass().collectAsState(null)
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
@@ -55,9 +67,11 @@ fun RadarScreen(viewModel: RadarViewModel = hiltViewModel()) {
)
}
}
ElevatedCard(modifier = Modifier
ElevatedCard(
modifier = Modifier
.fillMaxSize()
.weight(1f)) {
.weight(1f)
) {
viewModel.radarData.value?.let { data ->
RadarViewCompose(
item = data.satPos,
@@ -66,9 +80,11 @@ fun RadarScreen(viewModel: RadarViewModel = hiltViewModel()) {
)
}
}
ElevatedCard(modifier = Modifier
ElevatedCard(
modifier = Modifier
.fillMaxSize()
.weight(1f)) {
.weight(1f)
) {
TransmittersList(transmitters = viewModel.transmitters.value)
}
}
@@ -93,7 +109,10 @@ private fun TransmitterItem(radio: SatRadio) {
.background(MaterialTheme.colorScheme.surface)
.padding(6.dp)
) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Icon(
painter = painterResource(id = R.drawable.ic_next),
contentDescription = null, modifier = Modifier.rotate(180f)
@@ -22,8 +22,17 @@ import android.util.Log
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.createSavedStateHandle
import androidx.lifecycle.viewModelScope
import com.rtbishop.look4sat.domain.*
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.rtbishop.look4sat.MainApplication
import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ISatelliteRepository
import com.rtbishop.look4sat.domain.ISensorRepository
import com.rtbishop.look4sat.domain.ISettingsRepository
import com.rtbishop.look4sat.domain.Satellite
import com.rtbishop.look4sat.framework.BluetoothReporter
import com.rtbishop.look4sat.framework.NetworkReporter
import com.rtbishop.look4sat.model.GeoPos
@@ -32,15 +41,12 @@ import com.rtbishop.look4sat.model.SatPos
import com.rtbishop.look4sat.model.SatRadio
import com.rtbishop.look4sat.utility.round
import com.rtbishop.look4sat.utility.toDegrees
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class RadarViewModel @Inject constructor(
class RadarViewModel(
private val bluetoothReporter: BluetoothReporter,
private val networkReporter: NetworkReporter,
private val savedStateHandle: SavedStateHandle,
@@ -149,4 +155,23 @@ class RadarViewModel @Inject constructor(
transmitters.value = list
}
}
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY
initializer {
val savedStateHandle = createSavedStateHandle()
val container = (this[applicationKey] as MainApplication).container
RadarViewModel(
container.bluetoothReporter,
container.networkReporter,
savedStateHandle,
container.dataRepository,
container.satelliteRepository,
container.sensorRepository,
container.settingsRepository
)
}
}
}
}
@@ -4,9 +4,22 @@ import android.Manifest
import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.*
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
@@ -21,7 +34,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.BuildConfig
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.model.GeoPos
@@ -32,7 +45,8 @@ import com.rtbishop.look4sat.presentation.dialogs.PositionDialog
import com.rtbishop.look4sat.presentation.gotoUrl
import com.rtbishop.look4sat.presentation.showToast
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale
private const val POLICY_URL = "https://sites.google.com/view/look4sat-privacy-policy/home"
private const val LICENSE_URL = "https://www.gnu.org/licenses/gpl-3.0.html"
@@ -41,7 +55,8 @@ private const val DONATE_URL = "https://ko-fi.com/rt_bishop"
private const val FDROID_URL = "https://f-droid.org/en/packages/com.rtbishop.look4sat/"
@Composable
fun SettingsScreen(viewModel: SettingsViewModel = hiltViewModel()) {
fun SettingsScreen() {
val viewModel = viewModel(SettingsViewModel::class.java, factory = SettingsViewModel.Factory)
val context = LocalContext.current
// Permissions setup
@@ -19,20 +19,20 @@ package com.rtbishop.look4sat.presentation.settings
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.rtbishop.look4sat.MainApplication
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.IDataRepository
import com.rtbishop.look4sat.domain.ISettingsRepository
import com.rtbishop.look4sat.model.DataState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class SettingsViewModel @Inject constructor(
private val dataRepository: IDataRepository,
private val settingsRepository: ISettingsRepository
class SettingsViewModel(
private val dataRepository: IDataRepository, private val settingsRepository: ISettingsRepository
) : ViewModel() {
private val defaultLocationSettings = LocationSettings(false,
@@ -157,4 +157,14 @@ class SettingsViewModel @Inject constructor(
// fun setBTDeviceName(value: String) = settings.setBTDeviceName(value)
// fun getBTDeviceAddr(): String = settings.getBTDeviceAddr()
// fun setBTDeviceAddr(value: String) = settings.setBTDeviceAddr(value)
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
val applicationKey = ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY
initializer {
val container = (this[applicationKey] as MainApplication).container
SettingsViewModel(container.dataRepository, container.settingsRepository)
}
}
}
}
+10 -11
View File
@@ -1,9 +1,9 @@
buildscript {
ext {
application_version = '7.4.2'
library_version = '7.1.2'
gradle_plugin_version = '7.4.2'
library_plugin_version = '7.1.2'
ksp_version = '1.8.10-1.0.9'
kotlin_android_version = '1.8.10'
hilt_android_version = '2.45'
// Android
splashscreen_version = '1.0.0'
room_version = '2.5.0'
@@ -12,28 +12,27 @@ buildscript {
compose_version = '1.3.3'
compose_compiler_version = '1.4.3'
material3_version = '1.0.1'
hilt_compose_version = '1.0.0'
lifecycle_version = '2.5.1'
lifecycle_version = '2.6.0'
navigation_version = '2.5.3'
// Utility
timber_version = '5.0.1'
osmdroid_version = '6.1.14'
json_version = '20220924'
json_version = '20230227'
leakcanary_version = '2.10'
// Test
junit_version = '4.13.2'
mockito_version = '5.1.1'
mockito_version = '5.2.0'
coroutines_test_version = '1.6.4'
}
}
plugins {
id "com.android.application" version "$application_version" apply false
id "com.android.library" version "$library_version" apply false
id "com.android.application" version "$gradle_plugin_version" apply false
id "com.android.library" version "$library_plugin_version" apply false
id "com.google.devtools.ksp" version "$ksp_version" apply false
id "org.jetbrains.kotlin.android" version "$kotlin_android_version" apply false
id "com.google.dagger.hilt.android" version "$hilt_android_version" apply false
}
task clean(type: Delete) {
tasks.register('clean', Delete) {
delete rootProject.buildDir
}
+3 -3
View File
@@ -1,6 +1,6 @@
#Fri Feb 17 17:52:48 GMT 2023
#Mon Mar 20 10:37:41 GMT 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists