Compare commits

..

13 Commits

Author SHA1 Message Date
maxnes3
e247aaddb5 Залил 3 лабу 2023-12-23 11:28:02 +04:00
maxnes3
69175e82f0 Подготовка к 4 лабе(дополнил) 2023-11-25 21:44:25 +04:00
maxnes3
7076d707ea Подготовка к 4 лабе 2023-11-25 21:43:54 +04:00
maxnes3
da844b15f7 CRUD работает 2023-11-25 03:02:32 +04:00
maxnes3
f4fa24f50a БД работает 2023-11-24 21:39:43 +04:00
maxnes3
1d1a0e9be7 ВСЁ на ГИТ 2023-11-24 20:22:29 +04:00
maxnes3
1e3fcaa50f Не работает 2023-11-24 19:45:20 +04:00
maxnes3
31b936fe0e ещё немного осталось 2023-11-16 04:17:27 +04:00
maxnes3
1a3a0d4cd7 Я почти гений 2023-11-16 03:06:38 +04:00
maxnes3
6fc39a2396 Я хорош 2023-11-16 02:01:29 +04:00
maxnes3
2567fc24a1 Подготовка к переходу 2023-11-15 23:59:54 +04:00
maxnes3
b45183ebcc Кое-что добавил 2023-11-15 22:21:16 +04:00
maxnes3
1cfd40ae3e Начал 3 лабу 2023-11-15 18:23:02 +04:00
30 changed files with 856 additions and 295 deletions

View File

@ -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>

View File

@ -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 {
@ -30,17 +31,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 {
@ -67,4 +68,12 @@ dependencies {
androidTestImplementation("androidx.compose.ui:ui-test-junit4") androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest") debugImplementation("androidx.compose.ui:ui-test-manifest")
// Room
val room_version = "2.5.2"
implementation("androidx.room:room-runtime:$room_version")
annotationProcessor("androidx.room:room-compiler:$room_version")
ksp("androidx.room:room-compiler:$room_version")
implementation("androidx.room:room-ktx:$room_version")
implementation("androidx.room:room-paging:$room_version")
} }

View File

@ -3,28 +3,13 @@ package com.example.mobileapp
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.example.mobileapp.entities.Mail import com.example.mobileapp.components.NavBar
import com.example.mobileapp.entities.MailSingleton import com.example.mobileapp.database.entities.User
import com.example.mobileapp.entities.Story
import com.example.mobileapp.entities.StorySingleton
import com.example.mobileapp.screens.Authorization
import com.example.mobileapp.screens.EditMailScreen
import com.example.mobileapp.screens.EditStoryScreen
import com.example.mobileapp.screens.ListDataScreen
import com.example.mobileapp.screens.ListMailScreen
import com.example.mobileapp.screens.MainScreen
import com.example.mobileapp.screens.Registration
import com.example.mobileapp.screens.SettingsScreen
import com.example.mobileapp.ui.theme.MobileAppTheme import com.example.mobileapp.ui.theme.MobileAppTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@ -38,57 +23,31 @@ class MainActivity : ComponentActivity() {
color = MaterialTheme.colorScheme.background color = MaterialTheme.colorScheme.background
) { ) {
val navController = rememberNavController() val navController = rememberNavController()
val mailSingleton = MailSingleton() NavBar(navController = navController)
mailSingleton.addMail(Mail(0, 0, "Дзюнзи Ито", "Выложил новый"))
mailSingleton.addMail(Mail(1, 1, "Стивен Кинг", "Меня отменили в Твиттере"))
mailSingleton.addMail(Mail(0, 0, "Дзюнзи Ито", "Выложил новый"))
mailSingleton.addMail(Mail(1, 1, "Стивен Кинг", "Меня отменили в Твиттере"))
mailSingleton.addMail(Mail(0, 0, "Дзюнзи Ито", "Выложил новый"))
mailSingleton.addMail(Mail(1, 1, "Стивен Кинг", "Меня отменили в Твиттере"))
mailSingleton.addMail(Mail(0, 0, "Дзюнзи Ито", "Выложил новый"))
mailSingleton.addMail(Mail(1, 1, "Стивен Кинг", "Меня отменили в Твиттере"))
val storySingleton = StorySingleton()
storySingleton.addStory(Story(0, "Чужак", "Знаменитая книга стивена кинга", R.drawable.king))
storySingleton.addStory(Story(1, "Переулок", "История ужасов от Дзюнзи Ито", R.drawable.dzun))
storySingleton.addStory(Story(2, "Чужак", "Знаменитая книга стивена кинга", R.drawable.king))
storySingleton.addStory(Story(3, "Переулок", "История ужасов от Дзюнзи Ито", R.drawable.dzun))
AppNavigation(navController = navController)
} }
} }
} }
} }
} }
@Composable class GlobalUser private constructor() {
fun AppNavigation(navController: NavHostController){ private var user: User? = null
NavHost(
navController = navController, startDestination = "authorization" fun setUser(user: User?) {
) { this.user = user
composable("authorization"){
Authorization(navController = navController)
} }
composable("registration"){
Registration(navController = navController) fun getUser(): User? {
return user
}
companion object {
private var instance: GlobalUser? = null
fun getInstance(): GlobalUser {
return instance ?: synchronized(this) {
instance ?: GlobalUser().also { instance = it }
} }
composable("main"){
MainScreen(navController = navController)
}
composable("listdata"){
ListDataScreen(navController = navController)
}
composable("mail"){
ListMailScreen(navController = navController)
}
composable("settings"){
SettingsScreen(navController = navController)
}
composable("editstory"){
EditStoryScreen(navController = navController)
}
composable("editmail"){
EditMailScreen(navController = navController)
} }
} }
} }

