feat: Implement core data architecture (Room, Repository, ViewModels) and UI integration
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
alias(libs.plugins.google.devtools.ksp)
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -37,18 +37,28 @@ android {
|
||||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.compose.ui)
|
||||
implementation(libs.androidx.compose.ui.graphics)
|
||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||
implementation(libs.androidx.compose.material3)
|
||||
|
||||
// Room Database
|
||||
implementation(libs.androidx.room.runtime)
|
||||
implementation(libs.androidx.room.ktx)
|
||||
ksp(libs.androidx.room.compiler)
|
||||
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:name=".NoteshopApplication"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.lxtools.noteshop
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import de.lxtools.noteshop.ui.notes.NotesViewModel
|
||||
import de.lxtools.noteshop.ui.shopping.ShoppingListsViewModel
|
||||
|
||||
/**
|
||||
* Provides Factory to create ViewModels for the entire app
|
||||
*/
|
||||
object AppViewModelProvider {
|
||||
val Factory = viewModelFactory {
|
||||
// Initializer for NotesViewModel
|
||||
initializer {
|
||||
val application = (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as NoteshopApplication)
|
||||
NotesViewModel(
|
||||
application.container.noteshopRepository
|
||||
)
|
||||
}
|
||||
// Initializer for ShoppingListsViewModel
|
||||
initializer {
|
||||
val application = (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as NoteshopApplication)
|
||||
ShoppingListsViewModel(
|
||||
application.container.noteshopRepository
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -12,9 +13,8 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
@@ -41,11 +41,15 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.lxtools.noteshop.ui.notes.NotesScreen
|
||||
import de.lxtools.noteshop.ui.notes.NotesViewModel
|
||||
import de.lxtools.noteshop.ui.shopping.ShoppingListsScreen
|
||||
import de.lxtools.noteshop.ui.shopping.ShoppingListsViewModel
|
||||
import de.lxtools.noteshop.ui.theme.NoteshopTheme
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -69,7 +73,10 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AppShell() {
|
||||
fun AppShell(
|
||||
notesViewModel: NotesViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
shoppingListsViewModel: ShoppingListsViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
||||
val scope = rememberCoroutineScope()
|
||||
var currentScreen: Screen by remember { mutableStateOf(Screen.ShoppingLists) }
|
||||
@@ -144,10 +151,10 @@ fun AppShell() {
|
||||
) {
|
||||
when (currentScreen) {
|
||||
is Screen.ShoppingLists -> {
|
||||
Text(text = "Hier kommen die Einkaufslisten hin.")
|
||||
ShoppingListsScreen(viewModel = shoppingListsViewModel)
|
||||
}
|
||||
is Screen.Notes -> {
|
||||
Text(text = "Hier kommen die Notizen hin.")
|
||||
NotesScreen(viewModel = notesViewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
app/src/main/java/de/lxtools/noteshop/NoteshopApplication.kt
Normal file
40
app/src/main/java/de/lxtools/noteshop/NoteshopApplication.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package de.lxtools.noteshop
|
||||
|
||||
import android.app.Application
|
||||
import de.lxtools.noteshop.data.AppDatabase
|
||||
import de.lxtools.noteshop.data.NoteshopRepository
|
||||
import de.lxtools.noteshop.data.OfflineNoteshopRepository
|
||||
|
||||
/**
|
||||
* The application class, which creates and holds the dependency container.
|
||||
*/
|
||||
class NoteshopApplication : Application() {
|
||||
/**
|
||||
* AppContainer instance used by the rest of classes to obtain dependencies
|
||||
*/
|
||||
lateinit var container: AppContainer
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
container = AppDataContainer(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for the dependency container.
|
||||
*/
|
||||
interface AppContainer {
|
||||
val noteshopRepository: NoteshopRepository
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for the dependency container.
|
||||
*/
|
||||
class AppDataContainer(private val context: Application) : AppContainer {
|
||||
override val noteshopRepository: NoteshopRepository by lazy {
|
||||
OfflineNoteshopRepository(
|
||||
noteDao = AppDatabase.getDatabase(context).noteDao(),
|
||||
shoppingListDao = AppDatabase.getDatabase(context).shoppingListDao()
|
||||
)
|
||||
}
|
||||
}
|
||||
37
app/src/main/java/de/lxtools/noteshop/data/AppDatabase.kt
Normal file
37
app/src/main/java/de/lxtools/noteshop/data/AppDatabase.kt
Normal file
@@ -0,0 +1,37 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
|
||||
@Database(
|
||||
entities = [Note::class, ShoppingList::class, ShoppingListItem::class],
|
||||
version = 1,
|
||||
exportSchema = false // For simplicity, we disable schema exporting for now
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun noteDao(): NoteDao
|
||||
abstract fun shoppingListDao(): ShoppingListDao
|
||||
|
||||
companion object {
|
||||
// Volatile ensures that the instance is always up-to-date and the same for all execution threads.
|
||||
@Volatile
|
||||
private var INSTANCE: AppDatabase? = null
|
||||
|
||||
fun getDatabase(context: Context): AppDatabase {
|
||||
// If the INSTANCE is not null, then return it, otherwise create the database
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val instance = Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
AppDatabase::class.java,
|
||||
"noteshop_database"
|
||||
).build()
|
||||
INSTANCE = instance
|
||||
// return instance
|
||||
instance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
app/src/main/java/de/lxtools/noteshop/data/Note.kt
Normal file
12
app/src/main/java/de/lxtools/noteshop/data/Note.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "notes")
|
||||
data class Note(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int = 0,
|
||||
val title: String,
|
||||
val content: String
|
||||
)
|
||||
28
app/src/main/java/de/lxtools/noteshop/data/NoteDao.kt
Normal file
28
app/src/main/java/de/lxtools/noteshop/data/NoteDao.kt
Normal file
@@ -0,0 +1,28 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface NoteDao {
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(note: Note)
|
||||
|
||||
@Update
|
||||
suspend fun update(note: Note)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(note: Note)
|
||||
|
||||
@Query("SELECT * FROM notes WHERE id = :id")
|
||||
fun getNote(id: Int): Flow<Note?>
|
||||
|
||||
@Query("SELECT * FROM notes ORDER BY id DESC")
|
||||
fun getAllNotes(): Flow<List<Note>>
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Repository that provides insert, update, delete, and retrieve of data from a given data source.
|
||||
*/
|
||||
interface NoteshopRepository {
|
||||
/**
|
||||
* Retrieve all the notes from the the data source.
|
||||
*/
|
||||
fun getAllNotesStream(): Flow<List<Note>>
|
||||
|
||||
/**
|
||||
* Retrieve all the shopping lists with their items from the data source.
|
||||
*/
|
||||
fun getAllShoppingListsWithItemsStream(): Flow<List<ShoppingListWithItems>>
|
||||
|
||||
// Add other necessary methods for inserting, updating, deleting data
|
||||
}
|
||||
|
||||
class OfflineNoteshopRepository(private val noteDao: NoteDao, private val shoppingListDao: ShoppingListDao) : NoteshopRepository {
|
||||
override fun getAllNotesStream(): Flow<List<Note>> = noteDao.getAllNotes()
|
||||
|
||||
override fun getAllShoppingListsWithItemsStream(): Flow<List<ShoppingListWithItems>> = shoppingListDao.getListsWithItems()
|
||||
|
||||
}
|
||||
11
app/src/main/java/de/lxtools/noteshop/data/ShoppingList.kt
Normal file
11
app/src/main/java/de/lxtools/noteshop/data/ShoppingList.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "shopping_lists")
|
||||
data class ShoppingList(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int = 0,
|
||||
val name: String
|
||||
)
|
||||
@@ -0,0 +1,43 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.Update
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface ShoppingListDao {
|
||||
|
||||
// --- ShoppingList specific methods ---
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertList(list: ShoppingList)
|
||||
|
||||
@Update
|
||||
suspend fun updateList(list: ShoppingList)
|
||||
|
||||
@Delete
|
||||
suspend fun deleteList(list: ShoppingList)
|
||||
|
||||
// --- ShoppingListItem specific methods ---
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertItem(item: ShoppingListItem)
|
||||
|
||||
@Update
|
||||
suspend fun updateItem(item: ShoppingListItem)
|
||||
|
||||
@Delete
|
||||
suspend fun deleteItem(item: ShoppingListItem)
|
||||
|
||||
// --- Methods for combined data ---
|
||||
@Transaction
|
||||
@Query("SELECT * FROM shopping_lists")
|
||||
fun getListsWithItems(): Flow<List<ShoppingListWithItems>>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM shopping_lists WHERE id = :listId")
|
||||
fun getListWithItems(listId: Int): Flow<ShoppingListWithItems?>
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(
|
||||
tableName = "shopping_list_items",
|
||||
foreignKeys = [
|
||||
ForeignKey(
|
||||
entity = ShoppingList::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["list_id"],
|
||||
onDelete = ForeignKey.CASCADE // If a list is deleted, its items are also deleted
|
||||
)
|
||||
]
|
||||
)
|
||||
data class ShoppingListItem(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int = 0,
|
||||
val name: String,
|
||||
@ColumnInfo(name = "is_checked")
|
||||
val isChecked: Boolean = false,
|
||||
@ColumnInfo(name = "list_id", index = true)
|
||||
val listId: Int
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package de.lxtools.noteshop.data
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Relation
|
||||
|
||||
data class ShoppingListWithItems(
|
||||
@Embedded val shoppingList: ShoppingList,
|
||||
@Relation(
|
||||
parentColumn = "id",
|
||||
entityColumn = "list_id"
|
||||
)
|
||||
val items: List<ShoppingListItem>
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.lxtools.noteshop.ui.notes
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun NotesScreen(viewModel: NotesViewModel, modifier: Modifier = Modifier) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text(text = "Anzahl der Notizen: ${uiState.noteList.size}")
|
||||
// TODO: Implement LazyColumn to display actual notes
|
||||
uiState.noteList.forEach { note ->
|
||||
Text(text = "- ${note.title}: ${note.content}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.lxtools.noteshop.ui.notes
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.lxtools.noteshop.data.Note
|
||||
import de.lxtools.noteshop.data.NoteshopRepository
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class NotesViewModel(noteshopRepository: NoteshopRepository) : ViewModel() {
|
||||
|
||||
val uiState: StateFlow<NotesUiState> = noteshopRepository.getAllNotesStream().map { NotesUiState(it) }
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS),
|
||||
initialValue = NotesUiState()
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val TIMEOUT_MILLIS = 5_000L
|
||||
}
|
||||
}
|
||||
|
||||
data class NotesUiState(
|
||||
val noteList: List<Note> = listOf()
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.lxtools.noteshop.ui.shopping
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun ShoppingListsScreen(viewModel: ShoppingListsViewModel, modifier: Modifier = Modifier) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text(text = "Anzahl der Einkaufslisten: ${uiState.shoppingLists.size}")
|
||||
// TODO: Implement LazyColumn to display actual shopping lists
|
||||
uiState.shoppingLists.forEach { listWithItems ->
|
||||
Text(text = "- ${listWithItems.shoppingList.name} (${listWithItems.items.size} Artikel)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.lxtools.noteshop.ui.shopping
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.lxtools.noteshop.data.NoteshopRepository
|
||||
import de.lxtools.noteshop.data.ShoppingListWithItems
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class ShoppingListsViewModel(noteshopRepository: NoteshopRepository) : ViewModel() {
|
||||
|
||||
val uiState: StateFlow<ShoppingListsUiState> = noteshopRepository.getAllShoppingListsWithItemsStream().map { ShoppingListsUiState(it) }
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS),
|
||||
initialValue = ShoppingListsUiState()
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val TIMEOUT_MILLIS = 5_000L
|
||||
}
|
||||
}
|
||||
|
||||
data class ShoppingListsUiState(
|
||||
val shoppingLists: List<ShoppingListWithItems> = listOf()
|
||||
)
|
||||
@@ -2,5 +2,4 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
alias(libs.plugins.kotlin.compose) apply false
|
||||
}
|
||||
@@ -1,32 +1,44 @@
|
||||
[versions]
|
||||
agp = "8.13.0"
|
||||
kotlin = "2.0.21"
|
||||
coreKtx = "1.10.1"
|
||||
activity-compose = "1.9.0"
|
||||
compose-bom = "2024.06.00"
|
||||
espresso-core = "3.6.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.1.5"
|
||||
espressoCore = "3.5.1"
|
||||
lifecycleRuntimeKtx = "2.6.1"
|
||||
activityCompose = "1.8.0"
|
||||
composeBom = "2024.09.00"
|
||||
junit-version = "1.2.1"
|
||||
lifecycle-runtime-ktx = "2.8.3"
|
||||
lifecycle-viewmodel-compose = "2.8.3"
|
||||
core-ktx = "1.13.1"
|
||||
room = "2.6.1"
|
||||
ksp = "1.9.22-1.0.17"
|
||||
agp = "8.4.1"
|
||||
kotlin = "1.9.22"
|
||||
compose-compiler = "1.5.8"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
|
||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
|
||||
androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "core-ktx" }
|
||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" }
|
||||
androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" }
|
||||
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso-core" }
|
||||
androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junit-version" }
|
||||
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" }
|
||||
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle-viewmodel-compose" }
|
||||
androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
|
||||
androidx-compose-ui = { module = "androidx.compose.ui:ui" }
|
||||
androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }
|
||||
androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
|
||||
androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
|
||||
androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
|
||||
androidx-compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" }
|
||||
junit = { module = "junit:junit", version.ref = "junit" }
|
||||
|
||||
# Room database libraries
|
||||
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
|
||||
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
|
||||
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
||||
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
google-devtools-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
|
||||
[bundles]
|
||||
|
||||
Reference in New Issue
Block a user