3 lab
This commit is contained in:
parent
895ee0fe2b
commit
02a36d1a92
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="KotlinJpsPluginSettings">
|
<component name="KotlinJpsPluginSettings">
|
||||||
<option name="version" value="1.8.10" />
|
<option name="version" value="1.8.20" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("org.jetbrains.kotlin.android")
|
id("org.jetbrains.kotlin.android")
|
||||||
|
id("com.google.devtools.ksp")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -27,17 +28,17 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "17"
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
}
|
}
|
||||||
composeOptions {
|
composeOptions {
|
||||||
kotlinCompilerExtensionVersion = "1.4.3"
|
kotlinCompilerExtensionVersion = "1.4.5"
|
||||||
}
|
}
|
||||||
packaging {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
@ -57,6 +58,14 @@ dependencies {
|
|||||||
implementation("androidx.compose.ui:ui-graphics")
|
implementation("androidx.compose.ui:ui-graphics")
|
||||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||||
implementation("androidx.compose.material3:material3")
|
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")
|
testImplementation("junit:junit:4.13.2")
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||||
|
@ -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<Book> {
|
|
||||||
return listOf(
|
|
||||||
Book("1984", "Дж. Оруэлл", "Был холодный ясный апрельский день, и часы пробили тринадцать."),
|
|
||||||
Book("Собачье сердце", "М.А. Булгаков", "У‑у-у-у-у-гу-гуг-гуу! О, гляньте на меня, я погибаю."),
|
|
||||||
Book("Вельд", "Р. Брэдбери", "— Джорджи, пожалуйста, посмотри детскую комнату. — А что с ней?")
|
|
||||||
)
|
|
||||||
}
|
|
@ -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<BookWithAuthor?>(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<Book>() }
|
||||||
|
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, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,49 +2,76 @@ package com.example.myapplication.composeui
|
|||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
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.R
|
||||||
import com.example.myapplication.book.model.getBooks
|
import com.example.myapplication.composeui.navigation.Screen
|
||||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun BookView(id: Int) {
|
fun BookView(navController: NavController?, id: Int) {
|
||||||
val book = getBooks()[id]
|
val context = LocalContext.current
|
||||||
|
val (bookWithAuthor, setBookWithAuthor) = remember { mutableStateOf<BookWithAuthor?>(null) }
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
setBookWithAuthor(AppDatabase.getInstance(context).bookDao().getByUid(id))
|
||||||
|
}
|
||||||
|
}
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(all = 10.dp)
|
.padding(all = 10.dp)
|
||||||
) {
|
) {
|
||||||
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
value = book.title, onValueChange = {}, readOnly = true,
|
value = bookWithAuthor?.book?.title ?: "", onValueChange = {}, readOnly = true,
|
||||||
label = {
|
label = {
|
||||||
Text(stringResource(id = R.string.book_title))
|
Text(stringResource(id = R.string.book_title))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
value = book.author, onValueChange = {}, readOnly = true,
|
value = bookWithAuthor?.authorName ?: "", onValueChange = {}, readOnly = true,
|
||||||
label = {
|
label = {
|
||||||
Text(stringResource(id = R.string.author_name))
|
Text(stringResource(id = R.string.author_name))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
value = book.content, onValueChange = {}, readOnly = true,
|
value = bookWithAuthor?.book?.description ?: "", onValueChange = {}, readOnly = true,
|
||||||
label = {
|
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(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.background
|
color = MaterialTheme.colorScheme.background
|
||||||
) {
|
) {
|
||||||
BookView(id = 0)
|
BookView(navController = null, id = 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,35 +5,68 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
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.Button
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
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.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.navigation.NavController
|
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.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.composeui.navigation.Screen
|
||||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Catalog(navController: NavController?) {
|
fun Catalog(navController: NavController?) {
|
||||||
Column(Modifier.padding(all = 10.dp)) {
|
val context = LocalContext.current
|
||||||
getBooks().forEachIndexed() { index, book ->
|
val books = remember { mutableStateListOf<Book>() }
|
||||||
val bookId = Screen.BookView.route.replace("{id}", index.toString())
|
LaunchedEffect(Unit) {
|
||||||
Button(
|
withContext(Dispatchers.IO) {
|
||||||
modifier = Modifier
|
AppDatabase.getInstance(context).bookDao().getAll().collect { data ->
|
||||||
.fillMaxWidth()
|
books.clear()
|
||||||
.padding(all = 10.dp),
|
books.addAll(data)
|
||||||
onClick = { navController?.navigate(bookId) }) {
|
|
||||||
Text("${book.title}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
@ -12,6 +12,7 @@ import androidx.compose.material3.OutlinedTextField
|
|||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
@ -20,30 +21,57 @@ import androidx.navigation.NavController
|
|||||||
import com.example.myapplication.R
|
import com.example.myapplication.R
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
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.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 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)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Enter(navController: NavController?) {
|
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)) {
|
Column(Modifier.fillMaxWidth().padding(all = 40.dp)) {
|
||||||
val loginStr = remember{mutableStateOf("")}
|
|
||||||
Text(stringResource(id = R.string.login))
|
Text(stringResource(id = R.string.login))
|
||||||
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
value = loginStr.value, onValueChange = { newText -> loginStr.value = newText },
|
value = login, onValueChange = { login = it },
|
||||||
)
|
)
|
||||||
Spacer(Modifier.padding(bottom = 10.dp))
|
Spacer(Modifier.padding(bottom = 10.dp))
|
||||||
val passwordStr = remember{mutableStateOf("")}
|
|
||||||
Text(stringResource(id = R.string.password))
|
Text(stringResource(id = R.string.password))
|
||||||
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
||||||
value = passwordStr.value, onValueChange = { newText -> passwordStr.value = newText },
|
value = password, onValueChange = { password = it },
|
||||||
)
|
)
|
||||||
Spacer(Modifier.padding(bottom = 20.dp))
|
Spacer(Modifier.padding(bottom = 20.dp))
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(all = 10.dp),
|
.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))
|
Text(stringResource(id = R.string.enter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<Author>() }
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,255 @@
|
|||||||
package com.example.myapplication.composeui
|
package com.example.myapplication.composeui
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.layout.Column
|
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.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.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
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.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
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.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
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.R
|
||||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Profile() {
|
fun Profile(navController: NavController?) {
|
||||||
Column(Modifier.padding(all = 40.dp)) {
|
val openDialogEdit = remember { mutableStateOf(false) }
|
||||||
Text(stringResource(id = R.string.stats))
|
val openDialogExit = remember { mutableStateOf(false) }
|
||||||
|
val openDialogDelete = remember { mutableStateOf(false) }
|
||||||
|
val context = LocalContext.current
|
||||||
|
val user = remember { mutableStateOf<User>(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 = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
@Composable
|
@Composable
|
||||||
@ -29,7 +258,7 @@ fun ProfilePreview() {
|
|||||||
Surface(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.background
|
color = MaterialTheme.colorScheme.background
|
||||||
) {
|
) {
|
||||||
Profile()
|
Profile(navController = null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,10 +10,13 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
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.unit.dp
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.colorResource
|
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.R
|
||||||
import com.example.myapplication.ui.theme.MyApplicationTheme
|
import com.example.myapplication.ui.theme.MyApplicationTheme
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun Search() {
|
fun Search(navController: NavController?) {
|
||||||
|
var searchStr by remember { mutableStateOf("") }
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -37,16 +44,25 @@ fun Search() {
|
|||||||
Text(stringResource(id = R.string.book_world), color = Color.White)
|
Text(stringResource(id = R.string.book_world), color = Color.White)
|
||||||
}
|
}
|
||||||
Spacer(Modifier.padding(bottom = 20.dp))
|
Spacer(Modifier.padding(bottom = 20.dp))
|
||||||
val searchStr = remember{ mutableStateOf("") }
|
TextField(modifier = Modifier.fillMaxWidth(),
|
||||||
OutlinedTextField(modifier = Modifier.fillMaxWidth(),
|
value = searchStr, onValueChange = { searchStr = it }, singleLine = true,
|
||||||
value = searchStr.value, onValueChange = { newText -> searchStr.value = newText },
|
placeholder = { Text("Поиск", fontSize = 22.sp) }
|
||||||
)
|
)
|
||||||
Spacer(Modifier.padding(bottom = 10.dp))
|
Spacer(Modifier.padding(bottom = 10.dp))
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(all = 10.dp),
|
.padding(all = 10.dp),
|
||||||
onClick = {}) {
|
onClick = {
|
||||||
|
if(!searchStr.isEmpty()){
|
||||||
|
navController?.navigate(
|
||||||
|
Screen.BookSearch.route.replace(
|
||||||
|
"{text}",
|
||||||
|
searchStr
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
Text(stringResource(id = R.string.search_book))
|
Text(stringResource(id = R.string.search_book))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +76,7 @@ fun SearchPreview() {
|
|||||||
Surface(
|
Surface(
|
||||||
color = MaterialTheme.colorScheme.background
|
color = MaterialTheme.colorScheme.background
|
||||||
) {
|
) {
|
||||||
Search()
|
Search(navController=null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -41,6 +41,9 @@ import com.example.myapplication.composeui.Search
|
|||||||
import com.example.myapplication.composeui.Loader
|
import com.example.myapplication.composeui.Loader
|
||||||
import com.example.myapplication.composeui.Catalog
|
import com.example.myapplication.composeui.Catalog
|
||||||
import com.example.myapplication.composeui.BookView
|
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)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -113,15 +116,28 @@ fun Navhost(
|
|||||||
composable(Screen.Main.route) { Main(navController) }
|
composable(Screen.Main.route) { Main(navController) }
|
||||||
composable(Screen.Registration.route) { Registration(navController) }
|
composable(Screen.Registration.route) { Registration(navController) }
|
||||||
composable(Screen.Enter.route) { Enter(navController) }
|
composable(Screen.Enter.route) { Enter(navController) }
|
||||||
composable(Screen.Profile.route) { Profile() }
|
composable(Screen.Profile.route) { Profile(navController) }
|
||||||
composable(Screen.Search.route) { Search() }
|
composable(Screen.Search.route) { Search(navController) }
|
||||||
composable(Screen.Loader.route) { Loader() }
|
composable(Screen.Loader.route) { Loader() }
|
||||||
composable(Screen.Catalog.route) { Catalog(navController) }
|
composable(Screen.Catalog.route) { Catalog(navController) }
|
||||||
|
composable(Screen.ListAuthors.route) { ListAuthors() }
|
||||||
composable(
|
composable(
|
||||||
Screen.BookView.route,
|
Screen.BookView.route,
|
||||||
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
arguments = listOf(navArgument("id") { type = NavType.IntType })
|
||||||
) { backStackEntry ->
|
) { 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", "")) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.example.myapplication.composeui.navigation
|
|||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.AccountCircle
|
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.Favorite
|
||||||
import androidx.compose.material.icons.filled.List
|
import androidx.compose.material.icons.filled.List
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
@ -33,11 +34,20 @@ enum class Screen(
|
|||||||
Catalog(
|
Catalog(
|
||||||
"catalog", R.string.catalog, Icons.Filled.List
|
"catalog", R.string.catalog, Icons.Filled.List
|
||||||
),
|
),
|
||||||
|
ListAuthors(
|
||||||
|
"listauthors", R.string.listauthors, Icons.Filled.Face
|
||||||
|
),
|
||||||
Loader(
|
Loader(
|
||||||
"loader", R.string.loader, showInBottomBar = false
|
"loader", R.string.loader, showInBottomBar = false
|
||||||
),
|
),
|
||||||
|
BookSearch(
|
||||||
|
"book-search/{text}", R.string.search, showInBottomBar = false
|
||||||
|
),
|
||||||
BookView(
|
BookView(
|
||||||
"book-view/{id}", R.string.book_view_title, showInBottomBar = false
|
"book-view/{id}", R.string.book_view_title, showInBottomBar = false
|
||||||
|
),
|
||||||
|
BookRead(
|
||||||
|
"book-read/{id}", R.string.book_view_title, showInBottomBar = false
|
||||||
);
|
);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -45,6 +55,7 @@ enum class Screen(
|
|||||||
Profile,
|
Profile,
|
||||||
Search,
|
Search,
|
||||||
Catalog,
|
Catalog,
|
||||||
|
ListAuthors
|
||||||
)
|
)
|
||||||
fun getItem(route: String): Screen? {
|
fun getItem(route: String): Screen? {
|
||||||
val findRoute = route.split("/").first()
|
val findRoute = route.split("/").first()
|
||||||
|
@ -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<List<Author>>
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
suspend fun insert(author: Author)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(author: Author)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(author: Author)
|
||||||
|
}
|
@ -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<List<Book>>
|
||||||
|
|
||||||
|
@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<List<Book>>
|
||||||
|
|
||||||
|
@Query("select * from books where books.user_id = :userId")
|
||||||
|
fun getByUserId(userId: Int): Flow<List<Book>>
|
||||||
|
|
||||||
|
@Query("select * from books where books.author_id = :authorId")
|
||||||
|
fun getByAuthorId(authorId: Int): Flow<List<Book>>
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
suspend fun insert(book: Book)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(book: Book)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(book: Book)
|
||||||
|
}
|
@ -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<List<User>>
|
||||||
|
|
||||||
|
@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)
|
||||||
|
}
|
@ -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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
65
app/src/main/java/com/example/myapplication/db/model/Book.kt
Normal file
65
app/src/main/java/com/example/myapplication/db/model/Book.kt
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
)
|
41
app/src/main/java/com/example/myapplication/db/model/User.kt
Normal file
41
app/src/main/java/com/example/myapplication/db/model/User.kt
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
BIN
app/src/main/res/drawable/dogsheart.jpg
Normal file
BIN
app/src/main/res/drawable/dogsheart.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
app/src/main/res/drawable/eggs.jpg
Normal file
BIN
app/src/main/res/drawable/eggs.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
app/src/main/res/drawable/or1984.jpg
Normal file
BIN
app/src/main/res/drawable/or1984.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
app/src/main/res/drawable/veld.jpg
Normal file
BIN
app/src/main/res/drawable/veld.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.0 KiB |
@ -9,6 +9,7 @@
|
|||||||
<string name="search">Поиск</string>
|
<string name="search">Поиск</string>
|
||||||
<string name="loader">Загрузка</string>
|
<string name="loader">Загрузка</string>
|
||||||
<string name="catalog">Каталог</string>
|
<string name="catalog">Каталог</string>
|
||||||
|
<string name="listauthors">Писатели</string>
|
||||||
<string name="book_view_title">Книга</string>
|
<string name="book_view_title">Книга</string>
|
||||||
<string name="enter">Войти</string>
|
<string name="enter">Войти</string>
|
||||||
<string name="create_acc">Создать аккаунт</string>
|
<string name="create_acc">Создать аккаунт</string>
|
||||||
@ -27,11 +28,13 @@
|
|||||||
</string>
|
</string>
|
||||||
<string name="book_title">Название</string>
|
<string name="book_title">Название</string>
|
||||||
<string name="author_name">Автор</string>
|
<string name="author_name">Автор</string>
|
||||||
|
<string name="description">Содержание</string>
|
||||||
<string name="all_content">Содержание</string>
|
<string name="all_content">Содержание</string>
|
||||||
<string name="welcome">Добро пожаловать</string>
|
<string name="welcome">Добро пожаловать</string>
|
||||||
<string name="book_world">в мир книг!</string>
|
<string name="book_world">в мир книг!</string>
|
||||||
<string name="search_book">Найти</string>
|
<string name="search_book">Найти</string>
|
||||||
<string name="load_book">Загрузить</string>
|
<string name="load_book">Загрузить</string>
|
||||||
<string name="add_book">Добавить</string>
|
<string name="add_book">Добавить</string>
|
||||||
|
<string name="read_book">Читать</string>
|
||||||
<string name="help_me_pls">Вы можете помочь нашей библиотеке, загрузив свою книгу.</string>
|
<string name="help_me_pls">Вы можете помочь нашей библиотеке, загрузив свою книгу.</string>
|
||||||
</resources>
|
</resources>
|
@ -1,5 +1,6 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.1.1" apply false
|
id("com.android.application") version "8.1.2" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "1.8.10" 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
|
||||||
}
|
}
|
BIN
Отчеты и макеты/Тюрнер_ЛР3.docx
Normal file
BIN
Отчеты и макеты/Тюрнер_ЛР3.docx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user