View File

@ -27,18 +27,23 @@ 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.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import com.example.mobileapp.ui.theme.MobileAppTheme import com.example.mobileapp.ui.theme.MobileAppTheme
val buttonHeightStandard = 72.dp
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun PlaceholderInputField(label: String){ fun PlaceholderInputField(label: String, startValue: String? = null, isSingleLine: Boolean, onTextChanged: (String) -> Unit){
var text = remember { mutableStateOf("") } var text = remember { mutableStateOf("") }
startValue?.let{
text.value = startValue
}
OutlinedTextField( OutlinedTextField(
value = text.value, value = text.value,
onValueChange = { onValueChange = {
text.value = it text.value = it
onTextChanged(it)
}, },
placeholder = { placeholder = {
Text(label) Text(label)
@ -46,18 +51,24 @@ fun PlaceholderInputField(label: String){
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp),
shape = RoundedCornerShape(10.dp)) shape = RoundedCornerShape(10.dp),
singleLine = isSingleLine
)
} }
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun PasswordInputField(label: String){ fun PasswordInputField(label: String, startValue: String? = null, onPasswordChanged: (String) -> Unit){
var text = remember { mutableStateOf("") } var text = remember { mutableStateOf("") }
startValue?.let{
text.value = startValue
}
OutlinedTextField( OutlinedTextField(
value = text.value, value = text.value,
onValueChange = { onValueChange = {
text.value = it text.value = it
onPasswordChanged(it)
}, },
placeholder = { placeholder = {
Text(label) Text(label)
@ -92,7 +103,8 @@ fun SearchInputField(){
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 16.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), .padding(top = 16.dp, start = 16.dp, bottom = 8.dp, end = 16.dp),
shape = RoundedCornerShape(10.dp) shape = RoundedCornerShape(10.dp),
singleLine = true
) )
} }
@ -102,7 +114,7 @@ fun IconButton(iconLeft: ImageVector, label: String, backgroundColor: Color, tex
onClick = onClickAction, onClick = onClickAction,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.requiredHeight(64.dp) .requiredHeight(buttonHeightStandard)
.padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = backgroundColor containerColor = backgroundColor
@ -134,7 +146,7 @@ fun ActiveButton(label: String, backgroundColor: Color, textColor: Color, onClic
onClick = onClickAction, onClick = onClickAction,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.requiredHeight(64.dp) .requiredHeight(buttonHeightStandard)
.padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = backgroundColor containerColor = backgroundColor
@ -155,7 +167,7 @@ fun ActiveButton(label: String, backgroundColor: Color, textColor: Color, onClic
fun PlaceholderTextFieldPreview() { fun PlaceholderTextFieldPreview() {
MobileAppTheme { MobileAppTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
PlaceholderInputField("Email") PlaceholderInputField("Email", null,true, { })
} }
} }
} }

View File

@ -16,58 +16,83 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
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.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment 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.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.mobileapp.R import com.example.mobileapp.R
import com.example.mobileapp.entities.Mail import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.entities.MailSingleton import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.entities.Story import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.entities.StorySingleton
import com.example.mobileapp.ui.theme.BackgroundItem2 import com.example.mobileapp.ui.theme.BackgroundItem2
import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2 import com.example.mobileapp.ui.theme.ButtonColor2
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat
import java.util.Date
val dateFormat = SimpleDateFormat("dd.MM.yyyy")
@Composable @Composable
fun DataListScroll(navController: NavHostController){ fun <T : Any> DataListScroll(navController: NavHostController, dataList: List<T>){
val storySingleton = StorySingleton()
val isFirstTime = remember { mutableStateOf(true) }
LazyColumn( LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
){ ){
item { item {
addNewListItem(navController, "editstory") when {
dataList.isListOf<Story>() -> addNewListItem(navController, "editstory")
dataList.isListOf<Mail>() -> addNewListItem(navController, "editmail")
}
}
items(dataList){ item ->
when(item){
is Story -> StoryListItem(item = item, navController = navController)
is Mail -> MailListItem(item = item)
} }
items(storySingleton.getStoryList()){ item ->
DataListItem(item = item, navController = navController)
} }
} }
} }
inline fun <reified T> List<*>.isListOf(): Boolean {
return isNotEmpty() && all { it is T }
}
@Composable @Composable
fun DataListItem(item: Story, navController: NavHostController){ fun StoryListItem(item: Story, navController: NavHostController){
val context = LocalContext.current
val isExpanded = remember { val isExpanded = remember {
mutableStateOf(false) mutableStateOf(false)
} }
val showDialog = remember {
mutableStateOf(false)
}
val delete = remember {
mutableStateOf(false)
}
Card( Card(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -89,7 +114,7 @@ fun DataListItem(item: Story, navController: NavHostController){
Row( Row(
verticalAlignment = Alignment.Top verticalAlignment = Alignment.Top
){ ){
Image(painter = painterResource(id = item.cover), Image(bitmap = item.cover.asImageBitmap(),
contentDescription = item.description, contentDescription = item.description,
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier modifier = Modifier
@ -99,7 +124,7 @@ fun DataListItem(item: Story, navController: NavHostController){
modifier = Modifier.padding(8.dp) modifier = Modifier.padding(8.dp)
){ ){
Text( Text(
text = item.title, text = "${item.title} | ${dateFormat.format(Date(item.postdate!!))}",
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
@ -114,12 +139,36 @@ fun DataListItem(item: Story, navController: NavHostController){
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End horizontalArrangement = Arrangement.End
){ ){
DataListItemButton("Изменить", ButtonColor2, Color.White, onClickAction = { navController.navigate("editstory") }) DataListItemButton("Изменить", ButtonColor2, Color.White, onClickAction = {
DataListItemButton("Удалить", Color.Red, Color.White, onClickAction = { }) navController.navigate("editstory/${item.id}")
})
DataListItemButton("Удалить", Color.Red, Color.White, onClickAction = {
showDialog.value = !showDialog.value
})
} }
} }
} }
} }
if(showDialog.value) {
DialogWindow(label = "Подтверждение",
message = "Вы уверены что хотите удалить запись?", onConfirmAction = {
delete.value = !delete.value
showDialog.value = !showDialog.value
}, onDismissAction = {
showDialog.value = !showDialog.value
})
}
if(delete.value) {
LaunchedEffect(Unit){
withContext(Dispatchers.IO){
MobileAppDataBase.getInstance(context).storyDao().delete(item)
}
}
delete.value = !delete.value
navController.navigate("story")
}
} }
@Composable @Composable
@ -140,24 +189,6 @@ fun DataListItemButton(label: String, backgroundColor: Color, textColor: Color,
} }
} }
@Composable
fun MailListScroll(navController: NavHostController){
val mailSingleton = MailSingleton()
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
){
item {
addNewListItem(navController, "editmail")
}
items(mailSingleton.getMailList()){ item ->
MailListItem(item = item)
}
}
}
@Composable @Composable
fun MailListItem(item: Mail){ fun MailListItem(item: Mail){
val isExpanded = remember { val isExpanded = remember {
@ -195,7 +226,7 @@ fun MailListItem(item: Mail){
modifier = Modifier.padding(8.dp) modifier = Modifier.padding(8.dp)
){ ){
Text( Text(
text = item.username, text = "item.username | ${dateFormat.format(Date(item.postdate!!))}",
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.Bold) fontWeight = FontWeight.Bold)
Text(text = item.message) Text(text = item.message)
@ -265,3 +296,41 @@ fun addNewListItem(navController: NavHostController, destination: String){
} }
} }
} }
@Composable
fun DialogWindow(label: String, message: String, onConfirmAction: () -> Unit, onDismissAction: () -> Unit){
AlertDialog(onDismissRequest = onDismissAction,
title = {
Text(text = label,
fontSize = 20.sp,
fontWeight = FontWeight.Bold)
},
text = {
Text(text = message)
},
confirmButton = {
Button(
onClick = onConfirmAction,
colors = ButtonDefaults.buttonColors(
containerColor = ButtonColor2
),
shape = RoundedCornerShape(5.dp)
) {
Text(text = "Подтвердить",
color = Color.White)
}
},
dismissButton = {
Button(
onClick = onDismissAction,
colors = ButtonDefaults.buttonColors(
containerColor = ButtonColor1
),
shape = RoundedCornerShape(5.dp)
) {
Text(text = "Отмена",
color = Color.Black)
}
}
)
}

View File

@ -0,0 +1,11 @@
package com.example.mobileapp.components
import androidx.annotation.DrawableRes
class NavBarItem(
val route: String,
val label: String,
@DrawableRes
val icon: Int
) {
}

View File

@ -1,9 +1,11 @@
package com.example.mobileapp.components package com.example.mobileapp.components
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.Row
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.layout.requiredHeight import androidx.compose.foundation.layout.requiredHeight
@ -12,14 +14,15 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -30,38 +33,117 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.example.mobileapp.R import com.example.mobileapp.R
import com.example.mobileapp.screens.Authorization
import com.example.mobileapp.screens.EditMailScreen
import com.example.mobileapp.screens.EditStoryScreen
import com.example.mobileapp.screens.EditUserScreen
import com.example.mobileapp.screens.ListDataScreen
import com.example.mobileapp.screens.ListMailScreen
import com.example.mobileapp.screens.MainScreen
import com.example.mobileapp.screens.Registration
import com.example.mobileapp.screens.SettingsScreen
@Composable val navBarItems = listOf(
fun NavBar(navController: NavHostController, itemColorFilter: Color) { NavBarItem(route = "main", label = "Главная", icon = R.drawable.home),
Row( NavBarItem(route = "story", label = "Создание", icon = R.drawable.edit),
modifier = Modifier NavBarItem(route = "mail", label = "Уведомления", icon = R.drawable.mail),
.fillMaxWidth(), NavBarItem(route = "settings", label = "Настройки", icon = R.drawable.settings),
horizontalArrangement = Arrangement.SpaceEvenly, )
verticalAlignment = Alignment.CenterVertically
) {
NavItem(navController = navController, imageId = R.drawable.home,
description = "homeButton", destination = "main", itemColorFilter = itemColorFilter)
NavItem(navController = navController, imageId = R.drawable.edit,
description = "editButton", destination = "listdata", itemColorFilter = itemColorFilter)
NavItem(navController = navController, imageId = R.drawable.mail,
description = "mailButton", destination = "mail", itemColorFilter = itemColorFilter)
NavItem(navController = navController, imageId = R.drawable.settings,
description = "settingsButton", destination = "settings", itemColorFilter = itemColorFilter)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun NavItem(navController: NavHostController, imageId: Int, fun NavBar(navController: NavHostController) {
description: String, destination: String, itemColorFilter: Color){ val bottomBarState = rememberSaveable { (mutableStateOf(false)) }
Image(painter = painterResource(id = imageId),
contentDescription = description, Scaffold(
contentScale = ContentScale.Crop, bottomBar = {
AnimatedVisibility(
visible = bottomBarState.value,
enter = slideInVertically(initialOffsetY = { it }),
exit = slideOutVertically(targetOffsetY = { it }),
content = {
NavigationBar {
navBarItems.forEach{item ->
NavigationBarItem(
icon = {
Image(
painter = painterResource(item.icon),
contentDescription = null,
modifier = Modifier modifier = Modifier
.size(64.dp) .size(40.dp)
.clickable { .padding(bottom = 6.dp)
navController.navigate(destination) )
}, },
colorFilter = ColorFilter.tint(itemColorFilter)) label = {
Text(
text = item.label
)
},
onClick = {
navController.navigate(item.route)
},
selected = false,
modifier = Modifier.fillMaxSize()
)
}
}
}
)
},
modifier = Modifier.background(Color.White)
) {innerPaddings ->
NavHost(
navController = navController,
startDestination = "authorization",
modifier = Modifier.padding(innerPaddings)
) {
composable("authorization"){
bottomBarState.value = false
Authorization(navController = navController)
}
composable("registration"){
bottomBarState.value = false
Registration(navController = navController)
}
composable("main"){
bottomBarState.value = true
MainScreen(navController = navController)
}
composable("story"){
bottomBarState.value = true
ListDataScreen(navController = navController)
}
composable("mail"){
bottomBarState.value = true
ListMailScreen(navController = navController)
}
composable("settings"){
bottomBarState.value = true
SettingsScreen(navController = navController)
}
composable("editstory"){ // Без аргумента
bottomBarState.value = false
EditStoryScreen(navController = navController)
}
composable(
"editstory/{id}",
arguments = listOf(navArgument("id") { type = NavType.IntType }) //С аргументом
) { backStackEntry ->
backStackEntry.arguments?.let {
bottomBarState.value = false
EditStoryScreen(navController = navController, storyId = it.getInt("id"))
}
}
composable("editmail"){ // Без аргумента
bottomBarState.value = false
EditMailScreen(navController = navController)
}
composable("edituser"){
bottomBarState.value = false
EditUserScreen(navController = navController)
}
}
}
} }
@Composable @Composable
@ -74,7 +156,7 @@ fun NavigationButton(navController: NavHostController,
}, },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.requiredHeight(64.dp) .requiredHeight(72.dp)
.padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp), .padding(top = 8.dp, start = 16.dp, bottom = 8.dp, end = 16.dp),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = backgroundColor containerColor = backgroundColor

View File

@ -0,0 +1,74 @@
package com.example.mobileapp.database
import android.content.Context
import android.graphics.BitmapFactory
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.mobileapp.R
import com.example.mobileapp.database.dao.MailDao
import com.example.mobileapp.database.dao.StoryDao
import com.example.mobileapp.database.dao.UserDao
import com.example.mobileapp.database.entities.Converters
import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.database.entities.User
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@Database(entities = [User::class, Story::class, Mail::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class MobileAppDataBase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun storyDao(): StoryDao
abstract fun mailDao(): MailDao
companion object{
private const val DB_NAME: String = "my-db"
@Volatile
private var INSTANCE: MobileAppDataBase? = null
suspend fun initialDataBase(appContext: Context){
INSTANCE?.let { database ->
val userDao = database.userDao()
userDao.insert(User(id = 1, login = "Дзюнзи Ито", password = "1234", email = "ito@gmail.com"))
userDao.insert(User(id = 2, login = "Стивен Кинг", password = "4321", email = "king@gmail.com"))
val storyDao = database.storyDao()
storyDao.insert(Story(title = "Переулок", description = "История ужасов от Дзюнзи Ито",
cover = BitmapFactory.decodeResource(appContext.resources, R.drawable.dzun), userId = 1))
storyDao.insert(Story(title = "Чужак", description = "Знаменитая книга стивена кинга",
cover = BitmapFactory.decodeResource(appContext.resources, R.drawable.king), userId = 2))
val mailDao = database.mailDao()
mailDao.insert(Mail(message = "Выложил новые страницы", userId = 1))
mailDao.insert(Mail(message = "Меня отменили в Твиттере", userId = 2))
}
}
fun getInstance(appContext: Context): MobileAppDataBase {
return INSTANCE ?: synchronized(this) {
Room.databaseBuilder(
appContext,
MobileAppDataBase::class.java,
DB_NAME
)
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
CoroutineScope(Dispatchers.IO).launch {
initialDataBase(appContext)
}
}
})
.fallbackToDestructiveMigration()
.build()
.also { INSTANCE = it }
}
}
}
}

View File

@ -0,0 +1,28 @@
package com.example.mobileapp.database.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.mobileapp.database.entities.Mail
import kotlinx.coroutines.flow.Flow
@Dao
interface MailDao {
@Query("select * from mails")
fun getAll(): Flow<List<Mail>>
@Query("select * from mails where mails.id = :id")
fun getById(id: Int): Mail?
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(mail: Mail)
@Update
suspend fun update(mail: Mail)
@Delete
suspend fun delete(mail: Mail)
}

View File

@ -0,0 +1,31 @@
package com.example.mobileapp.database.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.mobileapp.database.entities.Story
import kotlinx.coroutines.flow.Flow
@Dao
interface StoryDao {
@Query("select * from stories")
fun getAll(): Flow<List<Story>>
@Query("select * from stories where stories.id = :id")
fun getById(id: Int): Story?
@Query("select * from stories where stories.user_id = :userId")
fun getByUserId(userId: Int): Flow<List<Story>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(story: Story)
@Update
suspend fun update(story: Story)
@Delete
suspend fun delete(story: Story)
}

View File

@ -0,0 +1,28 @@
package com.example.mobileapp.database.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import com.example.mobileapp.database.entities.User
import kotlinx.coroutines.flow.Flow
@Dao
interface UserDao {
@Query("select * from users")
fun getAll():Flow<List<User>>
@Query("select * from users where users.id = :id")
fun getById(id: Int): User?
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(user: User)
@Update
suspend fun update(user: User)
@Delete
suspend fun delete(user: User)
}

View File

@ -0,0 +1,22 @@
package com.example.mobileapp.database.entities
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.room.TypeConverter
import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
import java.util.Date
class Converters {
@TypeConverter
fun fromBitmap(bitmap: Bitmap) : ByteArray {
val outputStream = ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
return outputStream.toByteArray()
}
@TypeConverter
fun toBitmap(byteArray: ByteArray): Bitmap {
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
}
}

View File

@ -0,0 +1,34 @@
package com.example.mobileapp.database.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import java.util.Date
@Entity(
tableName = "mails",
foreignKeys = [
ForeignKey(
entity = User::class,
parentColumns = ["id"],
childColumns = ["user_id"],
onDelete = ForeignKey.RESTRICT,
onUpdate = ForeignKey.RESTRICT
)
]
)
data class Mail(
@PrimaryKey(autoGenerate = true)
val id: Int? = null,
@ColumnInfo(name = "message")
val message: String,
@ColumnInfo(name = "postdate")
val postdate: Long? = Date().time,
@ColumnInfo(name="user_id")
val userId: Int
){
override fun hashCode(): Int {
return id ?: -1
}
}

View File

@ -0,0 +1,40 @@
package com.example.mobileapp.database.entities
import android.graphics.Bitmap
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import java.util.Calendar
import java.util.Date
@Entity(
tableName = "stories",
foreignKeys = [
ForeignKey(
entity = User::class,
parentColumns = ["id"],
childColumns = ["user_id"],
onDelete = ForeignKey.RESTRICT,
onUpdate = ForeignKey.RESTRICT
)
]
)
data class Story(
@PrimaryKey(autoGenerate = true)
val id: Int? = null,
@ColumnInfo(name = "title")
val title: String,
@ColumnInfo(name = "description")
val description: String,
@ColumnInfo(name = "cover")
val cover: Bitmap,
@ColumnInfo(name = "postdate")
val postdate: Long? = Date().time,
@ColumnInfo(name="user_id")
val userId: Int
){
override fun hashCode(): Int {
return id ?: -1
}
}

