diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 0fc3113..69e8615 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9749697..eae8623 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,6 +1,7 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
+ id("com.google.devtools.ksp")
}
android {
@@ -30,17 +31,17 @@ android {
}
}
compileOptions {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = "1.8"
+ jvmTarget = "17"
}
buildFeatures {
compose = true
}
composeOptions {
- kotlinCompilerExtensionVersion = "1.4.3"
+ kotlinCompilerExtensionVersion = "1.4.5"
}
packaging {
resources {
@@ -48,11 +49,16 @@ android {
}
}
}
+kotlin {
+ jvmToolchain(17)
+}
dependencies {
-
+ //Core
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
+
+ //UI
implementation("androidx.activity:activity-compose:1.7.2")
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
implementation("androidx.navigation:navigation-compose:2.6.0")
@@ -61,6 +67,16 @@ dependencies {
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
+
+ // Room
+ val room_version = "2.5.2"
+ implementation("androidx.room:room-runtime:$room_version")
+ annotationProcessor("androidx.room:room-compiler:$room_version")
+ ksp("androidx.room:room-compiler:$room_version")
+ implementation("androidx.room:room-ktx:$room_version")
+ implementation("androidx.room:room-paging:$room_version")
+
+ //Tests
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
diff --git a/app/src/main/java/com/example/mobile_labs/converters/LocalDateConverter.kt b/app/src/main/java/com/example/mobile_labs/converters/LocalDateConverter.kt
new file mode 100644
index 0000000..ff08e73
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/converters/LocalDateConverter.kt
@@ -0,0 +1,24 @@
+package com.example.mobile_labs.converters
+
+import androidx.room.TypeConverter
+import java.time.LocalDate
+import java.time.LocalDateTime
+
+
+
+
+class LocalDateConverter {
+ @TypeConverter
+ fun toDate(dateString: String?): LocalDate? {
+ return if (dateString == null) {
+ null
+ } else {
+ LocalDate.parse(dateString)
+ }
+ }
+
+ @TypeConverter
+ fun toDateString(date: LocalDate?): String? {
+ return date?.toString()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/database/AppDatabase.kt b/app/src/main/java/com/example/mobile_labs/database/AppDatabase.kt
new file mode 100644
index 0000000..f10abbd
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/database/AppDatabase.kt
@@ -0,0 +1,118 @@
+package com.example.mobile_labs.database
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import androidx.sqlite.db.SupportSQLiteDatabase
+import com.example.mobile_labs.event.dao.EventDao
+import com.example.mobile_labs.event.model.Event
+import com.example.mobile_labs.performance.dao.PerformanceDao
+import com.example.mobile_labs.performance.dao.PerformancePersonDao
+import com.example.mobile_labs.performance.model.Performance
+import com.example.mobile_labs.performance.model.PerformancePersonCrossRef
+import com.example.mobile_labs.person.dao.PersonDao
+import com.example.mobile_labs.person.model.Person
+import com.example.mobile_labs.user.dao.UserDao
+import com.example.mobile_labs.user.model.User
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import java.time.LocalDate
+
+@Database(entities = [Performance::class, Person::class, Event::class, PerformancePersonCrossRef::class, User::class], version = 1, exportSchema = false)
+abstract class AppDatabase : RoomDatabase() {
+ abstract fun personDao(): PersonDao
+ abstract fun performanceDao(): PerformanceDao
+ abstract fun eventDao(): EventDao
+ abstract fun performancePersonDao(): PerformancePersonDao
+ abstract fun userDao(): UserDao
+
+ companion object {
+ private const val DB_NAME: String = "theatre-db"
+
+ @Volatile
+ private var INSTANCE: AppDatabase? = null
+
+ private suspend fun populateDatabase() {
+ INSTANCE?.let { database ->
+ //people
+ val personDao = database.personDao()
+ val person1 = Person(1, "Иванов", "Иван", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg")
+ val person2 = Person(2, "Ксения", "Дудникова", "https://bolshoi.ru/media/members/photos/1756_ru_wkznwzklgosnbiq_300x300_p.jpg")
+ val person3 = Person(3, "Евгения", "Сегенюк", "https://bolshoi.ru/media/members/photos/2908_ru_rycynrihdpzvgdj_300x300_p.jpg")
+ val person4 = Person(4, "Петров", "Петр", "https://bolshoi.ru/media/members/photos/15820_ru_zvewuwadyjuywkh_300x300_p.jpg")
+
+ personDao.insert(person1)
+ personDao.insert(person2)
+ personDao.insert(person3)
+ personDao.insert(person4)
+
+ val performanceDao = database.performanceDao()
+ val performance1 = Performance(1, "Представление 1", "Описание представления 1", 1, 2, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg")
+ val performance2 = Performance(2, "Представление 2", "Описание представления 2", 2, 3, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg")
+ val performance3 = Performance(3, "Представление 3", "Описание представления 1", 3, 4, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg")
+
+ performanceDao.insert(performance1)
+ performanceDao.insert(performance2)
+ performanceDao.insert(performance3)
+
+ val performancePersonDao = database.performancePersonDao()
+ val performancePerson1 = PerformancePersonCrossRef(1, 1)
+ val performancePerson2 = PerformancePersonCrossRef(1, 2)
+ val performancePerson3 = PerformancePersonCrossRef(1, 3)
+ val performancePerson4 = PerformancePersonCrossRef(1, 4)
+
+ performancePersonDao.insert(performancePerson1)
+ performancePersonDao.insert(performancePerson2)
+ performancePersonDao.insert(performancePerson3)
+ performancePersonDao.insert(performancePerson4)
+
+ val eventDao = database.eventDao()
+ val event1 = Event(1, LocalDate.parse("2023-10-23"), 1)
+ val event2 = Event(2, LocalDate.parse("2023-10-11"), 2)
+ val event3 = Event(3, LocalDate.parse("2023-10-15"), 3)
+ val event4 = Event(4, LocalDate.parse("2023-10-27"), 1)
+ val event5 = Event(5, LocalDate.parse("2023-10-03"), 2)
+ val event6 = Event(6, LocalDate.parse("2023-10-09"), 3)
+ val event7 = Event(7, LocalDate.parse("2023-11-03"), 2)
+ val event8 = Event(8, LocalDate.parse("2023-11-09"), 3)
+
+ eventDao.insert(event1)
+ eventDao.insert(event2)
+ eventDao.insert(event3)
+ eventDao.insert(event4)
+ eventDao.insert(event5)
+ eventDao.insert(event6)
+ eventDao.insert(event7)
+ eventDao.insert(event8)
+
+ val userDao = database.userDao()
+ val user1 = User(1, "test@example.com", "1234", "John", "Doe")
+ val user2 = User(2, "test@example.com", "1234", "John", "Doe")
+ userDao.insert(user1)
+ userDao.insert(user2)
+ }
+ }
+
+ fun getInstance(appContext: Context): AppDatabase {
+ return INSTANCE ?: synchronized(this) {
+ Room.databaseBuilder(
+ appContext,
+ AppDatabase::class.java,
+ DB_NAME
+ )
+ .addCallback(object : RoomDatabase.Callback() {
+ override fun onCreate(db: SupportSQLiteDatabase) {
+ super.onCreate(db)
+ CoroutineScope(Dispatchers.IO).launch {
+ populateDatabase()
+ }
+ }
+ })
+ .build()
+ .also { INSTANCE = it }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt b/app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt
index f384205..c243017 100644
--- a/app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt
+++ b/app/src/main/java/com/example/mobile_labs/event/composeui/Schedule.kt
@@ -15,30 +15,51 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
-import com.example.mobile_labs.event.model.getTestEvents
+import com.example.mobile_labs.database.AppDatabase
+import com.example.mobile_labs.event.model.EventWithPerformance
+import com.example.mobile_labs.person.model.Person
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import java.time.LocalDate
import java.time.format.DateTimeFormatter
+import java.util.Calendar
@Composable
fun Schedule(navController: NavController?) {
+ val context = LocalContext.current
+ val events = remember { mutableStateListOf() }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ val dateNow = LocalDate.now().toString()
+ AppDatabase.getInstance(context).eventDao().getAllWithPerformance(dateNow).collect { data ->
+ events.clear()
+ events.addAll(data)
+ }
+ }
+ }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(all = 10.dp)
.verticalScroll(rememberScrollState())) {
- getTestEvents().forEachIndexed() { _, event ->
- val performanceId = Screen.PerformanceView.route.replace("{id}", event.performance.id.toString())
+ events.forEachIndexed() { _, event ->
+ val performanceId = Screen.PerformanceView.route.replace("{id}", event.performance.performance_uid.toString())
Row(Modifier.padding(all = 10.dp)) {
- Text(modifier = Modifier.padding(all = 5.dp), textAlign = TextAlign.Center, text = event.date.format(DateTimeFormatter.ofPattern("dd.MM")))
+ Text(modifier = Modifier.padding(all = 5.dp), textAlign = TextAlign.Center, text = event.event.date.format(DateTimeFormatter.ofPattern("dd.MM")))
AsyncImage(model = event.performance.previewImageURL,
contentDescription = "performance preview image",
contentScale = ContentScale.Crop,
diff --git a/app/src/main/java/com/example/mobile_labs/event/dao/EventDao.kt b/app/src/main/java/com/example/mobile_labs/event/dao/EventDao.kt
new file mode 100644
index 0000000..6525c85
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/event/dao/EventDao.kt
@@ -0,0 +1,32 @@
+package com.example.mobile_labs.event.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import com.example.mobile_labs.event.model.Event
+import com.example.mobile_labs.event.model.EventWithPerformance
+import com.example.mobile_labs.performance.model.Performance
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface EventDao {
+ @Query("select * from events order by date asc")
+ fun getAll(): Flow>
+
+ @Query("select * from events where events.date > :dateFrom order by date asc")
+ fun getAllWithPerformance(dateFrom: String): Flow>
+
+ @Query("select * from events where events.uid = :uid")
+ suspend fun getByUid(uid: Int): EventWithPerformance
+
+ @Insert
+ suspend fun insert(event: Event)
+
+ @Update
+ suspend fun update(event: Event)
+
+ @Delete
+ suspend fun delete(event: Event)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/event/model/Event.kt b/app/src/main/java/com/example/mobile_labs/event/model/Event.kt
index ce7c878..ce3a46a 100644
--- a/app/src/main/java/com/example/mobile_labs/event/model/Event.kt
+++ b/app/src/main/java/com/example/mobile_labs/event/model/Event.kt
@@ -1,27 +1,32 @@
package com.example.mobile_labs.event.model
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import androidx.room.PrimaryKey
+import androidx.room.TypeConverter
+import androidx.room.TypeConverters
+import com.example.mobile_labs.converters.LocalDateConverter
import com.example.mobile_labs.performance.model.Performance
import com.example.mobile_labs.person.model.Person
import java.io.Serializable
import java.time.LocalDate
+@TypeConverters(LocalDateConverter::class)
+@Entity(tableName = "events", foreignKeys = [
+ ForeignKey(
+ entity = Performance::class,
+ parentColumns = ["performance_uid"],
+ childColumns = ["performance_id"],
+ onDelete = ForeignKey.RESTRICT,
+ onUpdate = ForeignKey.RESTRICT,
+ ),
+])
data class Event(
+ @PrimaryKey(autoGenerate = true)
+ val uid: Int?,
val date: LocalDate,
- val performance: Performance,
-) : Serializable
+ @ColumnInfo(name = "performance_id")
+ val performanceId: Int?,
+)
-fun getTestEvents(): List {
- val director = Person("Иванов", "Иван", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg");
- val author = Person("Петров", "Петр", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg");
- val actors = listOf(director, author);
- val performances = listOf(
- Performance(0,"Представление #1", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(1,"Представление #2", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(2,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- )
- return listOf(
- Event(LocalDate.parse("2023-10-15"), performances[0]),
- Event(LocalDate.parse("2023-10-16"), performances[1]),
- Event(LocalDate.parse("2023-10-17"), performances[2])
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/event/model/EventWithPerformance.kt b/app/src/main/java/com/example/mobile_labs/event/model/EventWithPerformance.kt
new file mode 100644
index 0000000..715e743
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/event/model/EventWithPerformance.kt
@@ -0,0 +1,12 @@
+package com.example.mobile_labs.event.model
+
+import androidx.room.Embedded
+import androidx.room.Relation
+import com.example.mobile_labs.performance.model.Performance
+
+data class EventWithPerformance (
+ @Embedded
+ val event: Event,
+ @Relation(entity = Performance::class, parentColumn = "performance_id", entityColumn = "performance_uid")
+ val performance: Performance,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/performance/composeui/PerformanceView.kt b/app/src/main/java/com/example/mobile_labs/performance/composeui/PerformanceView.kt
index 248eb99..be1f0b9 100644
--- a/app/src/main/java/com/example/mobile_labs/performance/composeui/PerformanceView.kt
+++ b/app/src/main/java/com/example/mobile_labs/performance/composeui/PerformanceView.kt
@@ -17,6 +17,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -24,6 +25,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
@@ -32,16 +34,25 @@ import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
-import com.example.mobile_labs.performance.model.getTestPerformances
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
import com.example.mobile_labs.R
+import com.example.mobile_labs.database.AppDatabase
+import com.example.mobile_labs.performance.model.PerformanceWithPeople
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PerformanceView(id: Int) {
- var performance = getTestPerformances()[id]
+ val context = LocalContext.current
+ val (performaceWithPeople, setPerformanceWithPeople) = remember { mutableStateOf(null) }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ setPerformanceWithPeople(AppDatabase.getInstance(context).performanceDao().getByUid(id))
+ }
+ }
var actorsText = ""
- performance.actors.forEach {
+ performaceWithPeople?.actors?.forEach {
if (actorsText != "") actorsText += "\n"
actorsText += "${it.last_name} ${it.first_name}"
}
@@ -50,10 +61,10 @@ fun PerformanceView(id: Int) {
modifier = Modifier
.padding(all = 10.dp)
.verticalScroll(rememberScrollState())) {
- Text(text = "${performance.author.last_name} ${performance.author.first_name}", textAlign = TextAlign.Center)
- Text(text = performance.title, textAlign = TextAlign.Center, fontSize = 30.sp)
- AsyncImage(model = performance.imageURL, contentDescription = "performance image")
- OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = performance.description, onValueChange = {}, readOnly = true,
+ Text(text = "${performaceWithPeople?.author?.last_name} ${performaceWithPeople?.author?.first_name}", textAlign = TextAlign.Center)
+ Text(text = performaceWithPeople?.performance?.title ?: "", textAlign = TextAlign.Center, fontSize = 30.sp)
+ AsyncImage(model = performaceWithPeople?.performance?.imageURL, contentDescription = "performance image")
+ OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = performaceWithPeople?.performance?.description ?: "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.performance_description))
}
diff --git a/app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt b/app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt
index 6438da9..453bfb2 100644
--- a/app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt
+++ b/app/src/main/java/com/example/mobile_labs/performance/composeui/Repertoire.kt
@@ -1,6 +1,7 @@
package com.example.mobile_labs.performance.composeui
import android.content.res.Configuration
+import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
@@ -16,6 +17,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
@@ -28,30 +30,51 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
+import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.performance.model.Performance
-import com.example.mobile_labs.performance.model.getTestPerformances
+import com.example.mobile_labs.person.model.Person
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
-
-var performances by mutableStateOf(getTestPerformances())
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Repertoire(navController: NavController?) {
+ val context = LocalContext.current
+ val performances = remember { mutableStateListOf() }
+ var performancesFiltered = remember { mutableStateListOf() }
var title by remember { mutableStateOf("") }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ AppDatabase.getInstance(context).performanceDao().getAll().collect { data ->
+ performances.clear()
+ performances.addAll(data)
+ performancesFiltered.addAll(data)
+ }
+ }
+ }
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(all = 10.dp)
.verticalScroll(rememberScrollState())) {
- TextField(value = title, label = {Text(text = "Поиск...")}, onValueChange = { title = it; performances =
- if (title != "") getTestPerformances().filter { performance -> performance.title.contains(title) } else getTestPerformances() })
- performances.forEachIndexed() { index, performance ->
- val performanceId = Screen.PerformanceView.route.replace("{id}", performance.id.toString())
+ TextField(value = title, label = {Text(text = "Поиск...")}, onValueChange = { title = it;
+ if (title != "") {
+ val data = performances.filter { performance -> performance.title.contains(title) }
+ performancesFiltered.clear()
+ performancesFiltered.addAll(data)
+ } else {
+ performancesFiltered.clear()
+ performancesFiltered.addAll(performances)
+ } })
+ performancesFiltered.forEachIndexed() { index, performance ->
+ val performanceId = Screen.PerformanceView.route.replace("{id}", performance.performance_uid.toString())
Row(Modifier.padding(all = 10.dp)) {
AsyncImage(model = performance.previewImageURL,
contentDescription = "performance preview image",
diff --git a/app/src/main/java/com/example/mobile_labs/performance/dao/PerformanceDao.kt b/app/src/main/java/com/example/mobile_labs/performance/dao/PerformanceDao.kt
new file mode 100644
index 0000000..ff1d8b4
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/performance/dao/PerformanceDao.kt
@@ -0,0 +1,29 @@
+package com.example.mobile_labs.performance.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import com.example.mobile_labs.performance.model.Performance
+import com.example.mobile_labs.performance.model.PerformanceWithPeople
+import com.example.mobile_labs.person.model.Person
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface PerformanceDao {
+ @Query("select * from performances order by title collate nocase asc")
+ fun getAll(): Flow>
+
+ @Query("select * from performances where performances.performance_uid = :uid")
+ suspend fun getByUid(uid: Int): PerformanceWithPeople
+
+ @Insert
+ suspend fun insert(performance: Performance)
+
+ @Update
+ suspend fun update(performance: Performance)
+
+ @Delete
+ suspend fun delete(performance: Performance)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/performance/dao/PerformancePersonDao.kt b/app/src/main/java/com/example/mobile_labs/performance/dao/PerformancePersonDao.kt
new file mode 100644
index 0000000..cf1ee34
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/performance/dao/PerformancePersonDao.kt
@@ -0,0 +1,26 @@
+package com.example.mobile_labs.performance.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import com.example.mobile_labs.performance.model.Performance
+import com.example.mobile_labs.performance.model.PerformancePersonCrossRef
+import com.example.mobile_labs.performance.model.PerformanceWithPeople
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface PerformancePersonDao {
+ @Query("select * from performance_person")
+ fun getAll(): Flow>
+
+ @Insert
+ suspend fun insert(performancePersonCrossRef: PerformancePersonCrossRef)
+
+ @Update
+ suspend fun update(performancePersonCrossRef: PerformancePersonCrossRef)
+
+ @Delete
+ suspend fun delete(performancePersonCrossRef: PerformancePersonCrossRef)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/performance/model/Performance.kt b/app/src/main/java/com/example/mobile_labs/performance/model/Performance.kt
index d3b5c34..4d89099 100644
--- a/app/src/main/java/com/example/mobile_labs/performance/model/Performance.kt
+++ b/app/src/main/java/com/example/mobile_labs/performance/model/Performance.kt
@@ -1,34 +1,52 @@
package com.example.mobile_labs.performance.model
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import androidx.room.PrimaryKey
import com.example.mobile_labs.person.model.Person
import java.io.Serializable
+@Entity(tableName = "performances", foreignKeys = [
+ ForeignKey(
+ entity = Person::class,
+ parentColumns = ["uid"],
+ childColumns = ["director_id"],
+ onDelete = ForeignKey.RESTRICT,
+ onUpdate = ForeignKey.RESTRICT,
+ ),
+ ForeignKey(
+ entity = Person::class,
+ parentColumns = ["uid"],
+ childColumns = ["author_id"],
+ onDelete = ForeignKey.RESTRICT,
+ onUpdate = ForeignKey.RESTRICT,
+ ),
+ ]
+)
data class Performance(
- val id: Int,
+ @PrimaryKey(autoGenerate = true)
+ val performance_uid: Int?,
val title: String,
val description: String,
- val author: Person,
- val director: Person,
- val actors: List,
+ @ColumnInfo(name = "author_id", index = true)
+ val authorId: Int?,
+ @ColumnInfo(name = "director_id", index = true)
+ val directorId: Int?,
+ @ColumnInfo(name = "image_url")
val imageURL: String,
+ @ColumnInfo(name = "preview_image_url")
val previewImageURL: String,
-) : Serializable
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+ other as Performance
+ if (performance_uid != other.performance_uid) return false
+ return true
+ }
-fun getTestPerformances(): List {
- val director = Person("Иванов", "Иван", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg");
- val author = Person("Петров", "Петр", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg");
- val actors = listOf(director, author);
- return listOf(
- Performance(0,"Представление #1", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(1,"Представление #2", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(2,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(3,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(4,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(5,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(6,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(7,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(8,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(9,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- Performance(10,"Представление #3", "Netus quis congue nascetur ullamcorper nibh, nostra iaculis turpis!", author, director, actors, "https://img.freepik.com/free-photo/empty-stage-with-few-props-red-seats_181624-57595.jpg?w=1380&t=st=1696959739~exp=1696960339~hmac=2107448a1d874f1315b5cf246c71df70dc653707c7c8be4a38581d3b73f842ba", "https://www.theatreinparis.com/uploads/images/article/theatre-de-l-athenee-dr.jpg"),
- )
-}
\ No newline at end of file
+ override fun hashCode(): Int {
+ return performance_uid ?: -1
+ }
+}
diff --git a/app/src/main/java/com/example/mobile_labs/performance/model/PerformancePersonCrossRef.kt b/app/src/main/java/com/example/mobile_labs/performance/model/PerformancePersonCrossRef.kt
new file mode 100644
index 0000000..3dcdb40
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/performance/model/PerformancePersonCrossRef.kt
@@ -0,0 +1,9 @@
+package com.example.mobile_labs.performance.model
+
+import androidx.room.Entity
+
+@Entity(tableName = "performance_person", primaryKeys = ["performance_uid", "uid"])
+data class PerformancePersonCrossRef(
+ val performance_uid: Int,
+ val uid: Int,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/performance/model/PerformanceWithPeople.kt b/app/src/main/java/com/example/mobile_labs/performance/model/PerformanceWithPeople.kt
new file mode 100644
index 0000000..5ba6849
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/performance/model/PerformanceWithPeople.kt
@@ -0,0 +1,22 @@
+package com.example.mobile_labs.performance.model
+
+import androidx.room.ColumnInfo
+import androidx.room.Embedded
+import androidx.room.Junction
+import androidx.room.Relation
+import com.example.mobile_labs.person.model.Person
+
+data class PerformanceWithPeople (
+ @Embedded
+ val performance: Performance,
+ @Relation(entity = Person::class, parentColumn = "author_id", entityColumn = "uid")
+ val author: Person,
+ @Relation(entity = Person::class, parentColumn = "director_id", entityColumn = "uid")
+ val director: Person,
+ @Relation(
+ parentColumn = "performance_uid",
+ entityColumn = "uid",
+ associateBy = Junction(PerformancePersonCrossRef::class),
+ )
+ val actors: List
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt b/app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt
index 87ebb24..343545e 100644
--- a/app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt
+++ b/app/src/main/java/com/example/mobile_labs/person/composeui/PeopleList.kt
@@ -15,26 +15,42 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.mobile_labs.composeui.navigation.Screen
+import com.example.mobile_labs.database.AppDatabase
import com.example.mobile_labs.performance.composeui.Repertoire
-import com.example.mobile_labs.performance.model.getTestPerformances
-import com.example.mobile_labs.person.model.getTestPerson
+import com.example.mobile_labs.person.model.Person
import com.example.mobile_labs.ui.theme.Mobile_LabsTheme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
@Composable
fun PeopleList(navController: NavController?) {
+ val context = LocalContext.current
+ val people = remember { mutableStateListOf() }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ AppDatabase.getInstance(context).personDao().getAll().collect { data ->
+ people.clear()
+ people.addAll(data)
+ }
+ }
+ }
Column(Modifier.padding(all = 10.dp)) {
LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 100.dp))
{
- items(getTestPerson()) {
+ items(people) {
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier
.width(300.dp)
.height(200.dp)) {
diff --git a/app/src/main/java/com/example/mobile_labs/person/dao/PersonDao.kt b/app/src/main/java/com/example/mobile_labs/person/dao/PersonDao.kt
new file mode 100644
index 0000000..e7d0962
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/person/dao/PersonDao.kt
@@ -0,0 +1,27 @@
+package com.example.mobile_labs.person.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import com.example.mobile_labs.person.model.Person
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface PersonDao {
+ @Query("select * from people order by last_name collate nocase asc")
+ fun getAll(): Flow>
+
+ @Query("select * from people where people.uid = :uid")
+ suspend fun getByUid(uid: Int): Person
+
+ @Insert
+ suspend fun insert(person: Person)
+
+ @Update
+ suspend fun update(person: Person)
+
+ @Delete
+ suspend fun delete(person: Person)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/person/model/Person.kt b/app/src/main/java/com/example/mobile_labs/person/model/Person.kt
index c2694e5..32934cf 100644
--- a/app/src/main/java/com/example/mobile_labs/person/model/Person.kt
+++ b/app/src/main/java/com/example/mobile_labs/person/model/Person.kt
@@ -1,26 +1,29 @@
package com.example.mobile_labs.person.model
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Ignore
+import androidx.room.PrimaryKey
import java.io.Serializable
+@Entity(tableName = "people")
data class Person(
+ @PrimaryKey(autoGenerate = true)
+ val uid: Int?,
val last_name: String,
val first_name: String,
+ @ColumnInfo(name = "image_url")
val imageURL: String,
-) : Serializable
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+ other as Person
+ if (uid != other.uid) return false
+ return true
+ }
-fun getTestPerson(): List {
- return listOf(
- Person("Иванов", "Иван", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg"),
- Person("Ксения", "Дудникова", "https://bolshoi.ru/media/members/photos/1756_ru_wkznwzklgosnbiq_300x300_p.jpg"),
- Person("Евгения", "Сегенюк", "https://bolshoi.ru/media/members/photos/2908_ru_rycynrihdpzvgdj_300x300_p.jpg"),
- Person("Петров", "Петр", "https://bolshoi.ru/media/members/photos/15820_ru_zvewuwadyjuywkh_300x300_p.jpg"),
- Person("Иванов", "Иван", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg"),
- Person("Ксения", "Дудникова", "https://bolshoi.ru/media/members/photos/1756_ru_wkznwzklgosnbiq_300x300_p.jpg"),
- Person("Евгения", "Сегенюк", "https://bolshoi.ru/media/members/photos/2908_ru_rycynrihdpzvgdj_300x300_p.jpg"),
- Person("Петров", "Петр", "https://bolshoi.ru/media/members/photos/15820_ru_zvewuwadyjuywkh_300x300_p.jpg"),
- Person("Иванов", "Иван", "https://bolshoi.ru/media/members/photos/86_ru_twyyatusbnifnzi_300x300_p.jpg"),
- Person("Ксения", "Дудникова", "https://bolshoi.ru/media/members/photos/1756_ru_wkznwzklgosnbiq_300x300_p.jpg"),
- Person("Евгения", "Сегенюк", "https://bolshoi.ru/media/members/photos/2908_ru_rycynrihdpzvgdj_300x300_p.jpg"),
- Person("Петров", "Петр", "https://bolshoi.ru/media/members/photos/15820_ru_zvewuwadyjuywkh_300x300_p.jpg"),
- )
+ override fun hashCode(): Int {
+ return uid ?: -1
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/user/dao/UserDao.kt b/app/src/main/java/com/example/mobile_labs/user/dao/UserDao.kt
new file mode 100644
index 0000000..9529bc9
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/user/dao/UserDao.kt
@@ -0,0 +1,28 @@
+package com.example.mobile_labs.user.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import com.example.mobile_labs.person.model.Person
+import com.example.mobile_labs.user.model.User
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface UserDao {
+ @Query("select * from users order by last_name collate nocase asc")
+ fun getAll(): Flow>
+
+ @Query("select * from users where users.uid = :uid")
+ suspend fun getByUid(uid: Int): User
+
+ @Insert
+ suspend fun insert(user: User)
+
+ @Update
+ suspend fun update(user: User)
+
+ @Delete
+ suspend fun delete(user: User)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/mobile_labs/user/model/User.kt b/app/src/main/java/com/example/mobile_labs/user/model/User.kt
new file mode 100644
index 0000000..5db216b
--- /dev/null
+++ b/app/src/main/java/com/example/mobile_labs/user/model/User.kt
@@ -0,0 +1,26 @@
+package com.example.mobile_labs.user.model
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "users")
+data class User(
+ @PrimaryKey(autoGenerate = true)
+ val uid: Int?,
+ val email: String,
+ val password: String,
+ val last_name: String,
+ val first_name: String,
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+ other as User
+ if (uid != other.uid) return false
+ return true
+ }
+
+ override fun hashCode(): Int {
+ return uid ?: -1
+ }
+}
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 9861456..bd1eb8a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,4 +2,5 @@
plugins {
id("com.android.application") version "8.1.1" apply false
id("org.jetbrains.kotlin.android") version "1.8.10" apply false
+ id("com.google.devtools.ksp") version "1.8.20-1.0.11" apply false
}
\ No newline at end of file