WIP: Sets up overview view model with TodoFileRepository singleton
This commit is contained in:
parent
2da2e011bc
commit
6478ea70f9
10 changed files with 92 additions and 39 deletions
|
|
@ -54,6 +54,8 @@ dependencies {
|
||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation(libs.kotlinx.serialization)
|
implementation(libs.kotlinx.serialization)
|
||||||
implementation(libs.hilt.android)
|
implementation(libs.hilt.android)
|
||||||
|
implementation(libs.hilt.navigation)
|
||||||
|
|
||||||
ksp(libs.hilt.compiler)
|
ksp(libs.hilt.compiler)
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
android:theme="@style/Theme.Plaindo"
|
android:theme="@style/Theme.Plaindo"
|
||||||
tools:targetApi="31">
|
tools:targetApi="31">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".PlaindoApplication"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/Theme.Plaindo">
|
android:theme="@style/Theme.Plaindo">
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,11 @@ import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import com.dnsc.plaindo.data.TodoFileRepository
|
import com.dnsc.plaindo.data.TodoFileRepository
|
||||||
import com.dnsc.plaindo.ui.theme.PlaindoTheme
|
import com.dnsc.plaindo.ui.theme.PlaindoTheme
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
const val TAG = "MainActivity"
|
const val TAG = "MainActivity"
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
private lateinit var todoFileRepository: TodoFileRepository
|
private lateinit var todoFileRepository: TodoFileRepository
|
||||||
private lateinit var openDocumentLauncher: ActivityResultLauncher<Array<String>>
|
private lateinit var openDocumentLauncher: ActivityResultLauncher<Array<String>>
|
||||||
|
|
@ -19,18 +21,7 @@ class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
// Set up dependencies
|
|
||||||
todoFileRepository = TodoFileRepository(this)
|
todoFileRepository = TodoFileRepository(this)
|
||||||
|
|
||||||
// Draw content
|
|
||||||
enableEdgeToEdge()
|
|
||||||
setContent {
|
|
||||||
PlaindoTheme {
|
|
||||||
PlaindoApp()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle init tasks
|
|
||||||
openDocumentLauncher = registerForActivityResult(
|
openDocumentLauncher = registerForActivityResult(
|
||||||
ActivityResultContracts.OpenDocument()
|
ActivityResultContracts.OpenDocument()
|
||||||
) { uri ->
|
) { uri ->
|
||||||
|
|
@ -50,6 +41,13 @@ class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
// TODO: Move to / listen to button click for this function
|
// TODO: Move to / listen to button click for this function
|
||||||
openDocumentLauncher.launch(arrayOf("text/plain"))
|
openDocumentLauncher.launch(arrayOf("text/plain"))
|
||||||
|
|
||||||
|
enableEdgeToEdge()
|
||||||
|
setContent {
|
||||||
|
PlaindoTheme {
|
||||||
|
PlaindoApp()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,7 @@ package com.dnsc.plaindo
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class PlaindoApplication: Application() {
|
class PlaindoApplication: Application()
|
||||||
override fun onCreate() {
|
|
||||||
super.onCreate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,12 +2,16 @@ package com.dnsc.plaindo.data
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
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.BufferedReader
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
|
||||||
class TodoFileRepository(val context: Context) {
|
class TodoFileRepository(val context: Context) {
|
||||||
var todoFileUri: Uri? = null
|
var todoFileUri: Uri? = null
|
||||||
val todos: ArrayList<Todo> = ArrayList()
|
private val _todos = MutableStateFlow<List<Todo>>(emptyList())
|
||||||
|
val todos: StateFlow<List<Todo>> = _todos.asStateFlow()
|
||||||
|
|
||||||
fun load(uri: Uri) {
|
fun load(uri: Uri) {
|
||||||
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||||
|
|
|
||||||
20
app/src/main/java/com/dnsc/plaindo/di/TodosModule.kt
Normal file
20
app/src/main/java/com/dnsc/plaindo/di/TodosModule.kt
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<Todo> {
|
|
||||||
return todoFileRepository.todos
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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<OverviewUiState> = 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<Todo>) : OverviewUiState
|
||||||
|
data class Error(val message: String) : OverviewUiState // Optional error state
|
||||||
|
}
|
||||||
|
|
@ -5,15 +5,32 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import com.dnsc.plaindo.ui.models.MainViewModel
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PlaindoOverviewScreen(navController: NavHostController, innerPadding: PaddingValues) {
|
fun PlaindoOverviewScreen(navController: NavHostController, innerPadding: PaddingValues, viewModel: OverviewViewModel = hiltViewModel()) {
|
||||||
val mainViewModel: MainViewModel = hiltViewModel()
|
val uiState by viewModel.todosUiState.collectAsState()
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(innerPadding)) {
|
Column(modifier = Modifier.padding(innerPadding)) {
|
||||||
Text(text = "Overview")
|
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
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ navigationCompose = "2.8.9"
|
||||||
kotlinxSerialization = "1.7.3"
|
kotlinxSerialization = "1.7.3"
|
||||||
hilt = "2.56.2"
|
hilt = "2.56.2"
|
||||||
ksp = "2.1.20-2.0.1"
|
ksp = "2.1.20-2.0.1"
|
||||||
|
hiltNavigation = "1.2.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
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" }
|
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-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
|
||||||
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", 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]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|
|
||||||
Reference in a new issue