View File

@ -0,0 +1,24 @@
package com.example.mobileapp.database.entities
import android.graphics.Bitmap
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true)
val id: Int? = null,
@ColumnInfo(name = "login")
val login: String,
@ColumnInfo(name = "password")
val password: String,
@ColumnInfo(name = "email")
val email: String,
@ColumnInfo(name = "photo")
val photo: Bitmap? = null
){
override fun hashCode(): Int {
return id ?: -1
}
}

View File

@ -1,8 +0,0 @@
package com.example.mobileapp.entities
data class Mail(
val id: Int,
val userId: Int,
val username: String,
val message: String
)

View File

@ -1,15 +0,0 @@
package com.example.mobileapp.entities
class MailSingleton {
companion object {
val mailList: MutableList<Mail> = mutableListOf()
}
fun addMail(mail: Mail) {
mailList.add(mail)
}
fun getMailList(): List<Mail> {
return mailList.toList()
}
}

View File

@ -1,8 +0,0 @@
package com.example.mobileapp.entities
data class Story(
val id: Int,
val title: String,
val description: String,
val cover: Int
)

View File

@ -1,15 +0,0 @@
package com.example.mobileapp.entities
class StorySingleton {
companion object {
val storyList: MutableList<Story> = mutableListOf()
}
fun addStory(story: Story) {
storyList.add(story)
}
fun getStoryList(): List<Story> {
return storyList.toList()
}
}

