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" }