diff --git a/app/src/main/java/com/example/mobileapp/components/InputContent.kt b/app/src/main/java/com/example/mobileapp/components/InputContent.kt index 78dde21..ce57e2d 100644 --- a/app/src/main/java/com/example/mobileapp/components/InputContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/InputContent.kt @@ -82,13 +82,14 @@ fun PasswordInputField(label: String, startValue: String? = null, onPasswordChan @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SearchInputField(){ +fun SearchInputField(onTextChanged: (String) -> Unit){ var text = remember { mutableStateOf("") } OutlinedTextField( value = text.value, onValueChange = { text.value = it + onTextChanged(it) }, leadingIcon = { Icon( diff --git a/app/src/main/java/com/example/mobileapp/components/ListContent.kt b/app/src/main/java/com/example/mobileapp/components/ListContent.kt index 85c8b52..3b8b62e 100644 --- a/app/src/main/java/com/example/mobileapp/components/ListContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/ListContent.kt @@ -74,7 +74,7 @@ fun DataListScroll(navController: NavHostController, dataList: List items(dataList){ item -> when(item){ is Story -> StoryListItem(item = item, navController = navController) - is Mail -> MailListItem(item = item) + is Mail -> MailListItem(item = item, navController = navController) } } } @@ -143,7 +143,7 @@ fun StoryListItem(item: Story, navController: NavHostController, if (isReadOnly!!){ DataListItemButton(label = "Подробнее", backgroundColor = ButtonColor2, textColor = Color.White, onClickAction = { - + navController.navigate("viewstory/${item.id}") }) } else{ @@ -193,7 +193,7 @@ fun DataListItemButton(label: String, backgroundColor: Color, textColor: Color, } @Composable -fun MailListItem(item: Mail){ +fun MailListItem(item: Mail, navController: NavHostController){ val isExpanded = remember { mutableStateOf(false) } @@ -241,7 +241,7 @@ fun MailListItem(item: Mail){ ) { DataListItemButton(label = "Подробнее", backgroundColor = ButtonColor2, textColor = Color.White, onClickAction = { - + navController.navigate("viewmail/${item.id}") }) } } diff --git a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt index 2e12b08..c2e5b06 100644 --- a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt +++ b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt @@ -43,9 +43,11 @@ import com.example.mobileapp.screens.EditStoryScreen import com.example.mobileapp.screens.EditUserScreen import com.example.mobileapp.screens.ListMailScreen import com.example.mobileapp.screens.ListStoryScreen +import com.example.mobileapp.screens.MailViewScreen import com.example.mobileapp.screens.MainScreen import com.example.mobileapp.screens.Registration import com.example.mobileapp.screens.SettingsScreen +import com.example.mobileapp.screens.StoryViewScreen val navBarItems = listOf( NavBarItem(route = "main", label = "Главная", icon = R.drawable.home), @@ -179,6 +181,26 @@ fun NavBar(navController: NavHostController) { bottomBarState.value = false EditUserScreen(navController = navController) } + composable( + "viewstory/{id}", + arguments = listOf(navArgument("id") { type = NavType.IntType }) //С аргументом + ) { backStackEntry -> + backStackEntry.arguments?.let { + topBarState.value = false + bottomBarState.value = false + StoryViewScreen(navController = navController, storyId = it.getInt("id")) + } + } + composable( + "viewmail/{id}", + arguments = listOf(navArgument("id") { type = NavType.IntType }) //С аргументом + ) { backStackEntry -> + backStackEntry.arguments?.let { + topBarState.value = false + bottomBarState.value = false + MailViewScreen(navController = navController, mailId = it.getInt("id")) + } + } } } } diff --git a/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt b/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt index 4e96fac..1085071 100644 --- a/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt +++ b/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt @@ -45,8 +45,16 @@ abstract class MobileAppDataBase : RoomDatabase() { 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)) + for (i in 0..50){ + if (i % 2 == 0){ + mailDao.insert(Mail(message = "Выложил новые страницы", userId = 1)) + } + else{ + mailDao.insert(Mail(message = "Меня отменили в Твиттере", userId = 2)) + } + } + /*mailDao.insert(Mail(message = "Выложил новые страницы", userId = 1)) + mailDao.insert(Mail(message = "Меня отменили в Твиттере", userId = 2))*/ } } diff --git a/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt b/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt index b76a50a..c2221aa 100644 --- a/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt +++ b/app/src/main/java/com/example/mobileapp/database/dao/UserDao.kt @@ -15,7 +15,7 @@ interface UserDao { fun getAll(): Flow> @Query("select * from users where users.id = :id") - suspend fun getById(id: Int): User? + fun getById(id: Int): Flow @Query("select * from users where users.login = :login") suspend fun getByLogin(login: String): User? diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/OfflineUserRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineUserRepository.kt index c32ffb3..add8f4d 100644 --- a/app/src/main/java/com/example/mobileapp/database/repositories/OfflineUserRepository.kt +++ b/app/src/main/java/com/example/mobileapp/database/repositories/OfflineUserRepository.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow class OfflineUserRepository(private val userDao: UserDao): UserRepository { override fun getAllUsers(): Flow> = userDao.getAll() - override suspend fun getUser(id: Int): User? = userDao.getById(id) + override fun getUser(id: Int): Flow = userDao.getById(id) override suspend fun getUserByLogin(login: String): User? = userDao.getByLogin(login) diff --git a/app/src/main/java/com/example/mobileapp/database/repositories/UserRepository.kt b/app/src/main/java/com/example/mobileapp/database/repositories/UserRepository.kt index 3be70c9..1c75ef0 100644 --- a/app/src/main/java/com/example/mobileapp/database/repositories/UserRepository.kt +++ b/app/src/main/java/com/example/mobileapp/database/repositories/UserRepository.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.Flow interface UserRepository { fun getAllUsers(): Flow> - suspend fun getUser(id: Int): User? + fun getUser(id: Int): Flow suspend fun getUserByLogin(login: String): User? diff --git a/app/src/main/java/com/example/mobileapp/database/viewmodels/UserViewModel.kt b/app/src/main/java/com/example/mobileapp/database/viewmodels/UserViewModel.kt index 5f68916..bfa2156 100644 --- a/app/src/main/java/com/example/mobileapp/database/viewmodels/UserViewModel.kt +++ b/app/src/main/java/com/example/mobileapp/database/viewmodels/UserViewModel.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.launch class UserViewModel(private val userRepository: UserRepository): ViewModel() { val getAllUsers = userRepository.getAllUsers() - suspend fun getUser(id: Int): User? = userRepository.getUser(id) + fun getUser(id: Int): Flow = userRepository.getUser(id) fun updateUser(user: User) = viewModelScope.launch { if (user.login.isEmpty()){ diff --git a/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt b/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt index c125c0b..7244ba5 100644 --- a/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt +++ b/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt @@ -76,12 +76,19 @@ fun EditStoryScreen(navController: NavHostController, storyId: Int? = null, } } - storyId?.let{ - val story by storyViewModel.getStoryById(storyId).collectAsState(null) - story?.let { - cover.value = it.cover - title.value = it.title - description.value = it.description + LaunchedEffect(Unit) { + storyId?.let { + storyViewModel.getStoryById(storyId).collect { + if (it != null) { + cover.value = it.cover + } + if (it != null) { + title.value = it.title + } + if (it != null) { + description.value = it.description + } + } } } diff --git a/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt b/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt index dc2ff65..f427503 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt @@ -54,7 +54,7 @@ fun ListMailScreen(navController: NavHostController, ) { index: Int -> val mail: Mail? = mails[index] if (mail != null) { - MailListItem(item = mail) + MailListItem(item = mail, navController = navController) } } } diff --git a/app/src/main/java/com/example/mobileapp/screens/MainScreen.kt b/app/src/main/java/com/example/mobileapp/screens/MainScreen.kt index b28dbd8..9270926 100644 --- a/app/src/main/java/com/example/mobileapp/screens/MainScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/MainScreen.kt @@ -12,6 +12,8 @@ import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -39,11 +41,16 @@ fun MainScreen(navController: NavHostController, factory = MobileAppViewModelProvider.Factory )) { val stories = storyViewModel.getAllStories.collectAsLazyPagingItems() + + val search = remember { mutableStateOf("") } + Column( modifier = Modifier .fillMaxSize() ) { - SearchInputField() + SearchInputField(onTextChanged = {newsearch -> + search.value = newsearch + }) if (stories.itemCount > 0){ LazyVerticalGrid( columns = GridCells.Fixed(1) @@ -53,7 +60,7 @@ fun MainScreen(navController: NavHostController, key = stories.itemKey { item -> item.id!! } ) { index: Int -> val story: Story? = stories[index] - if (story != null) { + if (story != null && (search.value.isEmpty() || story.title.contains(search.value, ignoreCase = true))) { StoryListItem(item = story, navController = navController, isReadOnly = true) } } diff --git a/app/src/main/java/com/example/mobileapp/screens/ViewScreens.kt b/app/src/main/java/com/example/mobileapp/screens/ViewScreens.kt new file mode 100644 index 0000000..92a1d78 --- /dev/null +++ b/app/src/main/java/com/example/mobileapp/screens/ViewScreens.kt @@ -0,0 +1,163 @@ +package com.example.mobileapp.screens + +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavHostController +import com.example.mobileapp.R +import com.example.mobileapp.components.NavigationButton +import com.example.mobileapp.database.viewmodels.MailViewModel +import com.example.mobileapp.database.viewmodels.MobileAppViewModelProvider +import com.example.mobileapp.database.viewmodels.StoryViewModel +import com.example.mobileapp.database.viewmodels.UserViewModel +import com.example.mobileapp.ui.theme.ButtonColor2 +import java.text.SimpleDateFormat +import java.util.Date + +val dateFormat = SimpleDateFormat("dd.MM.yyyy") + +@Composable +fun StoryViewScreen(navController: NavHostController, storyId: Int, + storyViewModel: StoryViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { + val context = LocalContext.current + + val cover = remember { mutableStateOf(BitmapFactory.decodeResource(context.resources, R.drawable.editplaceholder)) } + val title = remember { mutableStateOf("") } + val description = remember { mutableStateOf("") } + val postdate = remember { mutableStateOf(0) } + + val story by storyViewModel.getStoryById(storyId).collectAsState(null) + story?.let { + cover.value = it.cover + title.value = it.title + description.value = it.description + postdate.value = it.postdate!! + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 8.dp), + verticalArrangement = Arrangement.Center + ) { + Image( + bitmap = cover.value.asImageBitmap(), + contentDescription = "cover", + contentScale = ContentScale.Crop, + modifier = Modifier + .size(512.dp) + .padding(8.dp) + .align(Alignment.CenterHorizontally)) + Text(text = "Название: ${title.value}", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .padding(8.dp)) + Text(text = "Дата публикации: ${dateFormat.format(Date(postdate.value))}", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .padding(8.dp)) + Text(text = "Описание: ${description.value}", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .padding(8.dp)) + NavigationButton(navController = navController, destination = "main", label = "Назад", + backgroundColor = ButtonColor2, textColor = Color.White) + } +} + +@Composable +fun MailViewScreen(navController: NavHostController, mailId: Int, + mailViewModel: MailViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + ), + userViewModel: UserViewModel = viewModel( + factory = MobileAppViewModelProvider.Factory + )) { + val context = LocalContext.current + + val userId = remember { mutableStateOf(0) } + val userName = remember { mutableStateOf("") } + val photo = remember { mutableStateOf(BitmapFactory.decodeResource(context.resources, R.drawable.photoplaceholder)) } + val message = remember { mutableStateOf("") } + val postdate = remember { mutableStateOf(0) } + + val mail by mailViewModel.getMail(mailId).collectAsState(null) + mail?.let { + userId.value = it.userId + message.value = it.message + postdate.value = it.postdate!! + val user by userViewModel.getUser(userId.value).collectAsState(null) + user?.let {data -> + photo.value = data.photo!! + userName.value = data.login + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 8.dp), + verticalArrangement = Arrangement.Center + ) { + Image( + bitmap = photo.value.asImageBitmap(), + contentDescription = "editplaceholder", + contentScale = ContentScale.Crop, + modifier = Modifier + .padding(8.dp) + .clip(CircleShape) + .size(384.dp) + .border( + width = 2.dp, + color = MaterialTheme.colorScheme.onPrimary, + ) + .align(Alignment.CenterHorizontally)) + Text(text = "Автор: ${userName.value}", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .padding(8.dp)) + Text(text = "Дата публикации: ${dateFormat.format(Date(postdate.value))}", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .padding(8.dp)) + Text(text = "Текст: ${message.value}", + fontSize = 20.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier + .padding(8.dp)) + NavigationButton(navController = navController, destination = "mail", label = "Назад", + backgroundColor = ButtonColor2, textColor = Color.White) + } +} \ No newline at end of file