View File

@ -1,7 +0,0 @@
package com.example.mobileapp.entities
data class User(
val email: String,
val login: String,
val password: String
)

View File

@ -7,10 +7,14 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
@ -18,11 +22,26 @@ import com.example.mobileapp.R
import com.example.mobileapp.components.NavigationButton import com.example.mobileapp.components.NavigationButton
import com.example.mobileapp.components.PasswordInputField import com.example.mobileapp.components.PasswordInputField
import com.example.mobileapp.components.PlaceholderInputField import com.example.mobileapp.components.PlaceholderInputField
import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.User
import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2 import com.example.mobileapp.ui.theme.ButtonColor2
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun Authorization(navController: NavHostController){ fun Authorization(navController: NavHostController){
val context = LocalContext.current
val users = remember { mutableStateListOf<User>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
MobileAppDataBase.getInstance(context).userDao().getAll().collect { data ->
users.clear()
users.addAll(data)
}
}
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -37,8 +56,8 @@ fun Authorization(navController: NavHostController){
.size(512.dp) .size(512.dp)
.padding(8.dp) .padding(8.dp)
.align(Alignment.CenterHorizontally)) .align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Логин") PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {})
PasswordInputField(label = "Пароль") PasswordInputField(label = "Пароль", onPasswordChanged = {})
NavigationButton(navController = navController, destination = "main", label = "Вход", NavigationButton(navController = navController, destination = "main", label = "Вход",
backgroundColor = ButtonColor2, textColor = Color.White) backgroundColor = ButtonColor2, textColor = Color.White)
NavigationButton(navController = navController, destination = "registration", label = "Регистрация", NavigationButton(navController = navController, destination = "registration", label = "Регистрация",

View File

@ -1,5 +1,13 @@
package com.example.mobileapp.screens package com.example.mobileapp.screens
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageDecoder
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -7,10 +15,16 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment 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.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
@ -19,11 +33,81 @@ import com.example.mobileapp.components.ActiveButton
import com.example.mobileapp.components.NavigationButton import com.example.mobileapp.components.NavigationButton
import com.example.mobileapp.components.PasswordInputField import com.example.mobileapp.components.PasswordInputField
import com.example.mobileapp.components.PlaceholderInputField import com.example.mobileapp.components.PlaceholderInputField
import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor1
import com.example.mobileapp.ui.theme.ButtonColor2 import com.example.mobileapp.ui.theme.ButtonColor2
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun EditStoryScreen(navController: NavHostController) { fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) {
val context = LocalContext.current
val cover = remember { mutableStateOf<Bitmap>(BitmapFactory.decodeResource(context.resources, R.drawable.editplaceholder)) }
val title = remember { mutableStateOf("") }
val description = remember { mutableStateOf("") }
val imageData = remember { mutableStateOf<Uri?>(null) }
val launcher =
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {uri: Uri? ->
imageData.value = uri
}
imageData.value?.let {
if (Build.VERSION.SDK_INT < 28) {
cover.value = MediaStore.Images
.Media.getBitmap(context.contentResolver, imageData.value)
} else {
val source = ImageDecoder
.createSource(context.contentResolver, imageData.value!!)
cover.value = ImageDecoder.decodeBitmap(source)
}
}
storyId?.let{
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
val story = MobileAppDataBase.getInstance(context).storyDao().getById(storyId!!)
cover.value = story!!.cover
title.value = story!!.title
description.value = story!!.description
}
}
}
val edit = remember { mutableStateOf(false) }
if (edit.value){
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
storyId?.let {
MobileAppDataBase.getInstance(context).storyDao()
.update(
Story(
id = storyId,
title = title.value,
description = description.value,
cover = cover.value,
userId = 1)
)
} ?: run {
MobileAppDataBase.getInstance(context).storyDao()
.insert(
Story(
title = title.value,
description = description.value,
cover = cover.value,
userId = 1)
)
}
}
}
edit.value = !edit.value
navController.navigate("story")
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -31,23 +115,49 @@ fun EditStoryScreen(navController: NavHostController) {
verticalArrangement = Arrangement.Bottom verticalArrangement = Arrangement.Bottom
) { ) {
Image( Image(
painter = painterResource(id = R.drawable.editplaceholder), bitmap = cover.value.asImageBitmap(),
contentDescription = "editplaceholder", contentDescription = "editplaceholder",
contentScale = ContentScale.Crop, contentScale = ContentScale.Crop,
modifier = Modifier modifier = Modifier
.size(512.dp) .size(384.dp)
.padding(8.dp) .padding(8.dp)
.align(Alignment.CenterHorizontally)) .align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Название") ActiveButton(label = "Выбрать обложку", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
ActiveButton(label = "Выбрать обложку", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {}) launcher.launch("image/*")
PlaceholderInputField(label = "Описание") })
NavigationButton(navController = navController, destination = "listdata", label = "Назад", PlaceholderInputField(label = "Название", isSingleLine = true,
startValue = title.value, onTextChanged = { newName ->
title.value = newName
})
PlaceholderInputField(label = "Описание", isSingleLine = true,
startValue = description.value, onTextChanged = { newDescription ->
description.value = newDescription
})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
edit.value = !edit.value
})
NavigationButton(navController = navController, destination = "story", label = "Назад",
backgroundColor = ButtonColor2, textColor = Color.White) backgroundColor = ButtonColor2, textColor = Color.White)
} }
} }
@Composable @Composable
fun EditMailScreen(navController: NavHostController) { fun EditMailScreen(navController: NavHostController) {
val context = LocalContext.current
val message = remember { mutableStateOf("") }
val create = remember { mutableStateOf(false) }
if(create.value){
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
MobileAppDataBase.getInstance(context).mailDao()
.insert(Mail(message = message.value, userId = 2))
}
}
create.value = !create.value
navController.navigate("mail")
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -62,9 +172,76 @@ fun EditMailScreen(navController: NavHostController) {
.size(512.dp) .size(512.dp)
.padding(8.dp) .padding(8.dp)
.align(Alignment.CenterHorizontally)) .align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Заголовок") PlaceholderInputField(label = "Текс поста", isSingleLine = false, onTextChanged = { newmessage ->
PlaceholderInputField(label = "Текс поста") message.value = newmessage
})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
create.value = !create.value
})
NavigationButton(navController = navController, destination = "mail", label = "Назад", NavigationButton(navController = navController, destination = "mail", label = "Назад",
backgroundColor = ButtonColor2, textColor = Color.White) backgroundColor = ButtonColor2, textColor = Color.White)
} }
} }
@Composable
fun EditUserScreen(navController: NavHostController){
val context = LocalContext.current
val photo = remember { mutableStateOf<Bitmap>(BitmapFactory.decodeResource(context.resources, R.drawable.photoplaceholder)) }
val name = remember { mutableStateOf("") }
val password = remember { mutableStateOf("") }
val email = remember { mutableStateOf("") }
val imageData = remember { mutableStateOf<Uri?>(null) }
val launcher =
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {uri: Uri? ->
imageData.value = uri
}
imageData.value?.let {
if (Build.VERSION.SDK_INT < 28) {
photo.value = MediaStore.Images
.Media.getBitmap(context.contentResolver, imageData.value)
} else {
val source = ImageDecoder
.createSource(context.contentResolver, imageData.value!!)
photo.value = ImageDecoder.decodeBitmap(source)
}
}
Column(
modifier = Modifier
.fillMaxSize()
.padding(bottom = 8.dp),
verticalArrangement = Arrangement.Bottom
) {
Image(
bitmap = photo.value.asImageBitmap(),
contentDescription = "editplaceholder",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(384.dp)
.padding(8.dp)
.align(Alignment.CenterHorizontally))
ActiveButton(label = "Выбрать фото", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
launcher.launch("image/*")
})
PlaceholderInputField(label = "Никнейм", isSingleLine = true,
startValue = name.value, onTextChanged = { newName ->
name.value = newName
})
PlaceholderInputField(label = "Пароль", isSingleLine = true,
startValue = password.value, onTextChanged = { newPassword ->
password.value = newPassword
})
PlaceholderInputField(label = "Почта", isSingleLine = true,
startValue = email.value, onTextChanged = { newEmail ->
email.value = newEmail
})
ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
//edit.value = !edit.value
})
NavigationButton(navController = navController, destination = "story", label = "Назад",
backgroundColor = ButtonColor2, textColor = Color.White)
}
}

