From 6478ea70f9c1ba234696f926eaf5146c8c7abf25 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 14 May 2025 11:01:55 +0200 Subject: [PATCH] WIP: Sets up overview view model with TodoFileRepository singleton --- app/build.gradle.kts | 2 ++ app/src/main/AndroidManifest.xml | 2 +- .../java/com/dnsc/plaindo/MainActivity.kt | 20 ++++++------ .../com/dnsc/plaindo/PlaindoApplication.kt | 7 ++--- .../dnsc/plaindo/data/TodoFileRepository.kt | 6 +++- .../java/com/dnsc/plaindo/di/TodosModule.kt | 20 ++++++++++++ .../dnsc/plaindo/ui/models/MainViewModel.kt | 18 ----------- .../plaindo/ui/overview/OverviewViewModel.kt | 31 +++++++++++++++++++ .../ui/overview/PlaindoOverviewScreen.kt | 23 ++++++++++++-- gradle/libs.versions.toml | 2 ++ 10 files changed, 92 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/com/dnsc/plaindo/di/TodosModule.kt delete mode 100644 app/src/main/java/com/dnsc/plaindo/ui/models/MainViewModel.kt create mode 100644 app/src/main/java/com/dnsc/plaindo/ui/overview/OverviewViewModel.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3b84159..e3ea10b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -54,6 +54,8 @@ dependencies { implementation(libs.androidx.navigation.compose) implementation(libs.kotlinx.serialization) implementation(libs.hilt.android) + implementation(libs.hilt.navigation) + ksp(libs.hilt.compiler) testImplementation(libs.junit) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1aaf100..c09ce7d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,7 +13,7 @@ android:theme="@style/Theme.Plaindo" tools:targetApi="31"> diff --git a/app/src/main/java/com/dnsc/plaindo/MainActivity.kt b/app/src/main/java/com/dnsc/plaindo/MainActivity.kt index da1acc8..69fd6b1 100644 --- a/app/src/main/java/com/dnsc/plaindo/MainActivity.kt +++ b/app/src/main/java/com/dnsc/plaindo/MainActivity.kt @@ -9,9 +9,11 @@ import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import com.dnsc.plaindo.data.TodoFileRepository import com.dnsc.plaindo.ui.theme.PlaindoTheme +import dagger.hilt.android.AndroidEntryPoint const val TAG = "MainActivity" +@AndroidEntryPoint class MainActivity : ComponentActivity() { private lateinit var todoFileRepository: TodoFileRepository private lateinit var openDocumentLauncher: ActivityResultLauncher> @@ -19,18 +21,7 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // Set up dependencies todoFileRepository = TodoFileRepository(this) - - // Draw content - enableEdgeToEdge() - setContent { - PlaindoTheme { - PlaindoApp() - } - } - - // Handle init tasks openDocumentLauncher = registerForActivityResult( ActivityResultContracts.OpenDocument() ) { uri -> @@ -50,6 +41,13 @@ class MainActivity : ComponentActivity() { // TODO: Move to / listen to button click for this function openDocumentLauncher.launch(arrayOf("text/plain")) + + enableEdgeToEdge() + setContent { + PlaindoTheme { + PlaindoApp() + } + } } } diff --git a/app/src/main/java/com/dnsc/plaindo/PlaindoApplication.kt b/app/src/main/java/com/dnsc/plaindo/PlaindoApplication.kt index c7a2c0f..3d3db37 100644 --- a/app/src/main/java/com/dnsc/plaindo/PlaindoApplication.kt +++ b/app/src/main/java/com/dnsc/plaindo/PlaindoApplication.kt @@ -2,10 +2,7 @@ package com.dnsc.plaindo import android.app.Application import dagger.hilt.android.HiltAndroidApp +import javax.inject.Inject @HiltAndroidApp -class PlaindoApplication: Application() { - override fun onCreate() { - super.onCreate() - } -} \ No newline at end of file +class PlaindoApplication: Application() \ No newline at end of file diff --git a/app/src/main/java/com/dnsc/plaindo/data/TodoFileRepository.kt b/app/src/main/java/com/dnsc/plaindo/data/TodoFileRepository.kt index 8127a53..c0e84c8 100644 --- a/app/src/main/java/com/dnsc/plaindo/data/TodoFileRepository.kt +++ b/app/src/main/java/com/dnsc/plaindo/data/TodoFileRepository.kt @@ -2,12 +2,16 @@ package com.dnsc.plaindo.data import android.content.Context import android.net.Uri +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import java.io.BufferedReader import java.io.InputStreamReader class TodoFileRepository(val context: Context) { var todoFileUri: Uri? = null - val todos: ArrayList = ArrayList() + private val _todos = MutableStateFlow>(emptyList()) + val todos: StateFlow> = _todos.asStateFlow() fun load(uri: Uri) { context.contentResolver.openInputStream(uri)?.use { inputStream -> diff --git a/app/src/main/java/com/dnsc/plaindo/di/TodosModule.kt b/app/src/main/java/com/dnsc/plaindo/di/TodosModule.kt new file mode 100644 index 0000000..2d5e3b8 --- /dev/null +++ b/app/src/main/java/com/dnsc/plaindo/di/TodosModule.kt @@ -0,0 +1,20 @@ +package com.dnsc.plaindo.di + +import android.content.Context +import com.dnsc.plaindo.data.TodoFileRepository +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object TodosModule { + @Provides + @Singleton + fun provideTodoFileRepository(@ApplicationContext context: Context): TodoFileRepository { + return TodoFileRepository(context) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dnsc/plaindo/ui/models/MainViewModel.kt b/app/src/main/java/com/dnsc/plaindo/ui/models/MainViewModel.kt deleted file mode 100644 index 7c16552..0000000 --- a/app/src/main/java/com/dnsc/plaindo/ui/models/MainViewModel.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.dnsc.plaindo.ui.models - -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import com.dnsc.plaindo.data.Todo -import com.dnsc.plaindo.data.TodoFileRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject - -@HiltViewModel -class MainViewModel @Inject constructor( - private val savedStateHandle: SavedStateHandle, - private val todoFileRepository: TodoFileRepository -): ViewModel() { - fun getAllTodos(): List { - return todoFileRepository.todos - } -} \ No newline at end of file diff --git a/app/src/main/java/com/dnsc/plaindo/ui/overview/OverviewViewModel.kt b/app/src/main/java/com/dnsc/plaindo/ui/overview/OverviewViewModel.kt new file mode 100644 index 0000000..26fcf35 --- /dev/null +++ b/app/src/main/java/com/dnsc/plaindo/ui/overview/OverviewViewModel.kt @@ -0,0 +1,31 @@ +package com.dnsc.plaindo.ui.overview + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.dnsc.plaindo.data.Todo +import com.dnsc.plaindo.data.TodoFileRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import javax.inject.Inject + +@HiltViewModel +class OverviewViewModel @Inject constructor( + private val todoFileRepository: TodoFileRepository +) : ViewModel() { + val todosUiState: StateFlow = todoFileRepository.todos + .map { todos -> OverviewUiState.Success(todos) } + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5000), + initialValue = OverviewUiState.Loading + ) +} + +sealed interface OverviewUiState { + data object Loading : OverviewUiState + data class Success(val todos: List) : OverviewUiState + data class Error(val message: String) : OverviewUiState // Optional error state +} \ No newline at end of file diff --git a/app/src/main/java/com/dnsc/plaindo/ui/overview/PlaindoOverviewScreen.kt b/app/src/main/java/com/dnsc/plaindo/ui/overview/PlaindoOverviewScreen.kt index d1137c6..331de2a 100644 --- a/app/src/main/java/com/dnsc/plaindo/ui/overview/PlaindoOverviewScreen.kt +++ b/app/src/main/java/com/dnsc/plaindo/ui/overview/PlaindoOverviewScreen.kt @@ -5,15 +5,32 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.compose.runtime.getValue import androidx.navigation.NavHostController -import com.dnsc.plaindo.ui.models.MainViewModel @Composable -fun PlaindoOverviewScreen(navController: NavHostController, innerPadding: PaddingValues) { - val mainViewModel: MainViewModel = hiltViewModel() +fun PlaindoOverviewScreen(navController: NavHostController, innerPadding: PaddingValues, viewModel: OverviewViewModel = hiltViewModel()) { + val uiState by viewModel.todosUiState.collectAsState() Column(modifier = Modifier.padding(innerPadding)) { Text(text = "Overview") } + + /*when (uiState) { + OverviewUiState.Loading -> { + // Show a loading indicator + // ... + } + is OverviewUiState.Success -> { + // Display the list of todos + TodoList(todos = uiState.todos) + } + is OverviewUiState.Error -> { + // Show an error message + // ... + } + }*/ } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f3a251a..b4268e8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,7 @@ navigationCompose = "2.8.9" kotlinxSerialization = "1.7.3" hilt = "2.56.2" ksp = "2.1.20-2.0.1" +hiltNavigation = "1.2.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -32,6 +33,7 @@ androidx-material3 = { group = "androidx.compose.material3", name = "material3" kotlinx-serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" } hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } +hilt-navigation = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigation" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }