Add a basic room database system for further features

This commit is contained in:
Nishant Mishra
2025-07-03 20:21:24 +05:30
parent 9e3978f261
commit 32e3a05df8
12 changed files with 171 additions and 18 deletions

View File

@@ -0,0 +1,13 @@
package org.nsh07.pomodoro
import android.app.Application
import org.nsh07.pomodoro.data.AppContainer
import org.nsh07.pomodoro.data.DefaultAppContainer
class TomatoApplication : Application() {
lateinit var container: AppContainer
override fun onCreate() {
super.onCreate()
container = DefaultAppContainer(this)
}
}

View File

@@ -0,0 +1,17 @@
package org.nsh07.pomodoro.data
import android.content.Context
interface AppContainer {
val appPreferencesRepository: AppPreferenceRepository
}
class DefaultAppContainer(context: Context) : AppContainer {
override val appPreferencesRepository: AppPreferenceRepository by lazy {
AppPreferenceRepository(
AppDatabase.getDatabase(context).preferenceDao()
)
}
}

View File

@@ -0,0 +1,29 @@
package org.nsh07.pomodoro.data
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(
entities = [IntPreference::class],
version = 1
)
abstract class AppDatabase : RoomDatabase() {
abstract fun preferenceDao(): PreferenceDao
companion object {
@Volatile
private var Instance: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return Instance ?: synchronized(this) {
Room.databaseBuilder(context, AppDatabase::class.java, "app_database")
.build()
.also { Instance = it }
}
}
}
}

View File

@@ -0,0 +1,11 @@
package org.nsh07.pomodoro.data
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "int_preference")
data class IntPreference(
@PrimaryKey
val key: String,
val value: Int
)

View File

@@ -0,0 +1,19 @@
package org.nsh07.pomodoro.data
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kotlinx.coroutines.flow.Flow
@Dao
interface PreferenceDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertIntPreference(preference: IntPreference)
@Query("DELETE FROM int_preference")
suspend fun resetIntPreferences()
@Query("SELECT value FROM int_preference WHERE `key` = :key")
fun getIntPreference(key: String): Flow<Int?>
}

View File

@@ -0,0 +1,31 @@
package org.nsh07.pomodoro.data
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
interface PreferencesRepository {
suspend fun saveIntPreference(key: String, value: Int)
fun getIntPreference(key: String): Flow<Int?>
suspend fun resetSettings()
}
class AppPreferenceRepository(
private val preferenceDao: PreferenceDao,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
): PreferencesRepository {
override suspend fun saveIntPreference(key: String, value: Int) =
withContext(ioDispatcher) {
preferenceDao.insertIntPreference(IntPreference(key, value))
}
override fun getIntPreference(key: String): Flow<Int?> =
preferenceDao.getIntPreference(key)
override suspend fun resetSettings() = withContext(ioDispatcher) {
preferenceDao.resetIntPreferences()
}
}

View File

@@ -40,7 +40,7 @@ import org.nsh07.pomodoro.ui.viewModel.UiViewModel
@Composable
fun AppScreen(
modifier: Modifier = Modifier,
viewModel: UiViewModel = viewModel()
viewModel: UiViewModel = viewModel(factory = UiViewModel.Factory)
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val remainingTime by viewModel.time.collectAsStateWithLifecycle()

View File

@@ -2,7 +2,11 @@ package org.nsh07.pomodoro.ui.viewModel
import android.os.SystemClock
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
@@ -10,10 +14,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.nsh07.pomodoro.TomatoApplication
import org.nsh07.pomodoro.data.AppPreferenceRepository
import java.util.Locale
import kotlin.math.ceil
class UiViewModel : ViewModel() {
class UiViewModel(
private val preferenceRepository: AppPreferenceRepository
) : ViewModel() {
val focusTime = 25 * 60 * 1000
val shortBreakTime = 5 * 60 * 1000
val longBreakTime = 15 * 60 * 1000
@@ -153,6 +161,8 @@ class UiViewModel : ViewModel() {
)
}
}
toggleTimer()
} else {
_uiState.update { currentState ->
currentState.copy(
@@ -172,4 +182,14 @@ class UiViewModel : ViewModel() {
val sec = (ceil(t / 1000.0).toInt() % 60)
return String.format(locale = Locale.getDefault(), "%02d:%02d", min, sec)
}
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
initializer {
val application = (this[APPLICATION_KEY] as TomatoApplication)
val appPreferenceRepository = application.container.appPreferencesRepository
UiViewModel(preferenceRepository = appPreferenceRepository)
}
}
}
}