diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ac661b7..4076d86 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -53,6 +53,17 @@ dependencies { implementation(libs.androidx.compose.ui.graphics) implementation(libs.androidx.compose.ui.tooling.preview) implementation(libs.androidx.compose.material3) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.material3) + implementation("androidx.compose.material:material-icons-extended:1.4.3") + implementation(libs.androidx.compose.runtime) + + // CameraX + implementation("androidx.camera:camera-core:1.2.3") + implementation("androidx.camera:camera-camera2:1.2.3") // ⚠ Obligatoire + implementation(libs.androidx.camera.lifecycle) + implementation(libs.androidx.camera.view) + testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) @@ -61,13 +72,15 @@ dependencies { debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.test.manifest) - //implementation pour RETROFIT (API) + // Retrofit implementation("com.squareup.retrofit2:retrofit:3.0.0") implementation("com.squareup.retrofit2:converter-gson:3.0.0") - //pour Room + + // Room implementation("androidx.room:room-runtime:$roomVersion") implementation("androidx.room:room-ktx:$roomVersion") kapt("androidx.room:room-compiler:$roomVersion") - + // ML Kit + implementation("com.google.mlkit:barcode-scanning:17.2.0") } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 91fa271..9861072 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ - + - + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..5da8c70 Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/com/dev/collectiondvd/MainActivity.kt b/app/src/main/java/com/dev/collectiondvd/MainActivity.kt index 9d4796d..2c65a83 100644 --- a/app/src/main/java/com/dev/collectiondvd/MainActivity.kt +++ b/app/src/main/java/com/dev/collectiondvd/MainActivity.kt @@ -1,66 +1,392 @@ package com.dev.collectiondvd +import android.Manifest import android.content.Intent +import android.content.pm.PackageManager import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +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.platform.LocalContext -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.lifecycle.ViewModelProvider +import com.dev.collectiondvd.data.local.AppDatabase +import com.dev.collectiondvd.data.local.entities.Dvd +import com.dev.collectiondvd.data.repository.LocalDvdRepository import com.dev.collectiondvd.ui.screen.AjoutDvdActivity -import com.dev.collectiondvd.ui.screen.ListDvdActivity -import com.dev.collectiondvd.ui.screen.SupprDvdActivity import com.dev.collectiondvd.ui.theme.CollectionDvdTheme +import com.dev.collectiondvd.viewmodel.LocalDvdViewModel +import com.dev.collectiondvd.viewmodel.factory.LocalDvdViewModelFactory +import androidx.compose.material3.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import com.dev.collectiondvd.ui.screen.ScanCodeActivity +import com.dev.collectiondvd.ui.screen.StatDvdActivity import com.dev.collectiondvd.ui.theme.MyButton -import kotlin.system.exitProcess + class MainActivity : ComponentActivity() { + private lateinit var viewModel: LocalDvdViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContent { MenuScreen() } + val database = AppDatabase.getDatabase(applicationContext) + val dvdDao = database.dvdDao() + val repository = LocalDvdRepository(dvdDao) + val factory = LocalDvdViewModelFactory(repository) + viewModel = ViewModelProvider(this, factory).get(LocalDvdViewModel::class.java) + setContent { + CollectionDvdTheme(darkTheme = true) { + MenuScreen( + onQuit = { finish() }, + viewModel = viewModel + ) + } + } } } + + +enum class SortType( + val label: String +) { + TITLE_ASC("Titre (ascendant)"), + TITLE_DESC("Titre (descendant)"), + DIRECTOR_ASC("Réalisateur (ascendant)"), + DIRECTOR_DESC("Réalisateur (descendant)"), + YEAR_ASC("Année (ascendant)"), + YEAR_DESC("Année (descendant)") +} + + + @Composable -fun MenuScreen() { +fun MenuScreen( + viewModel: LocalDvdViewModel, + onQuit: () -> Unit +) { val context = LocalContext.current + val dvds by viewModel.dvds.collectAsState(initial = emptyList()) + var searchQuery by remember { mutableStateOf("") } + val filteredDvds = dvds.filter { dvd -> + val query = searchQuery.lowercase() + dvd.titre.orEmpty().lowercase().contains(query) || + dvd.realisateur.orEmpty().lowercase().contains(query) || + dvd.genre.orEmpty().lowercase().contains(query) || + dvd.annee.orEmpty().lowercase().contains(query) + } - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - horizontalAlignment = Alignment.CenterHorizontally, + var sortType by remember { mutableStateOf(SortType.TITLE_ASC) } + + val filteredAndSortedDvds = when (sortType) { + SortType.TITLE_ASC -> + filteredDvds.sortedBy { it.titre.orEmpty().lowercase() } + + SortType.TITLE_DESC -> + filteredDvds.sortedByDescending { it.titre.orEmpty() } + + SortType.DIRECTOR_ASC -> + filteredDvds.sortedBy { it.realisateur.orEmpty() } + + SortType.DIRECTOR_DESC -> + filteredDvds.sortedByDescending { it.realisateur.orEmpty() } + + SortType.YEAR_ASC -> + filteredDvds.sortedBy { it.annee.orEmpty() } + + SortType.YEAR_DESC -> + filteredDvds.sortedByDescending { it.annee.orEmpty() } + } + Scaffold( + floatingActionButtonPosition = FabPosition.Center, + floatingActionButton = { + ExtendedFloatingActionButton( + text = { Text("Ajouter") }, + icon = { Text("+") }, + onClick = { + context.startActivity( + Intent(context, AjoutDvdActivity::class.java) + ) + } + ) + } + + + + ) { padding -> + + Column( + modifier = Modifier + .fillMaxSize() + .padding(padding) + .padding(12.dp) ) { - Text("Gestion la collection de DVD", fontSize = 28.sp) - MyButton("Liste des DVDs") { context.startActivity(Intent(context, ListDvdActivity::class.java)) } - MyButton("Ajouter un DVD") { context.startActivity(Intent(context, AjoutDvdActivity::class.java)) } + TopBar() - MyButton("Supprimer un DVD") { context.startActivity((Intent(context, SupprDvdActivity::class.java)))} + SearchBar(searchQuery) { searchQuery = it } + + Spacer(modifier = Modifier.height(8.dp)) + + SortChip( + currentSort = sortType, + onSortSelected = { sortType = it } + ) + + Spacer(modifier = Modifier.height(8.dp)) + + DvdList( + dvds = filteredAndSortedDvds, + onDelete = { dvd -> + viewModel.deleteDvd(dvd) + } + ) + } } } -@Preview(showBackground = true) @Composable -fun MenuScreenPreview() { - CollectionDvdTheme { - com.dev.collectiondvd.MenuScreen() +fun TopBar() { + val context = LocalContext.current + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = "Votre Vidéothèque", + fontSize = 22.sp, + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleLarge + ) + + Row { + MyButton ("ⓘ"){ + context.startActivity( + Intent(context, StatDvdActivity::class.java) ) + } + } } -} \ No newline at end of file +} + +@Composable +fun SearchBar( + value: String, + onValueChange: (String) -> Unit +) { + OutlinedTextField( + value = value, + onValueChange = onValueChange, + placeholder = { Text("Chercher votre film (Par: titre, réal, etc)") }, + modifier = Modifier.fillMaxWidth(), + singleLine = true, + shape = RoundedCornerShape(50), + colors = TextFieldDefaults.colors( + focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, + unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent + ) + ) +} + +@Composable +fun SortChip( + currentSort: SortType, + onSortSelected: (SortType) -> Unit +) { + var expanded by remember { mutableStateOf(false) } + val context = LocalContext.current + Card( + modifier = Modifier.clickable { expanded = true }, + shape = RoundedCornerShape(50), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant + ) + ) { + Text( + text = "≡ ${currentSort.label}", + modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), + fontSize = 14.sp + ) + } + + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + SortType.values().forEach { sort -> + DropdownMenuItem( + text = { Text(sort.label) }, + onClick = { + expanded = false + onSortSelected(sort) + } + ) + } + } + + MyButton("Scanner") { + val intent = Intent(context, ScanCodeActivity::class.java) + context.startActivity(intent) + } + + +} + +@Composable +fun DvdList( + dvds: List, + onDelete: (Dvd) -> Unit +) { + LazyColumn { + items(dvds, key = { it.id }) { dvd -> + DvdItem(dvd = dvd, onDelete = onDelete) + } + } +} + +@Composable +fun DvdItem( + dvd: Dvd, + onDelete: (Dvd) -> Unit +) { + var expanded by remember { mutableStateOf(false) } + + Card( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 6.dp), + shape = RoundedCornerShape(12.dp) + ) { + Column { + + // Ligne du haut : titre + menu + Row( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.Top + ) { + Text( + dvd.titre.orEmpty().uppercase(), + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp, + color = Color(0xFFFFA405) + ) + + Box { + IconButton(onClick = { expanded = true }) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = "Menu" + ) + } + + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + DropdownMenuItem( + text = { Text("Supprimer") }, + leadingIcon = { + Icon( + imageVector = Icons.Default.Delete, + contentDescription = null + ) + }, + onClick = { + expanded = false + onDelete(dvd) + } + ) + DropdownMenuItem( + text = { Text("Modifier") }, + leadingIcon = { + Icon( + imageVector = Icons.Default.Edit, + contentDescription = null + ) + }, + onClick = {} + ) + } + } + } + + Divider() + + // 📀 Contenu + Row( + modifier = Modifier.padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + + Box( + modifier = Modifier + .height(90.dp) + .width(60.dp) + .background( + MaterialTheme.colorScheme.surfaceVariant, + RoundedCornerShape(8.dp) + ) + ) + + Spacer(modifier = Modifier.width(12.dp)) + + Column { + Text("Réalisateur: ${dvd.realisateur.orEmpty().uppercase()}") + Text("Année: ${dvd.annee.orEmpty()}") + Text("Genre: ${dvd.genre.orEmpty().uppercase()}") + } + } + } + } +} diff --git a/app/src/main/java/com/dev/collectiondvd/data/local/AppDatabase.kt b/app/src/main/java/com/dev/collectiondvd/data/local/AppDatabase.kt index cff73ac..df73645 100644 --- a/app/src/main/java/com/dev/collectiondvd/data/local/AppDatabase.kt +++ b/app/src/main/java/com/dev/collectiondvd/data/local/AppDatabase.kt @@ -7,7 +7,7 @@ import androidx.room.RoomDatabase import com.dev.collectiondvd.data.local.dao.DvdDao import com.dev.collectiondvd.data.local.entities.Dvd -@Database( entities = [Dvd::class], version = 1) +@Database( entities = [Dvd::class], version = 2) abstract class AppDatabase : RoomDatabase(){ abstract fun dvdDao(): DvdDao @@ -21,7 +21,7 @@ abstract class AppDatabase : RoomDatabase(){ context.applicationContext, AppDatabase::class.java, "dvd_manager" - ).build().also { INSTANCE = it } + ).fallbackToDestructiveMigration().build().also { INSTANCE = it } } } diff --git a/app/src/main/java/com/dev/collectiondvd/data/local/dao/DvdDao.kt b/app/src/main/java/com/dev/collectiondvd/data/local/dao/DvdDao.kt index 363b246..b275c64 100644 --- a/app/src/main/java/com/dev/collectiondvd/data/local/dao/DvdDao.kt +++ b/app/src/main/java/com/dev/collectiondvd/data/local/dao/DvdDao.kt @@ -22,5 +22,8 @@ interface DvdDao{ @Query("SELECT * FROM dvds WHERE id = :numero") fun getDvdById(numero: Long): Flow + @Query("SELECT * FROM dvds WHERE barcode = :barcode LIMIT 1") + suspend fun getByBarcode(barcode: String): Dvd? + } \ No newline at end of file diff --git a/app/src/main/java/com/dev/collectiondvd/data/local/entities/Dvd.kt b/app/src/main/java/com/dev/collectiondvd/data/local/entities/Dvd.kt index 5c4f30a..7e0d5e4 100644 --- a/app/src/main/java/com/dev/collectiondvd/data/local/entities/Dvd.kt +++ b/app/src/main/java/com/dev/collectiondvd/data/local/entities/Dvd.kt @@ -11,5 +11,7 @@ data class Dvd ( val annee: String, val realisateur: String, val genre: String, - val synced: Boolean = false + val synced: Boolean = false, + val barcode: String? = null, + val poster: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/dev/collectiondvd/ui/img/Collec.png b/app/src/main/java/com/dev/collectiondvd/ui/img/Collec.png new file mode 100644 index 0000000..c46bed9 Binary files /dev/null and b/app/src/main/java/com/dev/collectiondvd/ui/img/Collec.png differ diff --git a/app/src/main/java/com/dev/collectiondvd/ui/screen/AjoutDvdActivity.kt b/app/src/main/java/com/dev/collectiondvd/ui/screen/AjoutDvdActivity.kt index 1d29b77..ac9a6b2 100644 --- a/app/src/main/java/com/dev/collectiondvd/ui/screen/AjoutDvdActivity.kt +++ b/app/src/main/java/com/dev/collectiondvd/ui/screen/AjoutDvdActivity.kt @@ -12,9 +12,16 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.FabPosition import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -22,14 +29,17 @@ import androidx.compose.runtime.remember 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.unit.dp import androidx.compose.ui.unit.sp import com.dev.collectiondvd.data.local.AppDatabase import com.dev.collectiondvd.data.local.entities.Dvd import com.dev.collectiondvd.data.repository.LocalDvdRepository +import com.dev.collectiondvd.ui.theme.CollectionDvdTheme import com.dev.collectiondvd.ui.theme.MyButton import com.dev.collectiondvd.viewmodel.LocalDvdViewModel import com.dev.collectiondvd.viewmodel.factory.LocalDvdViewModelFactory +import org.intellij.lang.annotations.JdkConstants class AjoutDvdActivity : ComponentActivity() { @@ -43,79 +53,118 @@ class AjoutDvdActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val barcode = intent.getStringExtra("barcode") setContent { - AjoutDvdScreen(onQuit = { finish() }, onAdd = - { dvd -> - viewModel.addDvd(dvd) - finish() - } - ) + CollectionDvdTheme(darkTheme = true) { + AjoutDvdScreen( + onQuit = { finish() }, + onAdd = { dvd -> + viewModel.addDvd(dvd) + finish() + }, + preFilledBarcode = barcode + ) + } } } } + @Composable -fun AjoutDvdScreen(onQuit: () -> Unit, onAdd: (Dvd) -> Unit){ - //val context = LocalContext.current - var titre by remember() { mutableStateOf("") } - var annee by remember() { mutableStateOf("") } - var realisateur by remember() { mutableStateOf("") } - var genre by remember() { mutableStateOf("") } - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text("Ajouter un dvd", - fontSize = 26.sp, - style = MaterialTheme.typography.titleLarge, - modifier = Modifier.padding(bottom = 20.dp) - ) +fun AjoutDvdScreen( + onQuit: () -> Unit, + onAdd: (Dvd) -> Unit, + preFilledBarcode: String? = null +) { + var titre by remember { mutableStateOf("") } + var annee by remember { mutableStateOf("") } + var realisateur by remember { mutableStateOf("") } + var genre by remember { mutableStateOf("") } + var barcode by remember { mutableStateOf(preFilledBarcode?: "") } - OutlinedTextField( - value = titre, - onValueChange = { newValue -> titre = newValue }, - label = {Text("Titre")}, - modifier = Modifier.fillMaxWidth() - ) - OutlinedTextField( - value = realisateur, - onValueChange = { newValue -> realisateur = newValue }, - label = {Text("Réalisateur")}, - modifier = Modifier.fillMaxWidth() - ) - OutlinedTextField( - value = annee, - onValueChange = { newValue -> annee = newValue }, - label = {Text("Année")}, - modifier = Modifier.fillMaxWidth() - ) - OutlinedTextField( - value = genre, - onValueChange = { newValue -> genre = newValue }, - label = {Text("Genre")}, - modifier = Modifier.fillMaxWidth() - ) + Scaffold( + containerColor = MaterialTheme.colorScheme.background, // fond sombre - Spacer(modifier = Modifier.height(20.dp)) + ) { padding -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(padding) + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { - Column { - MyButton("Ajouter") { - if(titre.isNotBlank()){ - onAdd( - Dvd( - titre = titre, - annee = annee, - realisateur = realisateur, - genre = genre + Text( + "Ajouter un DVD", + fontSize = 26.sp, + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onBackground + ) + + // Champs stylisés + StyledTextField(value = titre, onValueChange = { titre = it }, label = "Titre") + + StyledTextField(value = barcode, onValueChange = { barcode = it }, label = "Code-barres") + + StyledTextField(value = realisateur, onValueChange = { realisateur = it }, label = "Réalisateur") + StyledTextField(value = annee, onValueChange = { annee = it }, label = "Année") + StyledTextField(value = genre, onValueChange = { genre = it }, label = "Genre") + + + + Spacer(modifier = Modifier.height(16.dp)) + + Row{ + MyButton("Valider") { + if (titre.isNotBlank()) { + onAdd( + Dvd( + titre = titre, + annee = annee, + realisateur = realisateur, + genre = genre + ) ) - ) + } + } + MyButton("Quitter") { onQuit() } + + Button( + onClick = { } + ) { + Text("Scanner un DVD") } } } - } -} \ No newline at end of file +} + +@Composable +fun StyledTextField( + value: String, + onValueChange: (String) -> Unit, + label: String +) { + OutlinedTextField( + value = value, + onValueChange = onValueChange, + placeholder = { Text(label, color = MaterialTheme.colorScheme.onSurfaceVariant) }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(50), + colors = TextFieldDefaults.colors( + focusedTextColor = MaterialTheme.colorScheme.onSurface, + unfocusedTextColor = MaterialTheme.colorScheme.onSurface, + focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, + unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + focusedPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant, + unfocusedPlaceholderColor = MaterialTheme.colorScheme.onSurfaceVariant, + cursorColor = MaterialTheme.colorScheme.primary + ) + ) + +} diff --git a/app/src/main/java/com/dev/collectiondvd/ui/screen/ListDvdActivity.kt b/app/src/main/java/com/dev/collectiondvd/ui/screen/ListDvdActivity.kt deleted file mode 100644 index 4f97478..0000000 --- a/app/src/main/java/com/dev/collectiondvd/ui/screen/ListDvdActivity.kt +++ /dev/null @@ -1,90 +0,0 @@ -package com.dev.collectiondvd.ui.screen - -import android.graphics.ColorSpace -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Divider -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.dev.collectiondvd.data.local.AppDatabase -import com.dev.collectiondvd.data.repository.LocalDvdRepository -import com.dev.collectiondvd.ui.theme.MyButton -import com.dev.collectiondvd.viewmodel.LocalDvdViewModel -import com.dev.collectiondvd.viewmodel.factory.LocalDvdViewModelFactory - - -class ListDvdActivity : ComponentActivity() { - - private lateinit var viewModel: LocalDvdViewModel - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val database = AppDatabase.getDatabase(applicationContext) - val dvdDao = database.dvdDao() - val repository = LocalDvdRepository(dvdDao) - val factory = LocalDvdViewModelFactory(repository) - viewModel = ViewModelProvider(this, factory).get(LocalDvdViewModel::class.java) - setContent { ListDvdScreen(onQuit = { finish() }, viewModel = viewModel) } - } -} - -@Composable -fun ListDvdScreen( - viewModel: LocalDvdViewModel, - onQuit: ()-> Unit -){ - val dvds by viewModel.dvds.collectAsState(initial = emptyList()) - - Column( - modifier = Modifier - .fillMaxSize() - .padding(8.dp) - ) - { - - Text( - "Vos Dvds", - fontSize = 24.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(bottom = 8.dp) - ) - - if(dvds.isEmpty()){ - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.Center - ){ - Text("Aucun Dvd dans votre collection") - } - } else { - LazyColumn(modifier = Modifier.weight(1f)) { - items ( dvds, key = { it.id}) { dvd -> - Column(modifier = Modifier.padding(8.dp)) { - Text(dvd.titre.orEmpty()) - Text(dvd.realisateur.orEmpty()) - Text(dvd.annee.orEmpty()) - Text(dvd.genre.orEmpty()) - Divider() - } - } - } - } - MyButton("Quitter") { onQuit() } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/dev/collectiondvd/ui/screen/ScanCodeActivity.kt b/app/src/main/java/com/dev/collectiondvd/ui/screen/ScanCodeActivity.kt new file mode 100644 index 0000000..75a4a77 --- /dev/null +++ b/app/src/main/java/com/dev/collectiondvd/ui/screen/ScanCodeActivity.kt @@ -0,0 +1,134 @@ +package com.dev.collectiondvd.ui.screen + +import android.Manifest +import android.content.Intent +import android.os.Bundle +import android.util.Log +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts +import androidx.camera.core.CameraSelector +import androidx.camera.core.ImageAnalysis +import androidx.camera.core.Preview +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.camera.view.PreviewView +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.content.ContextCompat +import androidx.lifecycle.compose.LocalLifecycleOwner +import com.google.mlkit.vision.barcode.BarcodeScanning +import com.google.mlkit.vision.common.InputImage + +class ScanCodeActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // Permission launcher moderne + val requestPermissionLauncher = + registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> + if (isGranted) startScan() + else finish() // permission refusée + } + + if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) + != android.content.pm.PackageManager.PERMISSION_GRANTED + ) { + requestPermissionLauncher.launch(Manifest.permission.CAMERA) + } else { + startScan() + } + } + + private fun startScan() { + setContent { + ScanBarcodeScreen( + onBarcodeDetected = { code -> + Log.d("SCAN", "Barcode détecté: $code") + val intent = Intent(this, AjoutDvdActivity::class.java) + intent.putExtra("barcode", code) + startActivity(intent) + finish() + }, + onBack = { finish() } + ) + } + } +} + +@Composable +fun ScanBarcodeScreen( + onBarcodeDetected: (String) -> Unit, + onBack: () -> Unit +) { + val context = LocalContext.current + val lifecycleOwner = LocalLifecycleOwner.current + val cameraProviderFuture = remember { ProcessCameraProvider.getInstance(context) } + + // State pour éviter double scan + val scanned = remember { mutableStateOf(false) } + + AndroidView(factory = { ctx -> + val previewView = PreviewView(ctx) + + cameraProviderFuture.addListener({ + try { + val cameraProvider = cameraProviderFuture.get() + + val preview = Preview.Builder().build().also { + it.setSurfaceProvider(previewView.surfaceProvider) + } + + val barcodeScanner = BarcodeScanning.getClient() + + val imageAnalyzer = ImageAnalysis.Builder() + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build() + .also { analysis -> + analysis.setAnalyzer(ContextCompat.getMainExecutor(ctx)) { imageProxy -> + val mediaImage = imageProxy.image + if (mediaImage != null) { + val inputImage = InputImage.fromMediaImage( + mediaImage, + imageProxy.imageInfo.rotationDegrees + ) + barcodeScanner.process(inputImage) + .addOnSuccessListener { barcodes -> + if (!scanned.value) { + barcodes.forEach { barcode -> + barcode.rawValue?.let { code -> + scanned.value = true + onBarcodeDetected(code) + } + } + } + } + .addOnFailureListener { e -> + Log.e("SCAN", "Erreur ML Kit: ${e.message}") + } + .addOnCompleteListener { imageProxy.close() } + } else { + imageProxy.close() + } + } + } + + val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA + cameraProvider.unbindAll() + cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalyzer) + Log.d("SCAN", "CameraX bound") + } catch (e: Exception) { + Log.e("SCAN", "Erreur CameraX: ${e.message}") + e.printStackTrace() + } + }, ContextCompat.getMainExecutor(ctx)) + + previewView + }, modifier = Modifier.fillMaxSize()) +} diff --git a/app/src/main/java/com/dev/collectiondvd/ui/screen/StatDvdActivity.kt b/app/src/main/java/com/dev/collectiondvd/ui/screen/StatDvdActivity.kt new file mode 100644 index 0000000..0d6330f --- /dev/null +++ b/app/src/main/java/com/dev/collectiondvd/ui/screen/StatDvdActivity.kt @@ -0,0 +1,245 @@ +package com.dev.collectiondvd.ui.screen + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.Divider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +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.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.ViewModelProvider +import com.dev.collectiondvd.MenuScreen +import com.dev.collectiondvd.data.local.AppDatabase +import com.dev.collectiondvd.data.repository.LocalDvdRepository +import com.dev.collectiondvd.ui.theme.CollectionDvdTheme +import com.dev.collectiondvd.ui.theme.MyButton +import com.dev.collectiondvd.viewmodel.LocalDvdViewModel +import com.dev.collectiondvd.viewmodel.factory.LocalDvdViewModelFactory + +class StatDvdActivity: ComponentActivity() { + private lateinit var viewModel: LocalDvdViewModel + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val database = AppDatabase.getDatabase(applicationContext) + val dvdDao = database.dvdDao() + val repository = LocalDvdRepository(dvdDao) + val factory = LocalDvdViewModelFactory(repository) + viewModel = ViewModelProvider(this, factory).get(LocalDvdViewModel::class.java) + setContent { + CollectionDvdTheme(darkTheme = true) { + StatDvdScreen( + onQuit = { finish() }, + viewModel = viewModel + ) + } + } + } +} + + +@Composable +fun StatDvdScreen( + viewModel: LocalDvdViewModel, + onQuit: () -> Unit +) { + val dvds by viewModel.dvds.collectAsState(initial = emptyList()) + + val totalDvds = dvds.size + + val genresCount = dvds.groupingBy { it.genre }.eachCount() + val directorsCount = dvds.groupingBy { it.realisateur }.eachCount() + + val numberOfGenres = genresCount.size + val favoriteGenre = genresCount.maxByOrNull { it.value }?.key ?: "Aucun" + val favoriteDirector = directorsCount.maxByOrNull { it.value }?.key ?: "Aucun" + + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + + Column( + modifier = Modifier + .fillMaxSize() + .padding( + top = WindowInsets.statusBars + .asPaddingValues() + .calculateTopPadding() + ) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "Mes Statistiques", + style = MaterialTheme.typography.titleLarge.copy( + fontWeight = FontWeight.Bold + ) + ) + } + + + StatCardDvd(totalDvds) + StatCard("Réalisateur", directorsCount.size, favoriteDirector) + StatCard("Genre", numberOfGenres, favoriteGenre) + + Text("La suite est en développement...") + + //Spacer(modifier = Modifier.weight(0.5f)) + + MyButton("Quitter") { + onQuit() + } + } + } +} + +@Composable +fun StatCardDvd( + totalDvd :Int, +){ + var expended by remember { mutableStateOf(false) } + + Card( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 6.dp), + shape = RoundedCornerShape(12.dp) + ){ + Column { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.Top + ) { + Text( + "Films", + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp, + color = Color(0xFFFFA405) + ) + } + + Divider() + + Row( + modifier = Modifier.padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ){ + +// Box( +// modifier = Modifier +// .height(90.dp) +// .width(60.dp) +// .background( +// MaterialTheme.colorScheme.surfaceVariant, +// RoundedCornerShape(8.dp) +// ) +// ) + + Spacer(modifier = Modifier.width(12.dp)) + + Column { + Text("Vous possedez: ${totalDvd} Dvds") + } + + } + } + } +} + +@Composable +fun StatCard( + name: String, + total :Int, + preferer: String +){ + var expended by remember { mutableStateOf(false) } + + Card( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 6.dp), + shape = RoundedCornerShape(12.dp) + ){ + Column { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.Top + ) { + Text( + "${name}", + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp, + color = Color(0xFFFFA405) + ) + } + + Divider() + + Row( + modifier = Modifier.padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ){ + +// Box( +// modifier = Modifier +// .height(90.dp) +// .width(60.dp) +// .background( +// MaterialTheme.colorScheme.surfaceVariant, +// RoundedCornerShape(8.dp) +// ) +// ) + + Spacer(modifier = Modifier.width(12.dp)) + + Column { + Text("Vous avez: ${total} ${name}") + Text("Votre ${name} preferé est: ${preferer} ") + } + + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dev/collectiondvd/ui/screen/SupprDvdActivity.kt b/app/src/main/java/com/dev/collectiondvd/ui/screen/SupprDvdActivity.kt index 97e4d0e..0d3878b 100644 --- a/app/src/main/java/com/dev/collectiondvd/ui/screen/SupprDvdActivity.kt +++ b/app/src/main/java/com/dev/collectiondvd/ui/screen/SupprDvdActivity.kt @@ -3,8 +3,6 @@ package com.dev.collectiondvd.ui.screen import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.viewModels -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height @@ -97,7 +95,7 @@ fun SupprDvdScreen(onQuit: () -> Unit, viewModel: LocalDvdViewModel){ MyButton("Supprimer le Dvd") { - viewModel.deleteDvd() + viewModel.deleteDvd(dvd) selectedId = null } } diff --git a/app/src/main/java/com/dev/collectiondvd/ui/theme/Theme.kt b/app/src/main/java/com/dev/collectiondvd/ui/theme/Theme.kt index 9dd8451..e4005c6 100644 --- a/app/src/main/java/com/dev/collectiondvd/ui/theme/Theme.kt +++ b/app/src/main/java/com/dev/collectiondvd/ui/theme/Theme.kt @@ -3,7 +3,9 @@ package com.dev.collectiondvd.ui.theme import android.app.Activity import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme @@ -65,17 +67,15 @@ fun CollectionDvdTheme( } @Composable -fun MyButton( - text: String, - onClick: () -> Unit -) { +fun MyButton(text: String, onClick: () -> Unit) { Button( onClick = onClick, colors = ButtonDefaults.buttonColors( - containerColor = Color.Blue, // Couleur de fond - contentColor = Color.White // Couleur du texte + containerColor = Color(0xFFFFA405), // ton orange + contentColor = Color.Black ), - modifier = Modifier.size(width = 200.dp, height = 50.dp) // Taille uniforme + shape = RoundedCornerShape(50), + modifier = Modifier.padding(horizontal = 8.dp) ) { Text(text) } diff --git a/app/src/main/java/com/dev/collectiondvd/viewmodel/LocalDvdViewModel.kt b/app/src/main/java/com/dev/collectiondvd/viewmodel/LocalDvdViewModel.kt index 359fb6d..feda7fc 100644 --- a/app/src/main/java/com/dev/collectiondvd/viewmodel/LocalDvdViewModel.kt +++ b/app/src/main/java/com/dev/collectiondvd/viewmodel/LocalDvdViewModel.kt @@ -38,13 +38,21 @@ class LocalDvdViewModel ( } } - fun deleteDvd() { + fun deleteDvd(dvd: Dvd) { viewModelScope.launch { - _selectedDvd.value?.let { dvd -> - repository.deleteDvd(dvd) - _selectedDvd.value = null - } + repository.deleteDvd(dvd) } } + fun addDvdFromBarcode(barcode: String, titre: String, realisateur: String, annee: String, genre: String) { + addDvd(Dvd(titre = titre, realisateur = realisateur, annee = annee, genre = genre, barcode = barcode)) + } + +// fun getDvdByBarcode(barcode: String, onResult: (Dvd?) -> Unit) { +// viewModelScope.launch { +// val dvd = repository.getDvdByBarcode(barcode) +// onResult(dvd) +// } +// } + } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index 07d5da9..ca3826a 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,170 +1,74 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:android="http://schemas.android.com/apk/res/android"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 56% rename from app/src/main/res/mipmap-anydpi/ic_launcher.xml rename to app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 6f3b755..c4a603d 100644 --- a/app/src/main/res/mipmap-anydpi/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 56% rename from app/src/main/res/mipmap-anydpi/ic_launcher_round.xml rename to app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 6f3b755..c4a603d 100644 --- a/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp index c209e78..93f61ea 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..e05e2dc Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp index b2dfe3d..e290c05 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp index 4f0f1d6..ab25a54 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..3f0c039 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp index 62b611d..d48f02f 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp index 948a307..3c4f264 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..8fdbaea Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp index 1b9a695..d3d1f5d 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp index 28d4b77..3277d75 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..ba59729 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp index 9287f50..b0ca9b7 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp index aa7d642..ea35a83 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..3f3e546 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp index 9126ae3..13aa7f8 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7882b6..b4ad44d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,11 @@ espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.10.0" activityCompose = "1.12.1" composeBom = "2024.09.00" +uiGraphics = "1.10.0" +material3 = "1.4.0" +runtime = "1.10.0" +cameraLifecycle = "1.5.2" +cameraView = "1.5.2" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -24,6 +29,11 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u 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-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics", version.ref = "uiGraphics" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } +androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime", version.ref = "runtime" } +androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "cameraLifecycle" } +androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "cameraView" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }