From 7aa7a2ffd924447a0b40269620310f149b5d9683 Mon Sep 17 00:00:00 2001 From: Marat Zargarov Date: Tue, 21 Nov 2023 12:06:54 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/vcs.xml | 1 + app/build.gradle.kts | 5 +- .../main/assets/images/dostoevskiy_besy.jpg | Bin 0 -> 17060 bytes .../com/example/shortbooks/MainActivity.kt | 25 ++-- .../shortbooks/book/composeui/BookList.kt | 109 ++++++++++++++++ .../shortbooks/book/composeui/BookText.kt | 54 ++++++++ .../com/example/shortbooks/book/model/Book.kt | 18 +++ .../favorite/composeui/FavoriteList.kt | 107 ++++++++++++++++ .../favorite/composeui/FavoriteText.kt | 54 ++++++++ .../shortbooks/favorite/model/Favorite.kt | 17 +++ .../shortbooks/navigation/MainNavbar.kt | 121 ++++++++++++++++++ .../example/shortbooks/navigation/Screen.kt | 45 +++++++ .../shortbooks/user/composeui/UserInfo.kt | 71 ++++++++++ .../com/example/shortbooks/user/model/User.kt | 14 ++ app/src/main/res/values/strings.xml | 9 +- 15 files changed, 633 insertions(+), 17 deletions(-) create mode 100644 app/src/main/assets/images/dostoevskiy_besy.jpg create mode 100644 app/src/main/java/com/example/shortbooks/book/composeui/BookList.kt create mode 100644 app/src/main/java/com/example/shortbooks/book/composeui/BookText.kt create mode 100644 app/src/main/java/com/example/shortbooks/book/model/Book.kt create mode 100644 app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteList.kt create mode 100644 app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteText.kt create mode 100644 app/src/main/java/com/example/shortbooks/favorite/model/Favorite.kt create mode 100644 app/src/main/java/com/example/shortbooks/navigation/MainNavbar.kt create mode 100644 app/src/main/java/com/example/shortbooks/navigation/Screen.kt create mode 100644 app/src/main/java/com/example/shortbooks/user/composeui/UserInfo.kt create mode 100644 app/src/main/java/com/example/shortbooks/user/model/User.kt diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..5567a95 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3dea29f..e9f7c18 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,7 +5,7 @@ plugins { android { namespace = "com.example.shortbooks" - compileSdk = 33 + compileSdk = 34 defaultConfig { applicationId = "com.example.shortbooks" @@ -53,8 +53,9 @@ dependencies { implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") - implementation("androidx.activity:activity-compose:1.8.1") + implementation("androidx.activity:activity-compose:1.8.0") implementation(platform("androidx.compose:compose-bom:2023.03.00")) + implementation("androidx.navigation:navigation-compose:2.6.0") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") diff --git a/app/src/main/assets/images/dostoevskiy_besy.jpg b/app/src/main/assets/images/dostoevskiy_besy.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fb0b257135788c6c1383b87d45d8cd7d9b67769d GIT binary patch literal 17060 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 pKSbN + val bookId = Screen.BookText.route.replace("{id}", index.toString()) + Card( + modifier = Modifier + .fillMaxWidth() + .padding(all = 10.dp) + .clickable { navController?.navigate(bookId) }, + shape = RoundedCornerShape(10.dp), + ) { + Box(){ + Row( + verticalAlignment = Alignment.CenterVertically + ){ + ImageConverse(imagePath = book.image) + Column { + Text("${book.name}", fontSize = 22.sp) + Text("${book.author}", fontSize = 18.sp) + } + } + } + } + } + } +} + + +@Composable +fun ImageConverse(imagePath: String) { + val context = LocalContext.current + val assetManager: AssetManager = context.assets + // Открываем поток данных для изображения в каталоге assets + val inputStream = assetManager.open(imagePath) + + // Преобразуем поток данных в Bitmap + val bitmap = BitmapFactory.decodeStream(inputStream) + + // Преобразуем Bitmap в ImageBitmap + val imageBitmap = bitmap.asImageBitmap() + + // Создаем BitmapPainter из ImageBitmap + val painter = BitmapPainter(imageBitmap) + + // Отображаем изображение с помощью Image и BitmapPainter + Image( + painter = painter, + contentDescription = "Image", + modifier = Modifier + .padding(all = 5.dp) + .size(64.dp) + .clip(RoundedCornerShape(10.dp)) + ) +} + +@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 BookListPreview() { + ShortBooksTheme { + Surface( + color = MaterialTheme.colorScheme.background + ) { + BookList(navController = null) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/book/composeui/BookText.kt b/app/src/main/java/com/example/shortbooks/book/composeui/BookText.kt new file mode 100644 index 0000000..9fea048 --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/book/composeui/BookText.kt @@ -0,0 +1,54 @@ +package com.example.shortbooks.book.composeui + +import android.content.res.AssetManager +import android.content.res.Configuration +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import com.example.shortbooks.book.model.getBooks +import com.example.shortbooks.ui.theme.ShortBooksTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BookText(id: Int) { + + val context = LocalContext.current + val assetManager: AssetManager = context.assets + + + val book = getBooks()[id] + val textContent: String = assetManager.open(book.text).bufferedReader().use { it.readText() } + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Button(onClick = { }) { + Text(text = "Добавить в избранное") + } + Text(text = textContent, modifier = Modifier.verticalScroll(rememberScrollState())) + } +} + +@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 BookTextPreview() { + ShortBooksTheme { + Surface( + color = MaterialTheme.colorScheme.background + ) { + BookText(id = 0) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/book/model/Book.kt b/app/src/main/java/com/example/shortbooks/book/model/Book.kt new file mode 100644 index 0000000..fdb3a50 --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/book/model/Book.kt @@ -0,0 +1,18 @@ +package com.example.shortbooks.book.model + +import java.io.Serializable + +data class Book( + val name: String, + val author: String, + val ageLimit: Int, + val text: String, + val image: String +):Serializable +fun getBooks(): List { + return listOf( + Book("Книга 1", "Автор 1", 18, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"), + Book("Книга 2", "Автор 2", 12, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"), + Book("Книга 3", "Автор 3", 6, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"), + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteList.kt b/app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteList.kt new file mode 100644 index 0000000..53e30bf --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteList.kt @@ -0,0 +1,107 @@ +package com.example.shortbooks.favorite.composeui + +import android.content.res.AssetManager +import android.content.res.Configuration +import android.graphics.BitmapFactory +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Card +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import com.example.shortbooks.favorite.model.getFavorites +import com.example.shortbooks.navigation.Screen +import com.example.shortbooks.ui.theme.ShortBooksTheme +@Composable +fun FavoriteList(navController: NavController?) { + Column( + Modifier + .padding(all = 10.dp) + .padding(vertical = 30.dp) + .verticalScroll(rememberScrollState())) { + Text(text = "Избранное", fontSize = 32.sp, modifier = Modifier.padding(all=10.dp)) + getFavorites().forEachIndexed() { index, favorite -> + val favoriteId = Screen.FavoriteText.route.replace("{id}", index.toString()) + Card( + modifier = Modifier + .fillMaxWidth() + .padding(all = 10.dp) + .clickable { navController?.navigate(favoriteId) }, + shape = RoundedCornerShape(15.dp), + ) + { + Box(){ + Row( + verticalAlignment = Alignment.CenterVertically + ){ + ImageConverse(imagePath = favorite.image) + Column { + Text("${favorite.name}", fontSize = 22.sp) + Text("${favorite.author}", fontSize = 18.sp) + } + } + } + } + } + } +} + +@Composable +fun ImageConverse(imagePath: String, modifier: Modifier = Modifier) { + val context = LocalContext.current + val assetManager: AssetManager = context.assets + // Открываем поток данных для изображения в каталоге assets + val inputStream = assetManager.open(imagePath) + + // Преобразуем поток данных в Bitmap + val bitmap = BitmapFactory.decodeStream(inputStream) + + // Преобразуем Bitmap в ImageBitmap + val imageBitmap = bitmap.asImageBitmap() + + // Создаем BitmapPainter из ImageBitmap + val painter = BitmapPainter(imageBitmap) + + // Отображаем изображение с помощью Image и BitmapPainter + Image( + painter = painter, + contentDescription = "Image", + modifier = modifier + .padding(all = 5.dp) + .size(64.dp) + .clip(RoundedCornerShape(10.dp)) + ) +} + +@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 BookListPreview() { + ShortBooksTheme { + Surface( + color = MaterialTheme.colorScheme.background + ) { + FavoriteList(navController = null) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteText.kt b/app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteText.kt new file mode 100644 index 0000000..6cc7fc5 --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/favorite/composeui/FavoriteText.kt @@ -0,0 +1,54 @@ +package com.example.shortbooks.favorite.composeui + +import android.content.res.AssetManager +import android.content.res.Configuration +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import com.example.shortbooks.favorite.model.getFavorites +import com.example.shortbooks.ui.theme.ShortBooksTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun FavoriteText(id: Int) { + + val context = LocalContext.current + val assetManager: AssetManager = context.assets + + + val favorite = getFavorites()[id] + val textContent: String = assetManager.open(favorite.text).bufferedReader().use { it.readText() } + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Button(onClick = { }) { + Text(text = "Удалить из избранного") + } + Text(text = textContent, modifier = Modifier.verticalScroll(rememberScrollState())) + } +} + +@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 BookTextPreview() { + ShortBooksTheme { + Surface( + color = MaterialTheme.colorScheme.background + ) { + FavoriteText(id = 0) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/favorite/model/Favorite.kt b/app/src/main/java/com/example/shortbooks/favorite/model/Favorite.kt new file mode 100644 index 0000000..a6edcaa --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/favorite/model/Favorite.kt @@ -0,0 +1,17 @@ +package com.example.shortbooks.favorite.model + +import java.io.Serializable + +data class Favorite( + val name: String, + val author: String, + val ageLimit: Int, + val text: String, + val image: String +):Serializable +fun getFavorites(): List{ + return listOf( + Favorite( "Книга 1", "Автор 1", 18, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"), + Favorite( "Книга 2", "Автор 2", 18, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"), + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/navigation/MainNavbar.kt b/app/src/main/java/com/example/shortbooks/navigation/MainNavbar.kt new file mode 100644 index 0000000..feca1cd --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/navigation/MainNavbar.kt @@ -0,0 +1,121 @@ +package com.example.shortbooks.navigation + +import android.content.res.Configuration +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.NavDestination +import androidx.navigation.NavDestination.Companion.hierarchy +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument +import com.example.shortbooks.book.composeui.BookList +import com.example.shortbooks.book.composeui.BookText +import com.example.shortbooks.favorite.composeui.FavoriteList +import com.example.shortbooks.favorite.composeui.FavoriteText +import com.example.shortbooks.ui.theme.ShortBooksTheme +import com.example.shortbooks.user.composeui.UserInfo + +@Composable +fun Navbar( + navController: NavHostController, + currentDestination: NavDestination?, + modifier: Modifier = Modifier +) { + NavigationBar(modifier) { + Screen.bottomBarItems.forEach { screen -> + NavigationBarItem( + icon = { Icon(screen.icon, contentDescription = null) }, + label = { Text(stringResource(screen.resourceId)) }, + selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true, + onClick = { + navController.navigate(screen.route) { + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + restoreState = true + } + } + ) + } + } +} + +@Composable +fun Navhost( + navController: NavHostController, + innerPadding: PaddingValues, modifier: + Modifier = Modifier +) { + NavHost( + navController, + startDestination = Screen.BookList.route, + modifier.padding(innerPadding) + ) { + composable(Screen.BookList.route) { BookList(navController) } + composable(Screen.FavoriteList.route) { FavoriteList(navController) } + composable(Screen.UserInfo.route) { UserInfo() } + composable( + Screen.BookText.route, + arguments = listOf(navArgument("id") { type = NavType.IntType }) + ) { backStackEntry -> + backStackEntry.arguments?.let { BookText(it.getInt("id")) } + } + composable( + Screen.FavoriteText.route, + arguments = listOf(navArgument("id") { type = NavType.IntType }) + ) { backStackEntry -> + backStackEntry.arguments?.let { FavoriteText(it.getInt("id")) } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun MainNavbar() { + val navController = rememberNavController() + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry?.destination + val currentScreen = currentDestination?.route?.let { Screen.getItem(it) } + + Scaffold( + bottomBar = { + if (currentScreen == null || currentScreen.showInBottomBar) { + Navbar(navController, currentDestination) + } + } + ) { innerPadding -> + Navhost(navController, innerPadding) + } +} + +@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 MainNavbarPreview() { + ShortBooksTheme { + Surface( + color = MaterialTheme.colorScheme.background + ) { + MainNavbar() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/navigation/Screen.kt b/app/src/main/java/com/example/shortbooks/navigation/Screen.kt new file mode 100644 index 0000000..4e87d9d --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/navigation/Screen.kt @@ -0,0 +1,45 @@ +package com.example.shortbooks.navigation + +import androidx.annotation.StringRes +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountBox +import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material.icons.filled.List +import androidx.compose.ui.graphics.vector.ImageVector +import com.example.shortbooks.R + +enum class Screen( + val route: String, + @StringRes val resourceId: Int, + val icon: ImageVector = Icons.Filled.Favorite, + val showInBottomBar: Boolean = true +) { + BookList( + "book-list", R.string.book_main_title, Icons.Filled.List + ), + FavoriteList( + "favorite-list", R.string.favorite_main_title, Icons.Filled.Favorite + ), + UserInfo( + "user-info", R.string.user_main_title, Icons.Filled.AccountBox + ), + BookText( + "book-view/{id}",R.string.text_main_title,showInBottomBar = false + ), + FavoriteText( + "favorite-view/{id}",R.string.text_main_title,showInBottomBar = false + ); + + companion object { + val bottomBarItems = listOf( + BookList, + FavoriteList, + UserInfo + ) + + fun getItem(route: String): Screen? { + val findRoute = route.split("/").first() + return values().find { value -> value.route.startsWith(findRoute) } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/user/composeui/UserInfo.kt b/app/src/main/java/com/example/shortbooks/user/composeui/UserInfo.kt new file mode 100644 index 0000000..6ce145c --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/user/composeui/UserInfo.kt @@ -0,0 +1,71 @@ +package com.example.shortbooks.user.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.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +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.unit.sp +import com.example.shortbooks.R +import com.example.shortbooks.ui.theme.ShortBooksTheme +import com.example.shortbooks.user.model.getUser + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun UserInfo() { + val user = getUser() + Column( + Modifier + .fillMaxWidth() + .padding(all = 20.dp,) + .padding(vertical = 30.dp) + ) { + Text(text = "Профиль", fontSize=32.sp) + OutlinedTextField(modifier = Modifier + .fillMaxWidth() + .padding(vertical = 10.dp), + value = user.name, onValueChange = {}, readOnly = true, + label = { + Text(stringResource(id = R.string.user_name)) + } + ) + OutlinedTextField(modifier = Modifier + .fillMaxWidth() + .padding(vertical = 10.dp), + value = user.age.toString(), onValueChange = {}, readOnly = true, + label = { + Text(stringResource(id = R.string.user_age)) + } + ) + OutlinedTextField(modifier = Modifier + .fillMaxWidth() + .padding(vertical = 10.dp), + value = user.email, onValueChange = {}, readOnly = true, + label = { + Text(stringResource(id = R.string.user_email)) + } + ) + } +} + +@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 UserInfoPreview() { + ShortBooksTheme { + Surface( + color = MaterialTheme.colorScheme.background + ) { + UserInfo() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shortbooks/user/model/User.kt b/app/src/main/java/com/example/shortbooks/user/model/User.kt new file mode 100644 index 0000000..46675ca --- /dev/null +++ b/app/src/main/java/com/example/shortbooks/user/model/User.kt @@ -0,0 +1,14 @@ +package com.example.shortbooks.user.model + +import java.io.Serializable + +data class User( + val email: String, + val password: String, + val name: String, + val age: Int +): Serializable + +fun getUser():User{ + return User("anatoliqw@gmail.com","anatol213","Анатолий", 47) +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f2aed16..56fa5e8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,10 @@ - ShortBooks + MiniBooks + Книги + Текст + Избранное + Профиль + Имя + Email + Возраст \ No newline at end of file