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 5b9e049..934b019 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 {
@@ -27,17 +28,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 {
@@ -57,6 +58,14 @@ dependencies {
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
+
+ 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")
+
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/myapplication/book/model/Book.kt b/app/src/main/java/com/example/myapplication/book/model/Book.kt
deleted file mode 100644
index 26677a3..0000000
--- a/app/src/main/java/com/example/myapplication/book/model/Book.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.example.myapplication.book.model
-
-import java.io.Serializable
-import com.example.myapplication.R
-
-data class Book(
- val title: String,
- val author: String,
- val content: String
-) : Serializable
-
-fun getBooks(): List {
- return listOf(
- Book("1984", "Дж. Оруэлл", "Был холодный ясный апрельский день, и часы пробили тринадцать."),
- Book("Собачье сердце", "М.А. Булгаков", "У‑у-у-у-у-гу-гуг-гуу! О, гляньте на меня, я погибаю."),
- Book("Вельд", "Р. Брэдбери", "— Джорджи, пожалуйста, посмотри детскую комнату. — А что с ней?")
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/composeui/BookRead.kt b/app/src/main/java/com/example/myapplication/composeui/BookRead.kt
new file mode 100644
index 0000000..4e88681
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/composeui/BookRead.kt
@@ -0,0 +1,55 @@
+package com.example.myapplication.composeui
+
+import android.content.res.Configuration
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.unit.dp
+import androidx.compose.material3.Text
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
+import com.example.myapplication.db.database.AppDatabase
+import com.example.myapplication.db.model.BookWithAuthor
+import com.example.myapplication.ui.theme.MyApplicationTheme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+@Composable
+fun BookRead(id: Int) {
+ val context = LocalContext.current
+ val (bookWithAuthor, setBookWithAuthor) = remember { mutableStateOf(null) }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ setBookWithAuthor(AppDatabase.getInstance(context).bookDao().getByUid(id))
+ }
+ }
+ Column(
+ Modifier
+ .fillMaxWidth()
+ .padding(all = 10.dp)
+ ){
+ Text(text = bookWithAuthor?.book?.content ?: "", fontSize=22.sp)
+ }
+}
+
+@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
+@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+fun BookReadPreview() {
+ MyApplicationTheme {
+ Surface(
+ color = MaterialTheme.colorScheme.background
+ ) {
+ BookRead(id = 0)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/composeui/BookSearch.kt b/app/src/main/java/com/example/myapplication/composeui/BookSearch.kt
new file mode 100644
index 0000000..17dcf1b
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/composeui/BookSearch.kt
@@ -0,0 +1,91 @@
+package com.example.myapplication.composeui
+
+import android.content.res.Configuration
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.items
+import androidx.compose.material3.Button
+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.key
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.navigation.NavController
+import com.example.myapplication.R
+import com.example.myapplication.composeui.navigation.Screen
+import com.example.myapplication.db.database.AppDatabase
+import com.example.myapplication.db.model.Book
+import com.example.myapplication.ui.theme.MyApplicationTheme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+@Composable
+fun BookSearch(navController: NavController?, text: String) {
+ val context = LocalContext.current
+ val books = remember { mutableStateListOf() }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ AppDatabase.getInstance(context).bookDao().getBySearch(text).collect { data ->
+ books.clear()
+ books.addAll(data)
+ }
+ }
+ }
+ Column(Modifier.padding(all = 10.dp)) {
+ LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 180.dp)) {
+ items (books){ book ->
+ key(book.uid) {
+ val bookId = Screen.BookView.route.replace("{id}", book.uid.toString())
+ Image(
+ painter = painterResource(id = book.cover!!),
+ contentDescription = book.title,
+ modifier = Modifier
+ .height(300.dp)
+ .padding(horizontal = 5.dp)
+ .clickable(
+ enabled = true,
+ onClick = { navController?.navigate(bookId) }
+ )
+ )
+ }
+ }
+ }
+ Spacer(Modifier.padding(bottom = 10.dp))
+ Button(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(all = 10.dp),
+ onClick = { navController?.navigate(Screen.Loader.route) }) {
+ Text(stringResource(id = R.string.add_book))
+ }
+ }
+}
+
+@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
+@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+fun BookSearchPreview() {
+ MyApplicationTheme {
+ Surface(
+ color = MaterialTheme.colorScheme.background
+ ) {
+ BookSearch(navController = null, "")
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/composeui/BookView.kt b/app/src/main/java/com/example/myapplication/composeui/BookView.kt
index 1d68c84..450d194 100644
--- a/app/src/main/java/com/example/myapplication/composeui/BookView.kt
+++ b/app/src/main/java/com/example/myapplication/composeui/BookView.kt
@@ -2,49 +2,76 @@ package com.example.myapplication.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
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.key
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.platform.LocalContext
+import androidx.navigation.NavController
+import androidx.navigation.compose.rememberNavController
+import kotlinx.coroutines.withContext
+import kotlinx.coroutines.Dispatchers
+import com.example.myapplication.db.database.AppDatabase;
+import com.example.myapplication.db.model.BookWithAuthor;
import com.example.myapplication.R
-import com.example.myapplication.book.model.getBooks
+import com.example.myapplication.composeui.navigation.Screen
import com.example.myapplication.ui.theme.MyApplicationTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun BookView(id: Int) {
- val book = getBooks()[id]
+fun BookView(navController: NavController?, id: Int) {
+ val context = LocalContext.current
+ val (bookWithAuthor, setBookWithAuthor) = remember { mutableStateOf(null) }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ setBookWithAuthor(AppDatabase.getInstance(context).bookDao().getByUid(id))
+ }
+ }
Column(
Modifier
.fillMaxWidth()
.padding(all = 10.dp)
) {
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
- value = book.title, onValueChange = {}, readOnly = true,
+ value = bookWithAuthor?.book?.title ?: "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.book_title))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
- value = book.author, onValueChange = {}, readOnly = true,
+ value = bookWithAuthor?.authorName ?: "", onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.author_name))
}
)
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
- value = book.content, onValueChange = {}, readOnly = true,
+ value = bookWithAuthor?.book?.description ?: "", onValueChange = {}, readOnly = true,
label = {
- Text(stringResource(id = R.string.all_content))
+ Text(stringResource(id = R.string.description))
}
)
+ Spacer(Modifier.padding(bottom = 10.dp))
+ Button(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(all = 10.dp),
+ onClick = { navController?.navigate(Screen.BookRead.route.replace("{id}", id.toString())) }) {
+ Text(stringResource(id = R.string.read_book))
+ }
}
}
@@ -56,7 +83,7 @@ fun BookViewPreview() {
Surface(
color = MaterialTheme.colorScheme.background
) {
- BookView(id = 0)
+ BookView(navController = null, id = 0)
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/composeui/Catalog.kt b/app/src/main/java/com/example/myapplication/composeui/Catalog.kt
index 51ceee0..ba6c9d6 100644
--- a/app/src/main/java/com/example/myapplication/composeui/Catalog.kt
+++ b/app/src/main/java/com/example/myapplication/composeui/Catalog.kt
@@ -5,35 +5,68 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.height
+import androidx.compose.ui.res.painterResource
import androidx.compose.material3.Button
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.key
+import androidx.compose.runtime.mutableStateListOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.compose.runtime.remember
import androidx.navigation.NavController
+import kotlinx.coroutines.Dispatchers
+import androidx.compose.ui.platform.LocalContext
+import kotlinx.coroutines.withContext
+import com.example.myapplication.db.database.AppDatabase;
+import com.example.myapplication.db.model.Book;
import com.example.myapplication.R
-import com.example.myapplication.book.model.getBooks
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.items
import com.example.myapplication.composeui.navigation.Screen
import com.example.myapplication.ui.theme.MyApplicationTheme
@Composable
fun Catalog(navController: NavController?) {
- Column(Modifier.padding(all = 10.dp)) {
- getBooks().forEachIndexed() { index, book ->
- val bookId = Screen.BookView.route.replace("{id}", index.toString())
- Button(
- modifier = Modifier
- .fillMaxWidth()
- .padding(all = 10.dp),
- onClick = { navController?.navigate(bookId) }) {
- Text("${book.title}")
+ val context = LocalContext.current
+ val books = remember { mutableStateListOf() }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ AppDatabase.getInstance(context).bookDao().getAll().collect { data ->
+ books.clear()
+ books.addAll(data)
}
}
- Spacer(Modifier.padding(bottom = 40.dp))
+ }
+ Column(Modifier.padding(all = 10.dp)) {
+ LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 180.dp)) {
+ items (books){ book ->
+ key(book.uid) {
+ val bookId = Screen.BookView.route.replace("{id}", book.uid.toString())
+ Image(
+ painter = painterResource(id = book.cover!!),
+ contentDescription = book.title,
+ modifier = Modifier
+ .height(300.dp)
+ .padding(horizontal = 5.dp)
+ .clickable(
+ enabled = true,
+ onClick = { navController?.navigate(bookId) }
+ )
+ )
+ }
+ }
+ }
+ Spacer(Modifier.padding(bottom = 10.dp))
Button(
modifier = Modifier
.fillMaxWidth()
diff --git a/app/src/main/java/com/example/myapplication/composeui/Enter.kt b/app/src/main/java/com/example/myapplication/composeui/Enter.kt
index 81c2ad4..83ee5fb 100644
--- a/app/src/main/java/com/example/myapplication/composeui/Enter.kt
+++ b/app/src/main/java/com/example/myapplication/composeui/Enter.kt
@@ -12,6 +12,7 @@ import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@@ -20,30 +21,57 @@ import androidx.navigation.NavController
import com.example.myapplication.R
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.platform.LocalContext
import com.example.myapplication.composeui.navigation.Screen
+import com.example.myapplication.db.database.AppDatabase
+import com.example.myapplication.db.model.User
import com.example.myapplication.ui.theme.MyApplicationTheme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.GlobalScope
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Enter(navController: NavController?) {
+ var login by remember{mutableStateOf("")}
+ var password by remember{mutableStateOf("")}
+ val context = LocalContext.current
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ AppDatabase.getInstance(context).userDao().getAll()
+ }
+ }
Column(Modifier.fillMaxWidth().padding(all = 40.dp)) {
- val loginStr = remember{mutableStateOf("")}
Text(stringResource(id = R.string.login))
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
- value = loginStr.value, onValueChange = { newText -> loginStr.value = newText },
+ value = login, onValueChange = { login = it },
)
Spacer(Modifier.padding(bottom = 10.dp))
- val passwordStr = remember{mutableStateOf("")}
Text(stringResource(id = R.string.password))
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
- value = passwordStr.value, onValueChange = { newText -> passwordStr.value = newText },
+ value = password, onValueChange = { password = it },
)
Spacer(Modifier.padding(bottom = 20.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
- onClick = { navController?.navigate(Screen.Profile.route) }) {
+ onClick = {
+ var user: User?
+ GlobalScope.launch (Dispatchers.Main) {
+ user = AppDatabase.getInstance(context).userDao().tryLogin(login, password)
+ if (user != null) {
+ //AppDatabase.getInstance(context).userDao().setLogined(user!!.uid!!)
+ navController?.navigate(Screen.Profile.route)
+ } else {
+ password = ""
+ login = "Неверный логин или пароль"
+ }
+ }
+ }) {
Text(stringResource(id = R.string.enter))
}
}
diff --git a/app/src/main/java/com/example/myapplication/composeui/ListAuthors.kt b/app/src/main/java/com/example/myapplication/composeui/ListAuthors.kt
new file mode 100644
index 0000000..7565706
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/composeui/ListAuthors.kt
@@ -0,0 +1,69 @@
+package com.example.myapplication.composeui
+
+import android.content.res.Configuration
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Button
+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.key
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.example.myapplication.R
+import com.example.myapplication.composeui.navigation.Screen
+import com.example.myapplication.db.database.AppDatabase
+import com.example.myapplication.db.model.Author
+import com.example.myapplication.ui.theme.MyApplicationTheme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+@Composable
+fun ListAuthors() {
+ val context = LocalContext.current
+ val authors = remember { mutableStateListOf() }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ AppDatabase.getInstance(context).authorDao().getAll().collect { data ->
+ authors.clear()
+ authors.addAll(data)
+ }
+ }
+ }
+ Column(Modifier.padding(all = 10.dp)) {
+ authors.forEach{ author ->
+ Text(author.name, fontSize = 20.sp)
+ }
+ Spacer(Modifier.padding(bottom = 10.dp))
+ Button(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(all = 10.dp),
+ onClick = {}) {
+ Text(stringResource(id = R.string.add_book))
+ }
+ }
+}
+
+@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
+@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+fun ListAuthorsPreview() {
+ MyApplicationTheme {
+ Surface(
+ color = MaterialTheme.colorScheme.background
+ ) {
+ ListAuthors()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/composeui/Profile.kt b/app/src/main/java/com/example/myapplication/composeui/Profile.kt
index 3b1f6be..9b62b53 100644
--- a/app/src/main/java/com/example/myapplication/composeui/Profile.kt
+++ b/app/src/main/java/com/example/myapplication/composeui/Profile.kt
@@ -1,26 +1,255 @@
package com.example.myapplication.composeui
import android.content.res.Configuration
+import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material.icons.filled.Create
+import androidx.compose.material.icons.filled.Edit
+import androidx.compose.material.icons.outlined.Clear
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+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.res.stringResource
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.navigation.NavController
+import com.example.myapplication.composeui.navigation.Screen
+import com.example.myapplication.db.database.AppDatabase
+import com.example.myapplication.db.model.User
import com.example.myapplication.R
import com.example.myapplication.ui.theme.MyApplicationTheme
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun Profile() {
- Column(Modifier.padding(all = 40.dp)) {
- Text(stringResource(id = R.string.stats))
+fun Profile(navController: NavController?) {
+ val openDialogEdit = remember { mutableStateOf(false) }
+ val openDialogExit = remember { mutableStateOf(false) }
+ val openDialogDelete = remember { mutableStateOf(false) }
+ val context = LocalContext.current
+ val user = remember { mutableStateOf(User("", "", "", "USER")) }
+ val userOldPsswd = remember { mutableStateOf("") }
+ val userNewPsswd = remember { mutableStateOf("") }
+ val userNewPsswdConf = remember { mutableStateOf("") }
+ LaunchedEffect(Unit) {
+ withContext(Dispatchers.IO) {
+ user.value = AppDatabase.getInstance(context).userDao().getByUid(2)
+ }
+ }
+ Column(Modifier.padding(all = 10.dp), horizontalAlignment = Alignment.CenterHorizontally) {
+ OutlinedTextField(modifier = Modifier.fillMaxWidth(),
+ value = user.value.login, onValueChange = {user.value.login = it},
+ label = {
+ Text(stringResource(id = R.string.login))
+ },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
+ )
+ OutlinedTextField(modifier = Modifier.fillMaxWidth(),
+ value = user.value.password, onValueChange = {user.value.password = it},
+ label = {
+ Text(stringResource(id = R.string.password))
+ },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
+ )
+ OutlinedTextField(modifier = Modifier.fillMaxWidth(),
+ value = user.value.email, onValueChange = {user.value.email = it},
+ label = {
+ Text(stringResource(id = R.string.email))
+ },
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
+ )
+ Spacer(modifier = Modifier.padding(all = 20.dp))
+ Button(
+ onClick = { openDialogEdit.value = true },
+ shape = CircleShape,
+ modifier = Modifier.fillMaxWidth(fraction = 0.75f),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = MaterialTheme.colorScheme.primaryContainer,
+ contentColor = MaterialTheme.colorScheme.primary
+ )
+ ) {
+ // Inner content including an icon and a text label
+ Icon(
+ imageVector = Icons.Default.Create,
+ contentDescription = "Favorite",
+ modifier = Modifier.size(20.dp)
+ )
+ Spacer(Modifier.size(ButtonDefaults.IconSpacing))
+ Text(text = "Редактировать")
+ }
+ Button(
+ onClick = { openDialogExit.value = true },
+ shape = CircleShape,
+ modifier = Modifier.fillMaxWidth(fraction = 0.75f),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = MaterialTheme.colorScheme.errorContainer,
+ contentColor = MaterialTheme.colorScheme.error
+ )
+ ) {
+ // Inner content including an icon and a text label
+ Icon(
+ imageVector = Icons.Default.Close,
+ contentDescription = "Favorite",
+ modifier = Modifier.size(20.dp)
+ )
+ Spacer(Modifier.size(ButtonDefaults.IconSpacing))
+ Text(text = "Выход")
+ }
+ OutlinedButton(
+ onClick = { openDialogDelete.value = true },
+ shape = CircleShape,
+ modifier = Modifier.fillMaxWidth(fraction = 0.75f),
+ border= BorderStroke(1.dp, MaterialTheme.colorScheme.error),
+ colors = ButtonDefaults.buttonColors(
+ containerColor = Color.Transparent,
+ contentColor = MaterialTheme.colorScheme.error
+ )
+ ) {
+ // Inner content including an icon and a text label
+ Icon(
+ imageVector = Icons.Outlined.Clear,
+ contentDescription = "Удалить",
+ modifier = Modifier.size(20.dp)
+ )
+ Spacer(Modifier.size(ButtonDefaults.IconSpacing))
+ Text(text = "Удалить аккаунт")
+ }
+ }
+ if (openDialogEdit.value) {
+ AlertDialog(
+ icon = {
+ Icon(Icons.Default.Edit, contentDescription = "Example Icon")
+ },
+ title = {
+ Text(text = "Подтверждение")
+ },
+ text = {
+ Text(text = "Вы хотите применить изменения?")
+ },
+ onDismissRequest = {
+ openDialogEdit.value = false
+ },
+ confirmButton = {
+ TextButton(
+ onClick = {
+ openDialogEdit.value = false
+ /* TODO */
+ }
+ ) {
+ Text("Да")
+ }
+ },
+ dismissButton = {
+ TextButton(
+ onClick = {
+ openDialogEdit.value = false
+ }
+ ) {
+ Text("Нет")
+ }
+ }
+ )
+ }
+ if (openDialogExit.value) {
+ AlertDialog(
+ icon = {
+ Icon(Icons.Default.Close, contentDescription = "Example Icon")
+ },
+ title = {
+ Text(text = "Подтверждение")
+ },
+ text = {
+ Text(text = "Вы хотите выйти из аккаунта?")
+ },
+ onDismissRequest = {
+ openDialogExit.value = false
+ },
+ confirmButton = {
+ TextButton(
+ onClick = {
+ openDialogExit.value = false
+ navController?.navigate(Screen.Enter.route)
+ }
+ ) {
+ Text("Да")
+ }
+ },
+ dismissButton = {
+ TextButton(
+ onClick = {
+ openDialogExit.value = false
+ }
+ ) {
+ Text("Нет")
+ }
+ }
+ )
+ }
+ if (openDialogDelete.value) {
+ AlertDialog(
+ icon = {
+ Icon(Icons.Default.Close, contentDescription = "Example Icon")
+ },
+ title = {
+ Text(text = "Подтверждение")
+ },
+ text = {
+ Text(text = "Вы хотите удалить аккаунт?")
+ },
+ onDismissRequest = {
+ openDialogDelete.value = false
+ },
+ confirmButton = {
+ TextButton(
+ onClick = {
+ openDialogDelete.value = false
+ /* TODO */
+ }
+ ) {
+ Text("Да")
+ }
+ },
+ dismissButton = {
+ TextButton(
+ onClick = {
+ openDialogDelete.value = false
+ }
+ ) {
+ Text("Нет")
+ }
+ }
+ )
}
}
+
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
@@ -29,7 +258,7 @@ fun ProfilePreview() {
Surface(
color = MaterialTheme.colorScheme.background
) {
- Profile()
+ Profile(navController = null)
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/composeui/Search.kt b/app/src/main/java/com/example/myapplication/composeui/Search.kt
index 59b1279..b2e9617 100644
--- a/app/src/main/java/com/example/myapplication/composeui/Search.kt
+++ b/app/src/main/java/com/example/myapplication/composeui/Search.kt
@@ -10,10 +10,13 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
+import androidx.compose.material3.TextField
+import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
@@ -22,12 +25,16 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
+import com.example.myapplication.composeui.navigation.Screen
import com.example.myapplication.R
import com.example.myapplication.ui.theme.MyApplicationTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun Search() {
+fun Search(navController: NavController?) {
+ var searchStr by remember { mutableStateOf("") }
Column(
Modifier
.fillMaxWidth()
@@ -37,16 +44,25 @@ fun Search() {
Text(stringResource(id = R.string.book_world), color = Color.White)
}
Spacer(Modifier.padding(bottom = 20.dp))
- val searchStr = remember{ mutableStateOf("") }
- OutlinedTextField(modifier = Modifier.fillMaxWidth(),
- value = searchStr.value, onValueChange = { newText -> searchStr.value = newText },
+ TextField(modifier = Modifier.fillMaxWidth(),
+ value = searchStr, onValueChange = { searchStr = it }, singleLine = true,
+ placeholder = { Text("Поиск", fontSize = 22.sp) }
)
Spacer(Modifier.padding(bottom = 10.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp),
- onClick = {}) {
+ onClick = {
+ if(!searchStr.isEmpty()){
+ navController?.navigate(
+ Screen.BookSearch.route.replace(
+ "{text}",
+ searchStr
+ )
+ )
+ }
+ }) {
Text(stringResource(id = R.string.search_book))
}
}
@@ -60,7 +76,7 @@ fun SearchPreview() {
Surface(
color = MaterialTheme.colorScheme.background
) {
- Search()
+ Search(navController=null)
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/composeui/navigation/MainNavbar.kt b/app/src/main/java/com/example/myapplication/composeui/navigation/MainNavbar.kt
index 8904e0d..66c2abf 100644
--- a/app/src/main/java/com/example/myapplication/composeui/navigation/MainNavbar.kt
+++ b/app/src/main/java/com/example/myapplication/composeui/navigation/MainNavbar.kt
@@ -41,6 +41,9 @@ import com.example.myapplication.composeui.Search
import com.example.myapplication.composeui.Loader
import com.example.myapplication.composeui.Catalog
import com.example.myapplication.composeui.BookView
+import com.example.myapplication.composeui.BookRead
+import com.example.myapplication.composeui.BookSearch
+import com.example.myapplication.composeui.ListAuthors
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -113,15 +116,28 @@ fun Navhost(
composable(Screen.Main.route) { Main(navController) }
composable(Screen.Registration.route) { Registration(navController) }
composable(Screen.Enter.route) { Enter(navController) }
- composable(Screen.Profile.route) { Profile() }
- composable(Screen.Search.route) { Search() }
+ composable(Screen.Profile.route) { Profile(navController) }
+ composable(Screen.Search.route) { Search(navController) }
composable(Screen.Loader.route) { Loader() }
composable(Screen.Catalog.route) { Catalog(navController) }
+ composable(Screen.ListAuthors.route) { ListAuthors() }
composable(
Screen.BookView.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
- backStackEntry.arguments?.let { BookView(it.getInt("id")) }
+ backStackEntry.arguments?.let { BookView(navController, it.getInt("id")) }
+ }
+ composable(
+ Screen.BookRead.route,
+ arguments = listOf(navArgument("id") { type = NavType.IntType })
+ ) { backStackEntry ->
+ backStackEntry.arguments?.let { BookRead(it.getInt("id")) }
+ }
+ composable(
+ Screen.BookSearch.route,
+ arguments = listOf(navArgument("text") { type = NavType.StringType })
+ ) { backStackEntry ->
+ backStackEntry.arguments?.let { BookSearch(navController = navController ,it.getString ("text", "")) }
}
}
}
diff --git a/app/src/main/java/com/example/myapplication/composeui/navigation/Screen.kt b/app/src/main/java/com/example/myapplication/composeui/navigation/Screen.kt
index 7b17e95..819dc81 100644
--- a/app/src/main/java/com/example/myapplication/composeui/navigation/Screen.kt
+++ b/app/src/main/java/com/example/myapplication/composeui/navigation/Screen.kt
@@ -3,6 +3,7 @@ package com.example.myapplication.composeui.navigation
import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
+import androidx.compose.material.icons.filled.Face
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.List
import androidx.compose.material.icons.filled.Search
@@ -33,11 +34,20 @@ enum class Screen(
Catalog(
"catalog", R.string.catalog, Icons.Filled.List
),
+ ListAuthors(
+ "listauthors", R.string.listauthors, Icons.Filled.Face
+ ),
Loader(
"loader", R.string.loader, showInBottomBar = false
),
+ BookSearch(
+ "book-search/{text}", R.string.search, showInBottomBar = false
+ ),
BookView(
"book-view/{id}", R.string.book_view_title, showInBottomBar = false
+ ),
+ BookRead(
+ "book-read/{id}", R.string.book_view_title, showInBottomBar = false
);
companion object {
@@ -45,6 +55,7 @@ enum class Screen(
Profile,
Search,
Catalog,
+ ListAuthors
)
fun getItem(route: String): Screen? {
val findRoute = route.split("/").first()
diff --git a/app/src/main/java/com/example/myapplication/db/dao/AuthorDao.kt b/app/src/main/java/com/example/myapplication/db/dao/AuthorDao.kt
new file mode 100644
index 0000000..ec9ef35
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/dao/AuthorDao.kt
@@ -0,0 +1,25 @@
+package com.example.myapplication.db.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import com.example.myapplication.db.model.Author;
+import com.example.myapplication.db.model.Book
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface AuthorDao {
+ @Query("select * from authors order by author_name collate nocase asc")
+ fun getAll(): Flow>
+
+ @Insert
+ suspend fun insert(author: Author)
+
+ @Update
+ suspend fun update(author: Author)
+
+ @Delete
+ suspend fun delete(author: Author)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/db/dao/BookDao.kt b/app/src/main/java/com/example/myapplication/db/dao/BookDao.kt
new file mode 100644
index 0000000..b6eb7d6
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/dao/BookDao.kt
@@ -0,0 +1,37 @@
+package com.example.myapplication.db.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import kotlinx.coroutines.flow.Flow
+import com.example.myapplication.db.model.Book;
+import com.example.myapplication.db.model.BookWithAuthor;
+
+@Dao
+interface BookDao {
+ @Query("select * from books order by title collate nocase asc")
+ fun getAll(): Flow>
+
+ @Query("select * from books left join authors on books.author_id = authors.uid where books.uid = :uid")
+ suspend fun getByUid(uid: Int): BookWithAuthor
+
+ @Query("select * from books where books.title LIKE '%' || :searchStr || '%'")
+ fun getBySearch(searchStr: String): Flow>
+
+ @Query("select * from books where books.user_id = :userId")
+ fun getByUserId(userId: Int): Flow>
+
+ @Query("select * from books where books.author_id = :authorId")
+ fun getByAuthorId(authorId: Int): Flow>
+
+ @Insert
+ suspend fun insert(book: Book)
+
+ @Update
+ suspend fun update(book: Book)
+
+ @Delete
+ suspend fun delete(book: Book)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/db/dao/UserDao.kt b/app/src/main/java/com/example/myapplication/db/dao/UserDao.kt
new file mode 100644
index 0000000..b9eb2b3
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/dao/UserDao.kt
@@ -0,0 +1,30 @@
+package com.example.myapplication.db.dao
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+import kotlinx.coroutines.flow.Flow
+import com.example.myapplication.db.model.User;
+
+@Dao
+interface UserDao {
+ @Query("select * from users")
+ fun getAll(): Flow>
+
+ @Query("select * from users where login = :login and password = :password")
+ suspend fun tryLogin(login: String, password: String): 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)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/db/database/AppDatabase.kt b/app/src/main/java/com/example/myapplication/db/database/AppDatabase.kt
new file mode 100644
index 0000000..1638411
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/database/AppDatabase.kt
@@ -0,0 +1,80 @@
+package com.example.myapplication.db.database
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import androidx.sqlite.db.SupportSQLiteDatabase
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import com.example.myapplication.db.dao.UserDao;
+import com.example.myapplication.db.dao.BookDao;
+import com.example.myapplication.db.dao.AuthorDao;
+import com.example.myapplication.db.model.User;
+import com.example.myapplication.db.model.Book;
+import com.example.myapplication.db.model.Author;
+import com.example.myapplication.R
+
+@Database(entities = [Book::class, Author::class, User::class], version = 1, exportSchema = false)
+abstract class AppDatabase : RoomDatabase() {
+ abstract fun bookDao(): BookDao
+ abstract fun authorDao(): AuthorDao
+ abstract fun userDao(): UserDao
+
+ companion object {
+ private const val DB_NAME: String = "PMU"
+
+ @Volatile
+ private var INSTANCE: AppDatabase? = null
+
+ private suspend fun populateDatabase() {
+ INSTANCE?.let { database ->
+ //Users
+ val userDao = database.userDao()
+ val user1 = User(1, "Admin", "Admin", "admin@mail.ru", "ADMIN")
+ val user2 = User(2, "User1", "123", "u1@mail.ru", "USER")
+ userDao.insert(user1)
+ userDao.insert(user2)
+ // Authors
+ val authorDao = database.authorDao()
+ val author1 = Author(1, "Дж. Оруэлл")
+ val author2 = Author(2, "М.А. Булгаков")
+ val author3 = Author(3, "Р. Брэдбери")
+ authorDao.insert(author1)
+ authorDao.insert(author2)
+ authorDao.insert(author3)
+ // Books
+ val bookDao = database.bookDao()
+ val book1 = Book(1,"1984", "Роман о том, как репрессивная машина тоталитарного государства может уничтожить любую личность.", "Был холодный ясный апрельский день, и часы пробили тринадцать.\n" + "Уинстон Смит, прижав подбородок к груди и ежась от омерзительного ветра, быстро скользнул в стеклянные двери Дома Победы, но все же вихрь песка и пыли успел ворваться вместе с ним.", R.drawable.or1984, 1, 1)
+ val book2 = Book(2,"Собачье сердце", "Роман о бродячем псе Шарике, превращенном в человека.", "У‑у-у-у-у-гу-гуг-гуу! О, гляньте на меня, я погибаю.\n" + "Вьюга в подворотне ревёт мне отходную, и я вою с ней.\n" + "Пропал я, пропал.", R.drawable.dogsheart, 2, 1)
+ val book3 = Book(3,"Вельд", "Рассказ о зависимости от технических устройств, потере человечности.", "— Джорджи, пожалуйста, посмотри детскую комнату.\n" + "— А что с ней?\n" + "— Не знаю.\n" + "— Так в чем же дело?", R.drawable.veld, 3, 1)
+ val book4 = Book(4,"Роковые яйца", "Рассказ, критикующий стремление к прогрессу без учета последствий.","16 апреля 1928 года, вечером, профессор зоологии IV государственного университета и директор зооинститута в Москве Персиков вошел в свой кабинет, помещающийся в зооинституте, что на улице Герцена.\n" + "Профессор зажег верхний матовый шар и огляделся.", R.drawable.eggs, 2, 2)
+ bookDao.insert(book1)
+ bookDao.insert(book2)
+ bookDao.insert(book3)
+ bookDao.insert(book4)
+ }
+ }
+
+ fun getInstance(appContext: Context): AppDatabase {
+ return INSTANCE ?: synchronized(this) {
+ Room.databaseBuilder(
+ appContext,
+ AppDatabase::class.java,
+ DB_NAME
+ )
+ .addCallback(object : 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/myapplication/db/model/Author.kt b/app/src/main/java/com/example/myapplication/db/model/Author.kt
new file mode 100644
index 0000000..39834d2
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/model/Author.kt
@@ -0,0 +1,30 @@
+package com.example.myapplication.db.model
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Ignore
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "authors")
+data class Author(
+ @PrimaryKey(autoGenerate = true)
+ val uid: Int?,
+ @ColumnInfo(name = "author_name")
+ val name: String
+) {
+ @Ignore
+ constructor(
+ name: String
+ ) : this(null, name)
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+ other as Author
+ if (uid != other.uid) return false
+ return true
+ }
+
+ override fun hashCode(): Int {
+ return uid ?: -1
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/db/model/Book.kt b/app/src/main/java/com/example/myapplication/db/model/Book.kt
new file mode 100644
index 0000000..21a871e
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/model/Book.kt
@@ -0,0 +1,65 @@
+package com.example.myapplication.db.model
+
+import androidx.annotation.DrawableRes
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import androidx.room.PrimaryKey
+import androidx.room.Ignore
+
+@Entity(
+ tableName = "books", foreignKeys = [
+ ForeignKey(
+ entity = Author::class,
+ parentColumns = ["uid"],
+ childColumns = ["author_id"],
+ onDelete = ForeignKey.RESTRICT,
+ onUpdate = ForeignKey.RESTRICT
+ ),
+ ForeignKey(
+ entity = User::class,
+ parentColumns = ["uid"],
+ childColumns = ["user_id"],
+ onDelete = ForeignKey.RESTRICT,
+ onUpdate = ForeignKey.RESTRICT
+ )
+ ]
+)
+data class Book(
+ @PrimaryKey(autoGenerate = true)
+ val uid: Int?,
+ @ColumnInfo(name = "title")
+ val title: String,
+ @ColumnInfo(name = "description")
+ val description: String,
+ @ColumnInfo(name = "content")
+ val content: String,
+ @ColumnInfo(name = "cover")
+ @DrawableRes val cover: Int?,
+ @ColumnInfo(name = "author_id", index = true)
+ val authorId: Int?,
+ @ColumnInfo(name = "user_id", index = true)
+ val userId: Int?
+) {
+ @Ignore
+ constructor(
+ title: String,
+ description: String,
+ content: String,
+ cover: Int?,
+ authorId: Int?,
+ userId: Int?
+ ) : this(null, title, description, content, cover, authorId, userId)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+ other as Book
+ if (uid != other.uid) return false
+ return true
+ }
+
+ override fun hashCode(): Int {
+ return uid ?: -1
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/db/model/BookWithAuthor.kt b/app/src/main/java/com/example/myapplication/db/model/BookWithAuthor.kt
new file mode 100644
index 0000000..1161292
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/model/BookWithAuthor.kt
@@ -0,0 +1,11 @@
+package com.example.myapplication.db.model
+
+import androidx.room.ColumnInfo
+import androidx.room.Embedded
+
+data class BookWithAuthor(
+ @Embedded
+ val book: Book,
+ @ColumnInfo(name = "author_name")
+ val authorName: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/myapplication/db/model/User.kt b/app/src/main/java/com/example/myapplication/db/model/User.kt
new file mode 100644
index 0000000..80eeb89
--- /dev/null
+++ b/app/src/main/java/com/example/myapplication/db/model/User.kt
@@ -0,0 +1,41 @@
+package com.example.myapplication.db.model
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import androidx.room.Ignore
+import androidx.room.Index
+
+@Entity(tableName = "users", indices = [(Index(value = ["login"], unique = true))])
+data class User(
+ @PrimaryKey(autoGenerate = true)
+ val uid: Int?,
+ @ColumnInfo(name = "login")
+ var login: String,
+ @ColumnInfo(name = "password")
+ var password: String,
+ @ColumnInfo(name = "email")
+ var email: String,
+ @ColumnInfo(name = "admin")
+ var role: String,
+) {
+ @Ignore
+ constructor(
+ login: String,
+ password: String,
+ email: String,
+ role: String
+ ) : this(null, login, password, email, role)
+
+ 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/app/src/main/res/drawable/dogsheart.jpg b/app/src/main/res/drawable/dogsheart.jpg
new file mode 100644
index 0000000..c7d7e5f
Binary files /dev/null and b/app/src/main/res/drawable/dogsheart.jpg differ
diff --git a/app/src/main/res/drawable/eggs.jpg b/app/src/main/res/drawable/eggs.jpg
new file mode 100644
index 0000000..ceb8337
Binary files /dev/null and b/app/src/main/res/drawable/eggs.jpg differ
diff --git a/app/src/main/res/drawable/or1984.jpg b/app/src/main/res/drawable/or1984.jpg
new file mode 100644
index 0000000..2e79f19
Binary files /dev/null and b/app/src/main/res/drawable/or1984.jpg differ
diff --git a/app/src/main/res/drawable/veld.jpg b/app/src/main/res/drawable/veld.jpg
new file mode 100644
index 0000000..31824a9
Binary files /dev/null and b/app/src/main/res/drawable/veld.jpg differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index acb01fe..87f6cfa 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -9,6 +9,7 @@
Поиск
Загрузка
Каталог
+ Писатели
Книга
Войти
Создать аккаунт
@@ -27,11 +28,13 @@
Название
Автор
+ Содержание
Содержание
Добро пожаловать
в мир книг!
Найти
Загрузить
Добавить
+ Читать
Вы можете помочь нашей библиотеке, загрузив свою книгу.
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 9861456..3b1b951 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id("com.android.application") version "8.1.1" apply false
- id("org.jetbrains.kotlin.android") version "1.8.10" apply false
+ id("com.android.application") version "8.1.2" apply false
+ id("org.jetbrains.kotlin.android") version "1.8.20" apply false
+ id("com.google.devtools.ksp") version "1.8.20-1.0.11" apply false
}
\ No newline at end of file
diff --git a/Отчеты и макеты/Тюрнер_ЛР3.docx b/Отчеты и макеты/Тюрнер_ЛР3.docx
new file mode 100644
index 0000000..c44848c
Binary files /dev/null and b/Отчеты и макеты/Тюрнер_ЛР3.docx differ