Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Android
*.iml
.gradle/
build/
local.properties
.idea/
.DS_Store
captures/
.externalNativeBuild
.cxx

# Kotlin
*.class
*.kotlin_module

# Dependency directories
/node_modules
/app/build

# Logging
*.log

# Testing
/app/reports
/app/test-results

# Sensitive information
*.env
*.keystore

# System files
.DS_Store
Thumbs.db
31 changes: 31 additions & 0 deletions app/src/main/java/com/todoapp/data/dao/TodoDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.todoapp.data.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.todoapp.data.entity.TodoItem
import kotlinx.coroutines.flow.Flow

/**
* Data Access Object for Todo items.
* Defines database operations for TodoItem.
*/
@Dao
interface TodoDao {
/**
* Retrieve all todo items.
*
* @return Flow of list of TodoItems
*/
@Query("SELECT * FROM todo_items")
fun getAllTodoItems(): Flow<List<TodoItem>>

/**
* Insert a new todo item.
*
* @param todoItem TodoItem to be inserted
* @return Long ID of the inserted item
*/
@Insert
suspend fun insertTodoItem(todoItem: TodoItem): Long
}
56 changes: 56 additions & 0 deletions app/src/main/java/com/todoapp/data/database/TodoDatabase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.todoapp.data.database

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.todoapp.data.dao.TodoDao
import com.todoapp.data.entity.TodoItem

/**
* Room Database for storing Todo items.
* This is a singleton database instance to ensure only one connection is maintained.
*/
@Database(entities = [TodoItem::class], version = 1, exportSchema = false)
abstract class TodoDatabase : RoomDatabase() {
// Abstract method to get the TodoDao
abstract fun todoDao(): TodoDao

companion object {
// Volatile ensures the instance is always up-to-date across threads
@Volatile
private var INSTANCE: TodoDatabase? = null

/**
* Get or create the database instance.
* Uses synchronized block to ensure thread safety during instance creation.
*
* @param context Application context
* @return TodoDatabase instance
*/
fun getDatabase(context: Context): TodoDatabase {
// If instance already exists, return it
return INSTANCE ?: synchronized(this) {
// Double-checked locking pattern
INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
}
}

/**
* Create the Room database instance.
*
* @param context Application context
* @return Created TodoDatabase
*/
private fun buildDatabase(context: Context): TodoDatabase {
return Room.databaseBuilder(
context.applicationContext,
TodoDatabase::class.java,
"todo_database"
)
// Optional: Add migration strategy if needed in future
.fallbackToDestructiveMigration() // Simplified for this example
.build()
}
}
}
23 changes: 23 additions & 0 deletions app/src/main/java/com/todoapp/data/entity/TodoItem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.todoapp.data.entity

import androidx.room.Entity
import androidx.room.PrimaryKey

/**
* Represents a Todo item in the database.
*
* @property id Unique identifier for the todo item
* @property title Title of the todo item
* @property description Optional description of the todo item
* @property isCompleted Flag indicating whether the todo item is completed
* @property createdAt Timestamp of item creation
*/
@Entity(tableName = "todo_items")
data class TodoItem(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val title: String,
val description: String? = null,
val isCompleted: Boolean = false,
val createdAt: Long = System.currentTimeMillis()
)
55 changes: 55 additions & 0 deletions app/src/test/java/com/todoapp/data/TodoDatabaseTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.todoapp.data

import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import com.todoapp.data.database.TodoDatabase
import com.todoapp.data.entity.TodoItem
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import java.io.IOException

class TodoDatabaseTest {
private lateinit var database: TodoDatabase

@Before
fun createDatabase() {
val context = ApplicationProvider.getApplicationContext<Context>()
database = Room.inMemoryDatabaseBuilder(
context, TodoDatabase::class.java
).build()
}

@After
@Throws(IOException::class)
fun closeDatabase() {
database.close()
}

@Test
@Throws(Exception::class)
fun insertAndRetrieveTodoItem() = runBlocking {
val todoItem = TodoItem(
title = "Test Todo",
description = "Test Description",
isCompleted = false
)

// Insert todo item
val insertedId = database.todoDao().insertTodoItem(todoItem)
assertTrue(insertedId > 0)

// Retrieve todo items
val todoItems = database.todoDao().getAllTodoItems().first()

// Verify
assertEquals(1, todoItems.size)
assertEquals("Test Todo", todoItems[0].title)
assertEquals("Test Description", todoItems[0].description)
assertFalse(todoItems[0].isCompleted)
}
}