View File

@ -8,33 +8,41 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.mobileapp.components.DataListScroll import com.example.mobileapp.components.DataListScroll
import com.example.mobileapp.components.NavBar import com.example.mobileapp.components.NavBar
import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.Story
import com.example.mobileapp.ui.theme.BackgroundItem1 import com.example.mobileapp.ui.theme.BackgroundItem1
import com.example.mobileapp.ui.theme.BackgroundItem2 import com.example.mobileapp.ui.theme.BackgroundItem2
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun ListDataScreen(navController: NavHostController){ fun ListDataScreen(navController: NavHostController){
val context = LocalContext.current
val stories = remember { mutableStateListOf<Story>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
MobileAppDataBase.getInstance(context).storyDao().getAll().collect { data ->
stories.clear()
stories.addAll(data)
}
}
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(BackgroundItem1) .background(BackgroundItem1)
) { ) {
Box( DataListScroll(navController, stories)
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.9f)
){
DataListScroll(navController)
}
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center
) {
NavBar(navController = navController, itemColorFilter = BackgroundItem2)
}
} }
} }

View File

@ -1,40 +1,42 @@
package com.example.mobileapp.screens package com.example.mobileapp.screens
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.mobileapp.components.MailListScroll import com.example.mobileapp.components.DataListScroll
import com.example.mobileapp.components.NavBar import com.example.mobileapp.database.MobileAppDataBase
import com.example.mobileapp.database.entities.Mail
import com.example.mobileapp.ui.theme.BackgroundItem1 import com.example.mobileapp.ui.theme.BackgroundItem1
import com.example.mobileapp.ui.theme.BackgroundItem2 import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable @Composable
fun ListMailScreen(navController: NavHostController){ fun ListMailScreen(navController: NavHostController){
val context = LocalContext.current
val mails = remember { mutableStateListOf<Mail>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
MobileAppDataBase.getInstance(context).mailDao().getAll().collect { data ->
mails.clear()
mails.addAll(data)
}
}
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(BackgroundItem1) .background(BackgroundItem1)
) { ) {
Box( DataListScroll(navController, mails)
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.9f)
){
MailListScroll(navController)
}
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center
) {
NavBar(navController = navController, itemColorFilter = BackgroundItem2)
}
} }
} }

View File

@ -51,12 +51,5 @@ fun MainScreen(navController: NavHostController) {
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
} }
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center
) {
NavBar(navController = navController, itemColorFilter = Color.Black)
}
} }
} }

View File

@ -37,10 +37,10 @@ fun Registration(navController: NavHostController){
.size(384.dp) .size(384.dp)
.padding(8.dp) .padding(8.dp)
.align(Alignment.CenterHorizontally)) .align(Alignment.CenterHorizontally))
PlaceholderInputField(label = "Логин") PlaceholderInputField(label = "Логин", isSingleLine = true, onTextChanged = {})
PlaceholderInputField(label = "Email") PlaceholderInputField(label = "Email", isSingleLine = true, onTextChanged = {})
PasswordInputField(label = "Пароль") PasswordInputField(label = "Пароль", onPasswordChanged = {})
PasswordInputField(label = "Пароль ещё раз") PasswordInputField(label = "Пароль ещё раз", onPasswordChanged = {})
NavigationButton(navController = navController, destination = "main", NavigationButton(navController = navController, destination = "main",
label = "Зарегистрироваться", backgroundColor = ButtonColor2, textColor = Color.White) label = "Зарегистрироваться", backgroundColor = ButtonColor2, textColor = Color.White)
NavigationButton(navController = navController, destination = "authorization", NavigationButton(navController = navController, destination = "authorization",

View File

@ -37,12 +37,7 @@ import com.example.mobileapp.ui.theme.ButtonColor2
fun SettingsScreen(navController: NavHostController){ fun SettingsScreen(navController: NavHostController){
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize(),
) {
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.9f),
verticalArrangement = Arrangement.Top, verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
@ -54,22 +49,24 @@ fun SettingsScreen(navController: NavHostController){
.size(384.dp) .size(384.dp)
.padding(8.dp)) .padding(8.dp))
IconButton(iconLeft = Icons.Default.AccountCircle, label = "Учётная запись", IconButton(iconLeft = Icons.Default.AccountCircle, label = "Учётная запись",
backgroundColor = ButtonColor2, textColor = Color.White, onClickAction = { }) backgroundColor = ButtonColor2, textColor = Color.White, onClickAction = {
navController.navigate("edituser")
})
IconButton(iconLeft = Icons.Default.Face, label = "Внешний вид", IconButton(iconLeft = Icons.Default.Face, label = "Внешний вид",
backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = { }) backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
})
IconButton(iconLeft = Icons.Default.Share, label = "Контакты", IconButton(iconLeft = Icons.Default.Share, label = "Контакты",
backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = { }) backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
})
IconButton(iconLeft = Icons.Default.Info, label = "О приложении", IconButton(iconLeft = Icons.Default.Info, label = "О приложении",
backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = { }) backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {
})
IconButton(iconLeft = Icons.Default.ExitToApp, label = "Выйти", IconButton(iconLeft = Icons.Default.ExitToApp, label = "Выйти",
backgroundColor = Color.Red, textColor = Color.White, onClickAction = { }) backgroundColor = Color.Red, textColor = Color.White, onClickAction = {
} navController.navigate("authorization")
Column( })
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center
) {
NavBar(navController = navController, itemColorFilter = Color.Black)
}
} }
} }

Binary file not shown.

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
</network-security-config>

View File

@ -2,4 +2,5 @@
plugins { plugins {
id("com.android.application") version "8.1.1" apply false id("com.android.application") version "8.1.1" apply false
id("org.jetbrains.kotlin.android") version "1.8.10" apply false id("org.jetbrains.kotlin.android") version "1.8.10" apply false
id("com.google.devtools.ksp") version "1.8.20-1.0.11" apply false
} }