Third lab
This commit is contained in:
parent
5a820b661e
commit
16257cf1b6
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.8.10" />
|
||||
<option name="version" value="1.8.20" />
|
||||
</component>
|
||||
</project>
|
@ -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")
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
@ -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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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<EventWithPerformance>() }
|
||||
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,
|
||||
|
@ -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<List<Event>>
|
||||
|
||||
@Query("select * from events where events.date > :dateFrom order by date asc")
|
||||
fun getAllWithPerformance(dateFrom: String): Flow<List<EventWithPerformance>>
|
||||
|
||||
@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)
|
||||
}
|
@ -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<Event> {
|
||||
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])
|
||||
)
|
||||
}
|
@ -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,
|
||||
)
|
@ -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<PerformanceWithPeople?>(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))
|
||||
}
|
||||
|
@ -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<Performance>() }
|
||||
var performancesFiltered = remember { mutableStateListOf<Performance>() }
|
||||
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",
|
||||
|
@ -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<List<Performance>>
|
||||
|
||||
@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)
|
||||
}
|
@ -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<List<PerformancePersonCrossRef>>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(performancePersonCrossRef: PerformancePersonCrossRef)
|
||||
|
||||
@Update
|
||||
suspend fun update(performancePersonCrossRef: PerformancePersonCrossRef)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(performancePersonCrossRef: PerformancePersonCrossRef)
|
||||
}
|
@ -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<Person>,
|
||||
@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
|
||||
|
||||
fun getTestPerformances(): List<Performance> {
|
||||
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"),
|
||||
)
|
||||
) {
|
||||
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
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return performance_uid ?: -1
|
||||
}
|
||||
}
|
@ -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,
|
||||
)
|
@ -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<Person>
|
||||
)
|
@ -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<Person>() }
|
||||
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)) {
|
||||
|
@ -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<List<Person>>
|
||||
|
||||
@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)
|
||||
}
|
@ -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
|
||||
|
||||
fun getTestPerson(): List<Person> {
|
||||
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 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
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return uid ?: -1
|
||||
}
|
||||
}
|
@ -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<List<User>>
|
||||
|
||||
@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)
|
||||
}
|
26
app/src/main/java/com/example/mobile_labs/user/model/User.kt
Normal file
26
app/src/main/java/com/example/mobile_labs/user/model/User.kt
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user