diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..44ca2d9 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,41 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/MainActivity.kt b/app/src/main/java/com/example/mobileapp/MainActivity.kt index 8105863..c15646a 100644 --- a/app/src/main/java/com/example/mobileapp/MainActivity.kt +++ b/app/src/main/java/com/example/mobileapp/MainActivity.kt @@ -15,15 +15,24 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.example.mobileapp.components.NavBar +import com.example.mobileapp.database.MobileAppDataBase import com.example.mobileapp.entities.Mail import com.example.mobileapp.entities.MailSingleton import com.example.mobileapp.entities.Story import com.example.mobileapp.entities.StorySingleton import com.example.mobileapp.ui.theme.MobileAppTheme +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { + val database by lazy { MobileAppDataBase.getInstance(this) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + this.deleteDatabase("mobileApp.db") + CoroutineScope(Dispatchers.IO).launch { + MobileAppDataBase.initialDataBase() + } setContent { MobileAppTheme { // A surface container using the 'background' color from the theme @@ -32,7 +41,7 @@ class MainActivity : ComponentActivity() { color = MaterialTheme.colorScheme.background ) { val navController = rememberNavController() - val mailSingleton = MailSingleton() + /*val mailSingleton = MailSingleton() mailSingleton.addMail(Mail(0, 0, "Дзюнзи Ито", "Выложил новый")) mailSingleton.addMail(Mail(1, 1, "Стивен Кинг", "Меня отменили в Твиттере")) mailSingleton.addMail(Mail(0, 0, "Дзюнзи Ито", "Выложил новый")) @@ -46,7 +55,7 @@ class MainActivity : ComponentActivity() { 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)) + storySingleton.addStory(Story(3, "Переулок", "История ужасов от Дзюнзи Ито", R.drawable.dzun))*/ NavBar(navController = navController) } 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 e0484da..3d7d456 100644 --- a/app/src/main/java/com/example/mobileapp/components/InputContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/InputContent.kt @@ -33,13 +33,14 @@ val buttonHeightStandard = 72.dp @OptIn(ExperimentalMaterial3Api::class) @Composable -fun PlaceholderInputField(label: String, isSingleLine: Boolean){ +fun PlaceholderInputField(label: String, isSingleLine: Boolean, onTextChanged: (String) -> Unit){ var text = remember { mutableStateOf("") } OutlinedTextField( value = text.value, onValueChange = { text.value = it + onTextChanged(it) }, placeholder = { Text(label) @@ -54,13 +55,14 @@ fun PlaceholderInputField(label: String, isSingleLine: Boolean){ @OptIn(ExperimentalMaterial3Api::class) @Composable -fun PasswordInputField(label: String){ +fun PasswordInputField(label: String, onPasswordChanged: (String) -> Unit){ var text = remember { mutableStateOf("") } OutlinedTextField( value = text.value, onValueChange = { text.value = it + onPasswordChanged(it) }, placeholder = { Text(label) @@ -159,7 +161,7 @@ fun ActiveButton(label: String, backgroundColor: Color, textColor: Color, onClic fun PlaceholderTextFieldPreview() { MobileAppTheme { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { - PlaceholderInputField("Email", true) + PlaceholderInputField("Email", true, { }) } } } \ No newline at end of file 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 38dfd09..41c2745 100644 --- a/app/src/main/java/com/example/mobileapp/components/ListContent.kt +++ b/app/src/main/java/com/example/mobileapp/components/ListContent.kt @@ -27,18 +27,16 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource 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.sp import androidx.navigation.NavHostController import com.example.mobileapp.R -import com.example.mobileapp.entities.Mail -import com.example.mobileapp.entities.MailSingleton -import com.example.mobileapp.entities.Story -import com.example.mobileapp.entities.StorySingleton +import com.example.mobileapp.database.entities.Mail +import com.example.mobileapp.database.entities.Story import com.example.mobileapp.ui.theme.BackgroundItem2 import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor2 @@ -92,7 +90,7 @@ fun StoryListItem(item: Story, navController: NavHostController){ Row( verticalAlignment = Alignment.Top ){ - Image(painter = painterResource(id = item.cover), + Image(bitmap = item.cover.asImageBitmap(), contentDescription = item.description, contentScale = ContentScale.Crop, modifier = Modifier @@ -117,8 +115,12 @@ fun StoryListItem(item: Story, navController: NavHostController){ modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End ){ - DataListItemButton("Изменить", ButtonColor2, Color.White, onClickAction = { navController.navigate("editstory") }) - DataListItemButton("Удалить", Color.Red, Color.White, onClickAction = { }) + DataListItemButton("Изменить", ButtonColor2, Color.White, onClickAction = { + navController.navigate("editstory/" + item.id) + }) + DataListItemButton("Удалить", Color.Red, Color.White, onClickAction = { + navController.navigate("story") + }) } } } @@ -180,7 +182,7 @@ fun MailListItem(item: Mail){ modifier = Modifier.padding(8.dp) ){ Text( - text = item.username, + text = "item.username", fontSize = 20.sp, fontWeight = FontWeight.Bold) Text(text = item.message) 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 578dc5a..eb78cc3 100644 --- a/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt +++ b/app/src/main/java/com/example/mobileapp/components/NavigationBar.kt @@ -42,7 +42,7 @@ import com.example.mobileapp.screens.SettingsScreen val navBarItems = listOf( NavBarItem(route = "main", label = "Главная", icon = R.drawable.home), - NavBarItem(route = "listdata", label = "Создание", icon = R.drawable.edit), + NavBarItem(route = "story", label = "Создание", icon = R.drawable.edit), NavBarItem(route = "mail", label = "Уведомления", icon = R.drawable.mail), NavBarItem(route = "settings", label = "Настройки", icon = R.drawable.settings), ) @@ -106,7 +106,7 @@ fun NavBar(navController: NavHostController) { MainScreen(navController = navController) bottomBarState.value = true } - composable("listdata"){ + composable("story"){ ListDataScreen(navController = navController) bottomBarState.value = true } @@ -118,12 +118,14 @@ fun NavBar(navController: NavHostController) { SettingsScreen(navController = navController) bottomBarState.value = true } - composable("editstory"){ - EditStoryScreen(navController = navController) + composable("editstory/{storyId}"){ navBackStackEntry -> + val storyId = navBackStackEntry.arguments?.getInt("storyId") + EditStoryScreen(navController = navController, storyId = storyId) bottomBarState.value = false } - composable("editmail"){ - EditMailScreen(navController = navController) + composable("editmail/{mailId}"){ navBackStackEntry -> + val mailId = navBackStackEntry.arguments?.getInt("mailId") + EditMailScreen(navController = navController, mailId = mailId) bottomBarState.value = false } } 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 f099384..f85ee95 100644 --- a/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt +++ b/app/src/main/java/com/example/mobileapp/database/MobileAppDataBase.kt @@ -1,11 +1,13 @@ 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 @@ -17,7 +19,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -@Database(entities = [User::class, Story::class, Mail::class], version = 1, exportSchema = false) +@Database(entities = [User::class, Story::class, Mail::class], version = 4) @TypeConverters(Converters::class) abstract class MobileAppDataBase : RoomDatabase() { abstract fun userDao(): UserDao @@ -30,6 +32,24 @@ abstract class MobileAppDataBase : RoomDatabase() { @Volatile private var INSTANCE: MobileAppDataBase? = null + suspend fun initialDataBase(){ + 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(null, R.drawable.dzun), userId = 1)) + storyDao.insert(Story(title = "Чужак", description = "Знаменитая книга стивена кинга", + cover = BitmapFactory.decodeResource(null, 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( @@ -41,10 +61,11 @@ abstract class MobileAppDataBase : RoomDatabase() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) CoroutineScope(Dispatchers.IO).launch { - //populateDatabase() + initialDataBase() } } }) + .fallbackToDestructiveMigration() .build() .also { INSTANCE = it } } diff --git a/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt b/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt index 261a857..d6c2358 100644 --- a/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt +++ b/app/src/main/java/com/example/mobileapp/database/dao/StoryDao.kt @@ -17,6 +17,9 @@ interface StoryDao { @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> + @Insert(onConflict = OnConflictStrategy.IGNORE) suspend fun insert(story: Story) diff --git a/app/src/main/java/com/example/mobileapp/database/entities/Converters.kt b/app/src/main/java/com/example/mobileapp/database/entities/Converters.kt index a95d5cd..90ea52b 100644 --- a/app/src/main/java/com/example/mobileapp/database/entities/Converters.kt +++ b/app/src/main/java/com/example/mobileapp/database/entities/Converters.kt @@ -4,6 +4,8 @@ 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 diff --git a/app/src/main/java/com/example/mobileapp/database/entities/Mail.kt b/app/src/main/java/com/example/mobileapp/database/entities/Mail.kt index 32b03b1..2b489f0 100644 --- a/app/src/main/java/com/example/mobileapp/database/entities/Mail.kt +++ b/app/src/main/java/com/example/mobileapp/database/entities/Mail.kt @@ -4,6 +4,8 @@ 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 = "mails", @@ -22,6 +24,8 @@ data class Mail( var id: Int? = null, @ColumnInfo(name = "message") val message: String, + @ColumnInfo(name = "postdate") + val postdate: Long? = Date().time, @ColumnInfo(name="user_id") val userId: Int ){ diff --git a/app/src/main/java/com/example/mobileapp/database/entities/Story.kt b/app/src/main/java/com/example/mobileapp/database/entities/Story.kt index bdd8431..e63e256 100644 --- a/app/src/main/java/com/example/mobileapp/database/entities/Story.kt +++ b/app/src/main/java/com/example/mobileapp/database/entities/Story.kt @@ -5,6 +5,8 @@ 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", @@ -27,6 +29,8 @@ data class Story( val description: String, @ColumnInfo(name = "cover") val cover: Bitmap, + @ColumnInfo(name = "postdate") + val postdate: Long? = Date().time, @ColumnInfo(name="user_id") val userId: Int ){ diff --git a/app/src/main/java/com/example/mobileapp/screens/Authorization.kt b/app/src/main/java/com/example/mobileapp/screens/Authorization.kt index dd91b1e..f047a6a 100644 --- a/app/src/main/java/com/example/mobileapp/screens/Authorization.kt +++ b/app/src/main/java/com/example/mobileapp/screens/Authorization.kt @@ -37,8 +37,8 @@ fun Authorization(navController: NavHostController){ .size(512.dp) .padding(8.dp) .align(Alignment.CenterHorizontally)) - PlaceholderInputField(label = "Логин", true) - PasswordInputField(label = "Пароль") + PlaceholderInputField(label = "Логин", true, onTextChanged = {}) + PasswordInputField(label = "Пароль", onPasswordChanged = {}) NavigationButton(navController = navController, destination = "main", label = "Вход", backgroundColor = ButtonColor2, textColor = Color.White) NavigationButton(navController = navController, destination = "registration", label = "Регистрация", 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 8c5d4a5..b477854 100644 --- a/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt +++ b/app/src/main/java/com/example/mobileapp/screens/EditScreens.kt @@ -7,10 +7,15 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size 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.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController @@ -19,11 +24,26 @@ import com.example.mobileapp.components.ActiveButton import com.example.mobileapp.components.NavigationButton import com.example.mobileapp.components.PasswordInputField import com.example.mobileapp.components.PlaceholderInputField +import com.example.mobileapp.database.MobileAppDataBase +import com.example.mobileapp.database.entities.Story import com.example.mobileapp.ui.theme.ButtonColor1 import com.example.mobileapp.ui.theme.ButtonColor2 +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext @Composable -fun EditStoryScreen(navController: NavHostController) { +fun EditStoryScreen(navController: NavHostController, storyId: Int? = null) { + val context = LocalContext.current + val story = remember { mutableStateOf(null) } + + storyId?.let{ + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + story.value = MobileAppDataBase.getInstance(context).storyDao().getById(storyId!!) + } + } + } + Column( modifier = Modifier .fillMaxSize() @@ -38,17 +58,21 @@ fun EditStoryScreen(navController: NavHostController) { .size(384.dp) .padding(8.dp) .align(Alignment.CenterHorizontally)) - PlaceholderInputField(label = "Название", true) ActiveButton(label = "Выбрать обложку", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {}) - PlaceholderInputField(label = "Описание", true) + PlaceholderInputField(label = "Название", true, onTextChanged = { newName -> + + }) + PlaceholderInputField(label = "Описание", true, onTextChanged = { newDescription -> + + }) ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {}) - NavigationButton(navController = navController, destination = "listdata", label = "Назад", + NavigationButton(navController = navController, destination = "story", label = "Назад", backgroundColor = ButtonColor2, textColor = Color.White) } } @Composable -fun EditMailScreen(navController: NavHostController) { +fun EditMailScreen(navController: NavHostController, mailId: Int? = null) { Column( modifier = Modifier .fillMaxSize() @@ -63,7 +87,7 @@ fun EditMailScreen(navController: NavHostController) { .size(512.dp) .padding(8.dp) .align(Alignment.CenterHorizontally)) - PlaceholderInputField(label = "Текс поста", false) + PlaceholderInputField(label = "Текс поста", false, onTextChanged = {}) ActiveButton(label = "Сохранить", backgroundColor = ButtonColor1, textColor = Color.Black, onClickAction = {}) NavigationButton(navController = navController, destination = "mail", label = "Назад", backgroundColor = ButtonColor2, textColor = Color.White) diff --git a/app/src/main/java/com/example/mobileapp/screens/ListDataScreen.kt b/app/src/main/java/com/example/mobileapp/screens/ListDataScreen.kt index 4df9465..f588285 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ListDataScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ListDataScreen.kt @@ -8,22 +8,42 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth 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.platform.LocalContext import androidx.navigation.NavHostController import com.example.mobileapp.components.DataListScroll import com.example.mobileapp.components.NavBar +import com.example.mobileapp.database.MobileAppDataBase +import com.example.mobileapp.database.entities.Story import com.example.mobileapp.entities.StorySingleton import com.example.mobileapp.ui.theme.BackgroundItem1 import com.example.mobileapp.ui.theme.BackgroundItem2 +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext @Composable fun ListDataScreen(navController: NavHostController){ - val storySingleton = StorySingleton() + + val context = LocalContext.current + val stories = remember { mutableStateListOf() } + + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + MobileAppDataBase.getInstance(context).storyDao().getAll().collect { data -> + stories.clear() + stories.addAll(data) + } + } + } + Column( modifier = Modifier .fillMaxSize() .background(BackgroundItem1) ) { - DataListScroll(navController, storySingleton.getStoryList()) + DataListScroll(navController, stories) } } \ No newline at end of file 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 e8df385..10e279a 100644 --- a/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt +++ b/app/src/main/java/com/example/mobileapp/screens/ListMailScreen.kt @@ -4,20 +4,39 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize 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.platform.LocalContext import androidx.navigation.NavHostController import com.example.mobileapp.components.DataListScroll -import com.example.mobileapp.entities.MailSingleton +import com.example.mobileapp.database.MobileAppDataBase +import com.example.mobileapp.database.entities.Mail import com.example.mobileapp.ui.theme.BackgroundItem1 +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext @Composable fun ListMailScreen(navController: NavHostController){ - val mailSingleton = MailSingleton() + + val context = LocalContext.current + val mails = remember { mutableStateListOf() } + + LaunchedEffect(Unit) { + withContext(Dispatchers.IO) { + MobileAppDataBase.getInstance(context).mailDao().getAll().collect { data -> + mails.clear() + mails.addAll(data) + } + } + } + Column( modifier = Modifier .fillMaxSize() .background(BackgroundItem1) ) { - DataListScroll(navController, mailSingleton.getMailList()) + DataListScroll(navController, mails) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/mobileapp/screens/Registration.kt b/app/src/main/java/com/example/mobileapp/screens/Registration.kt index 7817eb4..7fb0552 100644 --- a/app/src/main/java/com/example/mobileapp/screens/Registration.kt +++ b/app/src/main/java/com/example/mobileapp/screens/Registration.kt @@ -37,10 +37,10 @@ fun Registration(navController: NavHostController){ .size(384.dp) .padding(8.dp) .align(Alignment.CenterHorizontally)) - PlaceholderInputField(label = "Логин", true) - PlaceholderInputField(label = "Email", true) - PasswordInputField(label = "Пароль") - PasswordInputField(label = "Пароль ещё раз") + PlaceholderInputField(label = "Логин", true, onTextChanged = {}) + PlaceholderInputField(label = "Email", true, onTextChanged = {}) + PasswordInputField(label = "Пароль", onPasswordChanged = {}) + PasswordInputField(label = "Пароль ещё раз", onPasswordChanged = {}) NavigationButton(navController = navController, destination = "main", label = "Зарегистрироваться", backgroundColor = ButtonColor2, textColor = Color.White) NavigationButton(navController = navController, destination = "authorization",