Xaver
1 week ago
17 changed files with 561 additions and 49 deletions
@ -0,0 +1,24 @@ |
|||||||
|
package at.xaxa.demonstrator2 |
||||||
|
|
||||||
|
import android.app.Application |
||||||
|
import at.xaxa.demonstrator2.data.TaskRepository |
||||||
|
import at.xaxa.demonstrator2.data.db.TaskDatabase |
||||||
|
import kotlinx.serialization.json.Json |
||||||
|
import okhttp3.MediaType |
||||||
|
import retrofit2.Retrofit |
||||||
|
import retrofit2.converter.kotlinx.serialization.asConverterFactory |
||||||
|
|
||||||
|
|
||||||
|
class TaskApplication : Application() { |
||||||
|
|
||||||
|
val taskRepository by lazy { |
||||||
|
val retrofit = Retrofit.Builder() |
||||||
|
.baseUrl("https://my-json-server.typicode.com/GithubGenericUsername/find-your-pet/") |
||||||
|
.addConverterFactory(Json { ignoreUnknownKeys = true }.asConverterFactory(MediaType.get("application/json"))) |
||||||
|
.build() |
||||||
|
|
||||||
|
TaskRepository( |
||||||
|
TaskDatabase.getDatabase(this).TaskDao() |
||||||
|
) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
package at.xaxa.demonstrator2.data |
||||||
|
|
||||||
|
data class Task( |
||||||
|
val id: Int, |
||||||
|
val name :String, |
||||||
|
val details: String |
||||||
|
); |
@ -0,0 +1,42 @@ |
|||||||
|
package at.xaxa.demonstrator2.data |
||||||
|
|
||||||
|
import android.util.Log |
||||||
|
import at.xaxa.demonstrator2.data.db.TaskDao |
||||||
|
import at.xaxa.demonstrator2.data.db.TaskEntity |
||||||
|
import kotlinx.coroutines.flow.Flow |
||||||
|
import kotlinx.coroutines.flow.map |
||||||
|
|
||||||
|
class TaskRepository(private val taskDao: TaskDao) { |
||||||
|
|
||||||
|
fun getAllTasks(): Flow<List<Task>> { |
||||||
|
return taskDao.getAllTasks().map { |
||||||
|
it.map {item -> Task(item._id, item.name, item.details) } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
suspend fun getTaskById(id: Int): Task { |
||||||
|
val item = taskDao.getTaskById(id) |
||||||
|
return Task(item._id, item.name, item.details) |
||||||
|
} |
||||||
|
|
||||||
|
suspend fun addTask(task: Task) { |
||||||
|
taskDao.addTask(TaskEntity(_id=0, task.name, task.details)) |
||||||
|
} |
||||||
|
|
||||||
|
suspend fun updateTask(task: Task) { |
||||||
|
taskDao.updateTask(TaskEntity(task.id, task.name, task.details)) |
||||||
|
} |
||||||
|
|
||||||
|
suspend fun addRandomTask() { |
||||||
|
val randomTask:String = tasks.random() |
||||||
|
addTask(Task(0, randomTask, "Wow I have to ${randomTask.lowercase()}")) |
||||||
|
} |
||||||
|
|
||||||
|
val tasks = listOf( |
||||||
|
"Buy Milk", |
||||||
|
"Mow lawn", |
||||||
|
"Chill", |
||||||
|
"Drink Water" |
||||||
|
) |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package at.xaxa.demonstrator2.data.db |
||||||
|
|
||||||
|
import androidx.room.Dao |
||||||
|
import androidx.room.Delete |
||||||
|
import androidx.room.Insert |
||||||
|
import androidx.room.Query |
||||||
|
import androidx.room.Update |
||||||
|
import kotlinx.coroutines.flow.Flow |
||||||
|
|
||||||
|
@Dao |
||||||
|
interface TaskDao { |
||||||
|
@Insert |
||||||
|
suspend fun addTask(taskEntity: TaskEntity) |
||||||
|
|
||||||
|
@Update |
||||||
|
suspend fun updateTask(taskEntity: TaskEntity) |
||||||
|
|
||||||
|
@Delete |
||||||
|
suspend fun deleteTask(taskEntity: TaskEntity) |
||||||
|
|
||||||
|
@Query("SELECT * from tasks") |
||||||
|
fun getAllTasks(): Flow<List<TaskEntity>> |
||||||
|
|
||||||
|
@Query("SELECT * FROM tasks WHERE _id = :id") |
||||||
|
suspend fun getTaskById(id: Int): TaskEntity |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package at.xaxa.demonstrator2.data.db |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import androidx.room.Database |
||||||
|
import androidx.room.Room |
||||||
|
import androidx.room.RoomDatabase |
||||||
|
|
||||||
|
@Database(entities = [TaskEntity::class], version = 1) |
||||||
|
abstract class TaskDatabase : RoomDatabase() { |
||||||
|
abstract fun TaskDao(): TaskDao |
||||||
|
|
||||||
|
companion object { |
||||||
|
@Volatile |
||||||
|
private var Instance: TaskDatabase? = null |
||||||
|
|
||||||
|
fun getDatabase(context: Context): TaskDatabase { |
||||||
|
// if the Instance is not null, return it, otherwise create a new database instance. |
||||||
|
return Instance ?: synchronized(this) { |
||||||
|
val instance = Room.databaseBuilder(context, TaskDatabase::class.java, "task_database") |
||||||
|
/** |
||||||
|
* Setting this option in your app's database builder means that Room |
||||||
|
* permanently deletes all data from the tables in your database when it |
||||||
|
* attempts to perform a migration with no defined migration path. |
||||||
|
*/ |
||||||
|
.fallbackToDestructiveMigration() |
||||||
|
.build() |
||||||
|
Instance = instance |
||||||
|
return instance |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
package at.xaxa.demonstrator2.data.db |
||||||
|
|
||||||
|
import androidx.room.Entity |
||||||
|
|
||||||
|
@Entity(tableName = "tasks") |
||||||
|
data class TaskEntity( |
||||||
|
val _id: Int = 0, |
||||||
|
val name :String, |
||||||
|
val details: String = "empty" |
||||||
|
) |
@ -0,0 +1,23 @@ |
|||||||
|
package at.xaxa.demonstrator2.ui |
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY |
||||||
|
import androidx.lifecycle.createSavedStateHandle |
||||||
|
import androidx.lifecycle.viewmodel.initializer |
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory |
||||||
|
import at.xaxa.demonstrator2.TaskApplication |
||||||
|
|
||||||
|
object AppViewModelProvider { |
||||||
|
val Factory = viewModelFactory { |
||||||
|
initializer { |
||||||
|
DemoViewModel((this[APPLICATION_KEY] as TaskApplication).taskRepository) |
||||||
|
} |
||||||
|
|
||||||
|
initializer { |
||||||
|
DemoDetailsViewModel(this.createSavedStateHandle(), (this[APPLICATION_KEY] as TaskApplication).taskRepository) |
||||||
|
} |
||||||
|
|
||||||
|
initializer { |
||||||
|
DemoDetailsViewModel(this.createSavedStateHandle(), (this[APPLICATION_KEY] as TaskApplication).taskRepository) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package at.xaxa.demonstrator2.ui |
||||||
|
|
||||||
|
import androidx.lifecycle.SavedStateHandle |
||||||
|
import androidx.lifecycle.ViewModel |
||||||
|
import androidx.lifecycle.viewModelScope |
||||||
|
import at.xaxa.demonstrator2.data.Task |
||||||
|
import at.xaxa.demonstrator2.data.TaskRepository |
||||||
|
import kotlinx.coroutines.Dispatchers |
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow |
||||||
|
import kotlinx.coroutines.flow.asStateFlow |
||||||
|
import kotlinx.coroutines.flow.update |
||||||
|
import kotlinx.coroutines.launch |
||||||
|
import kotlinx.coroutines.withContext |
||||||
|
|
||||||
|
data class TaskDetailUi( |
||||||
|
val task: Task = Task(0, "", "") |
||||||
|
) |
||||||
|
|
||||||
|
class DemoDetailsViewModel(savedStateHandle: SavedStateHandle, private val taskRepository: TaskRepository): ViewModel() { |
||||||
|
|
||||||
|
private val taskId: Int = checkNotNull(savedStateHandle["taskId"]) |
||||||
|
|
||||||
|
private val _detailUiState = MutableStateFlow(TaskDetailUi()) |
||||||
|
val detailUiState = _detailUiState.asStateFlow() |
||||||
|
|
||||||
|
init { |
||||||
|
viewModelScope.launch { |
||||||
|
val task = withContext(Dispatchers.IO) { |
||||||
|
taskRepository.getTaskById(taskId) |
||||||
|
} |
||||||
|
_detailUiState.update { |
||||||
|
TaskDetailUi(task) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,177 @@ |
|||||||
|
package at.xaxa.demonstrator2.ui |
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box |
||||||
|
import androidx.compose.foundation.layout.Column |
||||||
|
import androidx.compose.foundation.layout.Row |
||||||
|
import androidx.compose.foundation.layout.Spacer |
||||||
|
import androidx.compose.foundation.layout.fillMaxSize |
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth |
||||||
|
import androidx.compose.foundation.layout.padding |
||||||
|
import androidx.compose.foundation.layout.width |
||||||
|
import androidx.compose.foundation.lazy.LazyColumn |
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed |
||||||
|
import androidx.compose.material.icons.Icons |
||||||
|
import androidx.compose.material.icons.automirrored.filled.List |
||||||
|
import androidx.compose.material.icons.filled.Add |
||||||
|
import androidx.compose.material.icons.outlined.Edit |
||||||
|
import androidx.compose.material3.Icon |
||||||
|
import androidx.compose.material3.IconButton |
||||||
|
import androidx.compose.material3.NavigationBarItem |
||||||
|
import androidx.compose.material3.OutlinedCard |
||||||
|
import androidx.compose.material3.Scaffold |
||||||
|
import androidx.compose.material3.Text |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.ui.Alignment |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import androidx.compose.ui.tooling.preview.Preview |
||||||
|
import androidx.compose.ui.unit.dp |
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle |
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel |
||||||
|
import androidx.navigation.NavType |
||||||
|
import androidx.navigation.compose.NavHost |
||||||
|
import androidx.navigation.compose.composable |
||||||
|
import androidx.navigation.compose.currentBackStackEntryAsState |
||||||
|
import androidx.navigation.compose.rememberNavController |
||||||
|
import androidx.navigation.navArgument |
||||||
|
import at.xaxa.demonstrator2.data.Task |
||||||
|
import at.xaxa.demonstrator2.ui.edit.TaskEditScreen |
||||||
|
import at.xaxa.demonstrator2.ui.theme.Typography |
||||||
|
|
||||||
|
enum class DemoRoutes(val route: String) { |
||||||
|
List("list"), |
||||||
|
Add("add"), |
||||||
|
Detail("task/{taskId}"), |
||||||
|
Edit("task/{taskId}/edit") |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun DemoApp(modifier: Modifier = Modifier) { |
||||||
|
val navController = rememberNavController() |
||||||
|
|
||||||
|
Scaffold( |
||||||
|
bottomBar = { |
||||||
|
androidx.compose.material3.NavigationBar { |
||||||
|
NavigationBarItem( |
||||||
|
icon = { Icon(Icons.AutoMirrored.Filled.List, contentDescription = "List") }, |
||||||
|
label = { Text("List") }, |
||||||
|
selected = navController.currentBackStackEntryAsState().value?.destination?.route == "list", |
||||||
|
onClick = { navController.navigate(DemoRoutes.List.route) } |
||||||
|
) |
||||||
|
NavigationBarItem( |
||||||
|
icon = { Icon(Icons.Default.Add, contentDescription = "Add") }, |
||||||
|
label = { Text("Add") }, |
||||||
|
selected = navController.currentBackStackEntryAsState().value?.destination?.route == "add", |
||||||
|
onClick = { navController.navigate(DemoRoutes.Add.route) } |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
) { innerPadding -> |
||||||
|
NavHost( |
||||||
|
navController = navController, |
||||||
|
startDestination = DemoRoutes.List.route, |
||||||
|
modifier = Modifier.padding(innerPadding) |
||||||
|
) { |
||||||
|
composable(DemoRoutes.List.route){ |
||||||
|
ListScreen( onEditClick = { |
||||||
|
navController.navigate(DemoRoutes.Edit.route.replace("{taskId}", "$it")) |
||||||
|
}){ |
||||||
|
navController.navigate(DemoRoutes.Detail.route.replace("{taskId}", "$it")) |
||||||
|
} |
||||||
|
} |
||||||
|
composable(DemoRoutes.Add.route) { AddScreen() } |
||||||
|
composable( |
||||||
|
route = DemoRoutes.Detail.route, |
||||||
|
arguments = listOf(navArgument("taskId") { |
||||||
|
type = NavType.IntType |
||||||
|
}) |
||||||
|
) { |
||||||
|
TaskDetailsScreen() |
||||||
|
} |
||||||
|
composable( |
||||||
|
route = DemoRoutes.Edit.route, |
||||||
|
arguments = listOf(navArgument("contactId") { |
||||||
|
type = NavType.IntType |
||||||
|
}) |
||||||
|
) { |
||||||
|
TaskEditScreen() { |
||||||
|
navController.navigateUp() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun ListScreen( |
||||||
|
modifier: Modifier = Modifier, |
||||||
|
demoViewModel: DemoViewModel = viewModel(factory = AppViewModelProvider.Factory), |
||||||
|
onEditClick: (Int) -> Unit, |
||||||
|
onCardClick: (Int) -> Unit |
||||||
|
) { |
||||||
|
Box(Modifier.fillMaxSize()) { |
||||||
|
val state by demoViewModel.taskUiState.collectAsStateWithLifecycle(); |
||||||
|
|
||||||
|
LazyColumn { |
||||||
|
itemsIndexed(state.tasks) { index, task -> |
||||||
|
TaskListItem(task, onCardClick = { |
||||||
|
onCardClick(task.id) |
||||||
|
}, onEditClick = { |
||||||
|
onEditClick(task.id) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun TaskDetailsScreen(modifier: Modifier = Modifier, demoDetailsViewModel: DemoDetailsViewModel = viewModel(factory = AppViewModelProvider.Factory)) { |
||||||
|
val detailUiState by demoDetailsViewModel.detailUiState.collectAsStateWithLifecycle() |
||||||
|
|
||||||
|
TaskDetails(detailUiState.task, modifier) |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun TaskDetails(task: Task, modifier: Modifier = Modifier) { |
||||||
|
OutlinedCard( |
||||||
|
modifier |
||||||
|
.fillMaxWidth() |
||||||
|
.padding(8.dp) |
||||||
|
) { |
||||||
|
Column(Modifier.padding(16.dp)) { |
||||||
|
Text(task.name, style = Typography.headlineMedium) |
||||||
|
Row { |
||||||
|
Text("Details: ${task.details}", style = Typography.headlineMedium) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun AddScreen() { |
||||||
|
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { |
||||||
|
Text("Add Screen") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun TaskListItem(task: Task, onCardClick: () -> Unit, onEditClick: ()->Unit, modifier: Modifier = Modifier) { |
||||||
|
OutlinedCard( |
||||||
|
onClick = { onCardClick() }, modifier = modifier |
||||||
|
.fillMaxWidth() |
||||||
|
.padding(8.dp) |
||||||
|
) { |
||||||
|
Row(Modifier.padding(16.dp), verticalAlignment = Alignment.CenterVertically) { |
||||||
|
Text(task.name, style = Typography.headlineMedium) |
||||||
|
IconButton(onEditClick) { |
||||||
|
Icon(Icons.Outlined.Edit, "Edit contact") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Preview |
||||||
|
@Composable |
||||||
|
fun PreviewTaskListItem(){ |
||||||
|
TaskListItem(Task(0, "Buy Milk", "buy milk"), {}, {}) |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
package at.xaxa.demonstrator2.ui |
||||||
|
|
||||||
|
import at.xaxa.demonstrator2.data.Task |
||||||
|
|
||||||
|
data class DemoUiState( |
||||||
|
val tasks : List<Task> |
||||||
|
) |
@ -0,0 +1,33 @@ |
|||||||
|
package at.xaxa.demonstrator2.ui |
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel |
||||||
|
import androidx.lifecycle.viewModelScope |
||||||
|
import at.xaxa.demonstrator2.data.TaskRepository |
||||||
|
import kotlinx.coroutines.flow.SharingStarted |
||||||
|
import kotlinx.coroutines.flow.map |
||||||
|
import kotlinx.coroutines.flow.stateIn |
||||||
|
import kotlinx.coroutines.launch |
||||||
|
|
||||||
|
class DemoViewModel(val repository: TaskRepository) : ViewModel() { |
||||||
|
|
||||||
|
init { |
||||||
|
viewModelScope.launch { |
||||||
|
repository.getAllTasks() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
val taskUiState = repository.getAllTasks() |
||||||
|
.map { DemoUiState(it) } |
||||||
|
.stateIn( |
||||||
|
scope = viewModelScope, |
||||||
|
started = SharingStarted.WhileSubscribed(5000), |
||||||
|
initialValue = DemoUiState(emptyList()) |
||||||
|
) |
||||||
|
|
||||||
|
fun onAddButtonClicked() { |
||||||
|
viewModelScope.launch { |
||||||
|
repository.addRandomTask() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,78 @@ |
|||||||
|
package at.xaxa.demonstrator2.ui.edit |
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column |
||||||
|
import androidx.compose.foundation.layout.Row |
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth |
||||||
|
import androidx.compose.foundation.layout.padding |
||||||
|
import androidx.compose.material3.Button |
||||||
|
import androidx.compose.material3.OutlinedCard |
||||||
|
import androidx.compose.material3.OutlinedTextField |
||||||
|
import androidx.compose.material3.Text |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.ui.Alignment |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import androidx.compose.ui.tooling.preview.Preview |
||||||
|
import androidx.compose.ui.unit.dp |
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel |
||||||
|
import at.xaxa.demonstrator2.data.Task |
||||||
|
import at.xaxa.demonstrator2.ui.AppViewModelProvider |
||||||
|
|
||||||
|
|
||||||
|
@Composable |
||||||
|
fun TaskEditScreen( |
||||||
|
modifier: Modifier = Modifier, |
||||||
|
viewModel: TaskEditViewModel = viewModel(factory = AppViewModelProvider.Factory), |
||||||
|
onSave: () -> Unit |
||||||
|
) { |
||||||
|
val task = viewModel.editUiState.task |
||||||
|
|
||||||
|
|
||||||
|
TaskEditForm(task, modifier, onValueChange = { taskChanged -> |
||||||
|
viewModel.updateTask(taskChanged) |
||||||
|
}) { |
||||||
|
viewModel.saveTask() |
||||||
|
onSave() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Composable |
||||||
|
fun TaskEditForm( |
||||||
|
task: Task, |
||||||
|
modifier: Modifier = Modifier, |
||||||
|
onValueChange: (Task) -> Unit = {}, |
||||||
|
onSaveButtonClicked: () -> Unit = {} |
||||||
|
) { |
||||||
|
OutlinedCard( |
||||||
|
modifier = modifier |
||||||
|
.fillMaxWidth() |
||||||
|
) |
||||||
|
{ |
||||||
|
Column(Modifier.padding(16.dp).fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { |
||||||
|
Row { |
||||||
|
OutlinedTextField( |
||||||
|
value = task.name, |
||||||
|
label = { Text("Name") }, |
||||||
|
onValueChange = { newText -> |
||||||
|
onValueChange(task.copy(name = newText)) |
||||||
|
}) |
||||||
|
} |
||||||
|
Row { |
||||||
|
OutlinedTextField( |
||||||
|
value = task.details.toString(), |
||||||
|
label = { Text("Details") }, |
||||||
|
onValueChange = { newText -> |
||||||
|
onValueChange(task.copy(details = newText)) |
||||||
|
}) |
||||||
|
} |
||||||
|
Button(onClick = { onSaveButtonClicked() }) { |
||||||
|
Text("Save changes") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Preview |
||||||
|
@Composable |
||||||
|
private fun TaskEditPreview() { |
||||||
|
TaskEditForm(Task(234, "Buy milk", "buy milk")) { } |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package at.xaxa.demonstrator2.ui.edit |
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.runtime.mutableStateOf |
||||||
|
import androidx.compose.runtime.setValue |
||||||
|
import androidx.lifecycle.SavedStateHandle |
||||||
|
import androidx.lifecycle.ViewModel |
||||||
|
import androidx.lifecycle.viewModelScope |
||||||
|
import at.xaxa.demonstrator2.data.Task |
||||||
|
import at.xaxa.demonstrator2.data.TaskRepository |
||||||
|
import kotlinx.coroutines.Dispatchers |
||||||
|
import kotlinx.coroutines.launch |
||||||
|
import kotlinx.coroutines.withContext |
||||||
|
|
||||||
|
|
||||||
|
data class TaskEditUi( |
||||||
|
val task: Task = Task(0, "", "") |
||||||
|
) |
||||||
|
|
||||||
|
class TaskEditViewModel(private val savedStateHandle: SavedStateHandle, |
||||||
|
private val taskRepository: TaskRepository) : ViewModel() { |
||||||
|
|
||||||
|
private val taskId: Int = checkNotNull(savedStateHandle["taskId"]) |
||||||
|
|
||||||
|
var editUiState by mutableStateOf(TaskEditUi()) |
||||||
|
private set |
||||||
|
|
||||||
|
init { |
||||||
|
viewModelScope.launch { |
||||||
|
val task = withContext(Dispatchers.IO) { |
||||||
|
taskRepository.getTaskById(taskId) |
||||||
|
} |
||||||
|
editUiState = TaskEditUi(task) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fun updateTask(task: Task) { |
||||||
|
editUiState = editUiState.copy(task=task) |
||||||
|
} |
||||||
|
|
||||||
|
fun saveTask() { |
||||||
|
viewModelScope.launch { |
||||||
|
taskRepository.updateTask(editUiState.task) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue