bug in instance clearance for todo, when reminder time changes.
src:
consistency maintenance for todo to save just like notes
This commit is contained in:
chindaronit
2026-07-18 13:32:20 +05:30
parent e64f85e002
commit 4c0aef85cb
4 changed files with 53 additions and 38 deletions
+4 -6
View File
@@ -81,7 +81,7 @@ English, Hindi, French, Portugal (Brazil), Russian, German, Spanish, Dutch, Chin
## 🛠️ Architecture
- **MVI**: Model View ViewModel
-
## 📦 Installation
To build and run this application, you need to install the latest version of Android Studio. Then,
@@ -98,12 +98,10 @@ In Android Studio, select `Run > Run 'app'` to start the application.
Any form of contribution is welcome! If you find a bug or have a new feature request, please create
an issue. If you want to contribute code directly to this project, you can create a pull request.
## Credits
<div align="center">
## Credits.
[![Stargazers over time](https://starchart.cc/chindaronit/Flux.svg?variant=adaptive)](https://starchart.cc/chindaronit/Flux)
<a href="https://github.com/chindaronit/Flux/graphs/contributors">
<img src="https://contrib.rocks/image?repo=chindaronit/Flux" width="200"/>
</a>
@@ -2,9 +2,8 @@ package com.flux.data.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Upsert
import com.flux.data.model.TodoModel
import kotlinx.coroutines.flow.Flow
@@ -13,7 +12,7 @@ interface TodoDao {
@Query("SELECT EXISTS(SELECT 1 FROM TodoModel WHERE id = :id)")
suspend fun exists(id: String): Boolean
@Insert(onConflict = OnConflictStrategy.REPLACE)
@Upsert
suspend fun upsertList(list: TodoModel)
@Delete
@@ -1,9 +1,8 @@
package com.flux.data.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Upsert
import com.flux.data.model.TodoInstance
import kotlinx.coroutines.flow.Flow
@@ -24,7 +23,7 @@ interface TodoInstanceDao {
@Query("SELECT * FROM TodoInstance WHERE instanceDate = :date and todoId = :todoId")
fun observeInstanceForDate(todoId: String, date: Long): Flow<List<TodoInstance>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
@Upsert
suspend fun upsertTodoInstance(instance: TodoInstance)
@Query("DELETE FROM TodoInstance WHERE todoId = :listId")
@@ -1,5 +1,7 @@
package com.flux.ui.screens.todo
import android.widget.Toast
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
@@ -15,7 +17,6 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Alarm
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.filled.LockOpen
import androidx.compose.material.icons.filled.Menu
@@ -28,6 +29,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
@@ -81,7 +83,6 @@ fun NewTodoList(
val deleteQueue = remember {
Channel<Pair<Int, TodoItem>>(Channel.UNLIMITED)
}
// True = normal editing mode (locked ordering)
// False = reorder mode (unlocked ordering, drag handles visible)
var isReordering by remember { mutableStateOf(false) }
@@ -113,7 +114,8 @@ fun NewTodoList(
val result = snackbarHostState.showSnackbar(
message = itemRemovedLabel,
actionLabel = undoLabel
actionLabel = undoLabel,
duration = SnackbarDuration.Short
)
if (result == SnackbarResult.ActionPerformed) {
@@ -123,6 +125,40 @@ fun NewTodoList(
}
}
fun saveTodoIfPossible(): Boolean {
val hasContent = title.isNotBlank() || itemList.isNotEmpty()
if (!hasContent) { return true }
if (title.isBlank()) {
Toast.makeText(context, "Title is Required", Toast.LENGTH_SHORT).show()
return false
}
onTodoEvents(
TodoEvents.UpsertList(
context,
list.recurrence is RecurrenceRule.Weekly && recurrence is RecurrenceRule.NONE,
list.copy(
title = title,
items = itemList.toList(),
workspaceId = workspaceId,
recurrence = recurrence,
startDateTime = reminderTime
)
)
)
return true
}
BackHandler {
if (saveTodoIfPossible()) {
isReordering = false
navController.popBackStack()
}
}
Scaffold(
modifier = Modifier.imePadding(),
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
@@ -154,7 +190,12 @@ fun NewTodoList(
)
},
navigationIcon = {
IconButton({ navController.popBackStack() }) {
IconButton({
if (saveTodoIfPossible()) {
isReordering = false
navController.popBackStack()
}
}) {
Icon(Icons.AutoMirrored.Default.ArrowBack, null)
}
},
@@ -168,28 +209,6 @@ fun NewTodoList(
IconButton(onClick = { isReordering = !isReordering }) {
Icon(if(!isReordering) Icons.Default.Lock else Icons.Default.LockOpen, null)
}
// ✓ in edit mode: persist everything to ViewModel
IconButton(
enabled = title.isNotBlank(),
onClick = {
onTodoEvents(
TodoEvents.UpsertList(
context,
list.recurrence is RecurrenceRule.Weekly && recurrence is RecurrenceRule.NONE,
list.copy(
title = title,
items = itemList.toList(),
workspaceId = workspaceId,
recurrence = recurrence,
startDateTime = reminderTime
)
)
)
isReordering = false
navController.popBackStack()
}
) { Icon(Icons.Default.Check, null) }
}
)
}