feat: add tasks and notes management for lessons
- Introduced a new feature for managing tasks and notes associated with lessons. - Added a `NotesStore` class to handle local storage of notes in JSON format. - Implemented UI components for displaying, adding, editing, and deleting notes. - Enhanced the `HomeScreen`, `ScheduleScreen`, and `SubjectsScreen` to integrate notes functionality. - Updated the API to handle versioning and added error handling for outdated endpoints. - Improved the overall user experience with visual indicators for tasks and notes in the schedule.
This commit is contained in:
59
android/app/src/main/kotlin/ritm/schedule/data/Notes.kt
Normal file
59
android/app/src/main/kotlin/ritm/schedule/data/Notes.kt
Normal file
@@ -0,0 +1,59 @@
|
||||
package ritm.schedule.data
|
||||
|
||||
import android.content.Context
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* A homework task or a plain note the student pinned to one lesson: the subject,
|
||||
* the lesson's date and start time. Tasks can be ticked off; notes just remind.
|
||||
*/
|
||||
@Serializable
|
||||
data class Note(
|
||||
val id: String = UUID.randomUUID().toString(),
|
||||
/** "docId|group": notes of one group never show up in another. */
|
||||
val group: String,
|
||||
val subject: String,
|
||||
val date: String,
|
||||
val start: String,
|
||||
val text: String,
|
||||
val task: Boolean = true,
|
||||
val done: Boolean = false,
|
||||
val created: Long = System.currentTimeMillis(),
|
||||
)
|
||||
|
||||
fun groupKey(g: SavedGroup) = "${g.docId}|${g.group}"
|
||||
|
||||
/** Notes live only on the device, in one small JSON file. */
|
||||
class NotesStore(context: Context) {
|
||||
private val file = File(context.filesDir, "notes.json")
|
||||
private val lock = Mutex()
|
||||
private val _notes = MutableStateFlow(read())
|
||||
val notes: StateFlow<List<Note>> = _notes
|
||||
|
||||
private fun read(): List<Note> =
|
||||
runCatching { json.decodeFromString<List<Note>>(file.readText()) }.getOrDefault(emptyList())
|
||||
|
||||
private suspend fun change(block: (List<Note>) -> List<Note>) = withContext(Dispatchers.IO) {
|
||||
lock.withLock {
|
||||
val next = block(_notes.value)
|
||||
file.writeText(json.encodeToString(next))
|
||||
_notes.value = next
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun save(note: Note) = change { list ->
|
||||
if (list.any { it.id == note.id }) list.map { if (it.id == note.id) note else it } else list + note
|
||||
}
|
||||
|
||||
suspend fun delete(id: String) = change { list -> list.filterNot { it.id == id } }
|
||||
|
||||
suspend fun toggle(id: String) = change { list -> list.map { if (it.id == id) it.copy(done = !it.done) else it } }
|
||||
}
|
||||
Reference in New Issue
Block a user