diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index b268ef3..600b76c 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -5,6 +5,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/MainActivity.kt b/app/src/main/java/ru/megboyzz/lks/profile/MainActivity.kt
index 25a849e..9113a1f 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/MainActivity.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/MainActivity.kt
@@ -6,13 +6,21 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.Navigator
+import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
import dagger.hilt.android.AndroidEntryPoint
+import ru.megboyzz.lks.profile.ui.components.MainNavigator
+import ru.megboyzz.lks.profile.ui.screens.SearchScreen
import ru.megboyzz.lks.profile.ui.screens.SignInScreen
import ru.megboyzz.lks.profile.ui.theme.MainTheme
@@ -21,8 +29,9 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
+
setContent {
- Navigator(SignInScreen())
+ MainNavigator(SearchScreen())
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/data/di/DataModule.kt b/app/src/main/java/ru/megboyzz/lks/profile/data/di/DataModule.kt
index 47aef50..72fc539 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/data/di/DataModule.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/data/di/DataModule.kt
@@ -31,8 +31,8 @@ class DataModule {
fun providesDefaultCookies() = mapOf(
"PHPSESSID" to "deleted",
"BITRIX_SM_SOUND_LOGIN_PLAYED" to "Y",
- "BITRIX_SM_UIDH" to "00000000000000000000000000000000",
- "BITRIX_SM_UIDL" to "ivachev.a.a%40edu.mirea.ru"
+ "BITRIX_SM_UIDH" to "22f459c5c83cff9cd62c99693b00c361",
+ "BITRIX_SM_UIDL" to "kits.m.a%40edu.mirea.ru"
)
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/HiltModule.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/HiltModule.kt
index dadf8e7..5d08af2 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/ui/HiltModule.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/HiltModule.kt
@@ -9,7 +9,9 @@ import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.multibindings.IntoMap
+import ru.megboyzz.lks.profile.ui.model.SearchScreenModel
import ru.megboyzz.lks.profile.ui.model.SignInScreenModel
+import javax.inject.Qualifier
@Module
@InstallIn(ActivityComponent::class)
@@ -22,6 +24,9 @@ interface HiltModule {
signInScreenModel: SignInScreenModel
) : ScreenModel*/
+ @Qualifier
+ annotation class MyFactory
+
@Binds
@IntoMap
@ScreenModelFactoryKey(SignInScreenModel.Factory::class)
@@ -29,4 +34,11 @@ interface HiltModule {
factory: SignInScreenModel.Factory
): ScreenModelFactory
+ @Binds
+ @IntoMap
+ @ScreenModelKey(SearchScreenModel::class)
+ fun bindSearchScreenModelFactory(
+ factory: SearchScreenModel
+ ): ScreenModel
+
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/Util.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/Util.kt
new file mode 100644
index 0000000..fe065c3
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/Util.kt
@@ -0,0 +1,20 @@
+package ru.megboyzz.lks.profile.ui
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.material.ripple.rememberRipple
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import kotlin.concurrent.thread
+
+@Composable
+fun Modifier.clickableWithNormalRipple(onClick: () -> Unit) = this.clickable(
+ interactionSource = remember { MutableInteractionSource() },
+ indication = rememberRipple(bounded = true),
+ onClick = onClick
+)
+
+@Composable
+fun Int.asPainter() = painterResource(this)
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/components/MainNavigator.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/components/MainNavigator.kt
new file mode 100644
index 0000000..983bf38
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/components/MainNavigator.kt
@@ -0,0 +1,20 @@
+package ru.megboyzz.lks.profile.ui.components
+
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import cafe.adriel.voyager.core.screen.Screen
+import cafe.adriel.voyager.navigator.Navigator
+import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
+import ru.megboyzz.lks.profile.ui.screens.SearchScreen
+
+@Composable
+fun MainNavigator(screen: Screen) {
+ BottomSheetNavigator(
+ sheetShape = RoundedCornerShape(12.dp)
+ ) {
+
+ Navigator(screen)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/components/SearchBottomComponents.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/components/SearchBottomComponents.kt
new file mode 100644
index 0000000..abead6b
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/components/SearchBottomComponents.kt
@@ -0,0 +1,346 @@
+package ru.megboyzz.lks.profile.ui.components
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
+import androidx.compose.material.icons.filled.KeyboardArrowDown
+import androidx.compose.material.icons.filled.KeyboardArrowRight
+import androidx.compose.material.icons.filled.KeyboardArrowUp
+import androidx.compose.material3.Button
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.OutlinedTextFieldDefaults
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextFieldDefaults
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.layout.onSizeChanged
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import cafe.adriel.voyager.navigator.bottomSheet.LocalBottomSheetNavigator
+import ru.megboyzz.lks.profile.R
+import ru.megboyzz.lks.profile.domain.entities.LksRequest
+import ru.megboyzz.lks.profile.domain.entities.LksStudent
+import ru.megboyzz.lks.profile.domain.entities.Student
+import ru.megboyzz.lks.profile.ui.asPainter
+import ru.megboyzz.lks.profile.ui.clickableWithNormalRipple
+
+@Composable
+fun ContextMenuContainer(
+ content: @Composable ColumnScope.() -> Unit
+) {
+
+ Column(
+ modifier = Modifier
+ .padding(4.dp)
+ .fillMaxWidth()
+ .navigationBarsPadding(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+
+ Box(
+ modifier = Modifier
+ .size(32.dp, 4.dp)
+ .clip(RoundedCornerShape(80))
+ .background(MaterialTheme.colorScheme.onBackground)
+ )
+ Spacer(Modifier.height(16.dp))
+ Column (
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 12.dp)
+ .padding(bottom = 12.dp),
+ content = content
+ )
+
+
+ }
+
+}
+
+@Preview
+@Composable
+private fun ContextMenuContainerPrev() {
+
+ ContextMenuContainer {
+
+ Text("Hello!")
+ Text("Hello!")
+
+ }
+
+}
+
+@Composable
+fun SearchTextField(
+ value: String,
+ onValueChange: (String) -> Unit,
+ suggestions: List? = null,
+ label: String? = null
+) {
+
+ var expanded by remember { mutableStateOf(false) }
+
+ var dropDownWidth by remember { mutableIntStateOf(0) }
+
+ val icon = if (expanded)
+ Icons.Filled.KeyboardArrowUp
+ else
+ Icons.Filled.KeyboardArrowDown
+
+
+ Column() {
+ OutlinedTextField(
+ value = value,
+ onValueChange = onValueChange,
+ modifier = Modifier
+ .fillMaxWidth()
+ .onSizeChanged { dropDownWidth = it.width },
+ label = { Text(label ?: "Label") },
+ trailingIcon = {
+ if(suggestions != null)
+ Icon(
+ icon,
+ "contentDescription",
+ Modifier.clickableWithNormalRipple{ expanded = !expanded }
+ )
+ }
+ )
+ DropdownMenu(
+ expanded = expanded,
+ onDismissRequest = { expanded = false },
+ modifier = Modifier
+ .width(with(LocalDensity.current){dropDownWidth.toDp()})
+ ) {
+ suggestions?.forEach { label ->
+ DropdownMenuItem(
+ onClick = { onValueChange(label) },
+ text = { Text(text = label) }
+ )
+ }
+ }
+ }
+
+}
+
+@Preview
+@Composable
+fun SearchTextFieldPrev() {
+
+ val suggestions = listOf("Item1","Item2","Item3")
+ var value by remember { mutableStateOf("") }
+
+ SearchTextField(
+ value = value,
+ onValueChange = { value = it },
+ suggestions = suggestions
+ )
+
+}
+
+@Composable
+fun SearchContextMenu(
+ onSearch: (LksRequest) -> Unit
+) {
+
+ val bottomSheetNavigator = LocalBottomSheetNavigator.current
+
+ var name by remember { mutableStateOf("") }
+ var surname by remember { mutableStateOf("") }
+ var family by remember { mutableStateOf("") }
+
+ var group by remember { mutableStateOf("") }
+ var departamnet by remember { mutableStateOf("") }
+
+ ContextMenuContainer {
+
+ Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
+
+ SearchTextField(
+ value = family,
+ onValueChange = {family = it},
+ label = "Фамилия"
+ )
+
+ SearchTextField(
+ value = name,
+ onValueChange = {name = it},
+ label = "Имя"
+ )
+
+ SearchTextField(
+ value = surname,
+ onValueChange = {surname = it},
+ label = "Отчество"
+ )
+
+ Spacer(Modifier.height(1.dp))
+ HorizontalDivider(color = MaterialTheme.colorScheme.onBackground)
+
+ SearchTextField(
+ value = group,
+ onValueChange = {group = it},
+ label = "Учебная группа"
+ )
+
+ SearchTextField(
+ value = departamnet,
+ onValueChange = { departamnet = it },
+ label = "Подразделение"
+ )
+
+ Button(
+ shape = OutlinedTextFieldDefaults.shape,
+ modifier = Modifier.fillMaxWidth(),
+ onClick = {
+ val lksRequest = LksRequest(
+ student = Student(
+ name = name,
+ surname = family,
+ patronymic = surname
+ ),
+ group = group,
+ department = departamnet
+ )
+ onSearch(lksRequest)
+ bottomSheetNavigator?.hide()
+ }
+ ) {
+ Text("Поиск")
+ }
+
+ }
+
+ }
+
+}
+
+@Preview
+@Composable
+private fun SearchContextMenuPrev() {
+
+ SearchContextMenu {
+
+ }
+
+}
+
+@Composable
+fun ContextMenuButton(
+ icon: Painter,
+ label: String,
+ onClick: () -> Unit
+) {
+
+ Box(
+ modifier = Modifier
+ .padding(8.dp)
+ .clickableWithNormalRipple(onClick)
+ ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Icon(
+ painter = icon,
+ contentDescription = null
+ )
+ Text(text = label)
+ }
+
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
+ contentDescription = null
+ )
+
+ }
+
+ }
+
+}
+
+@Preview
+@Composable
+fun ContextMenuButtonPrev() {
+
+ ContextMenuButton(
+ icon = R.drawable.vk_ic.asPainter(),
+ label = "Переидти в VK",
+ onClick = {}
+ )
+
+}
+
+@Composable
+fun LongPressCardContextMenu(
+ lksStudent: LksStudent,
+ onClick: () -> Unit
+) {
+ ContextMenuContainer {
+ Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
+
+ Text(
+ "${lksStudent.studentFullName} ${lksStudent.group}"
+ )
+ HorizontalDivider(color = MaterialTheme.colorScheme.onBackground)
+ ContextMenuButton(
+ icon = R.drawable.vk_ic.asPainter(),
+ label = "Переидти в VK",
+ onClick = onClick
+ )
+ }
+ }
+}
+
+@Preview
+@Composable
+private fun LongPressCardContextMenuPrev() {
+
+ val lksStudent = LksStudent(
+ studentFullName = "Киц Михаил Андреевич",
+ group = "ИКБО-03-20"
+ )
+
+ LongPressCardContextMenu(
+ lksStudent = lksStudent,
+ onClick = {}
+ )
+
+
+}
+
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/components/SearchComponents.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/components/SearchComponents.kt
index a058271..bf9a6ba 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/ui/components/SearchComponents.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/components/SearchComponents.kt
@@ -1,14 +1,166 @@
package ru.megboyzz.lks.profile.ui.components
import android.provider.ContactsContract.Profile
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Search
+import androidx.compose.material.ripple.rememberRipple
+import androidx.compose.material3.Divider
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.FloatingActionButton
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import ru.megboyzz.lks.profile.MainActivity
import ru.megboyzz.lks.profile.domain.entities.LksResponse
import ru.megboyzz.lks.profile.domain.entities.LksStudent
+import ru.megboyzz.lks.profile.ui.clickableWithNormalRipple
+import ru.megboyzz.lks.profile.ui.theme.MainTheme
@Composable
-fun ProfileCard(lksStudent: LksStudent) {
+fun ProfileCard(
+ lksStudent: LksStudent,
+ onLongPress: () -> Unit
+) {
+
+ var toggled by remember { mutableStateOf(false) }
+
+ Box(
+ modifier = Modifier
+ .border(
+ border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary),
+ shape = RoundedCornerShape(16.dp)
+ )
+ .defaultMinSize(minWidth = 240.dp)
+ .clickableWithNormalRipple { toggled =! toggled },
+ contentAlignment = Alignment.Center
+ ) {
+ Column(
+ modifier = Modifier.fillMaxWidth().padding(12.dp),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ Text(
+ text = lksStudent.studentFullName ?: "<Нет имени>"
+ )
+ Text(
+ text = lksStudent.group ?: "<Нет группы>"
+ )
+ AnimatedVisibility(toggled) {
+
+ Column(
+ modifier = Modifier.padding(top = 4.dp).fillMaxWidth(),
+ verticalArrangement = Arrangement.spacedBy(12.dp),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ HorizontalDivider(
+ modifier = Modifier.fillMaxWidth(),
+ color = MaterialTheme.colorScheme.primary
+ )
+ Text(
+ text = lksStudent.department ?: "<Нет подразделения>"
+ )
+ }
+ }
+ }
+ }
+
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun MainScaffold(
+ onFloatingButtonClick: () -> Unit,
+ content: @Composable (PaddingValues) -> Unit
+) {
+
+ Scaffold(
+ topBar = {
+ Surface(shadowElevation = 8.dp) {
+ TopAppBar(
+ title = { Text("LKS Search") }
+ )
+ }
+ },
+ floatingActionButton = {
+ FloatingActionButton(onFloatingButtonClick) {
+ Icon(
+ imageVector = Icons.Default.Search,
+ contentDescription = null
+ )
+ }
+ },
+ content = content
+ )
+
+}
+
+@Preview
+@Composable
+private fun ProfileCardPrev() {
+
+ val student = LksStudent(
+ studentFullName = "Киц Михаил Андреевич",
+ department = "ИИТ",
+ group = "ИКБО-03-20"
+ )
+
+ ProfileCard(
+ lksStudent = student
+ ) { }
+
+}
+
+@Preview
+@Composable
+private fun Main() {
+
+ val student = LksStudent(
+ studentFullName = "Киц Михаил Андреевич",
+ department = "ИИТ",
+ group = "ИКБО-03-20"
+ )
+
+ MainTheme {
+ MainScaffold(
+ onFloatingButtonClick = {}
+ ) {
+ Column(modifier = Modifier.padding(it)) {
+ ProfileCard(
+ lksStudent = student
+ ) { }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/model/SearchScreenModel.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/model/SearchScreenModel.kt
index 63a46a6..e0b6a6e 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/ui/model/SearchScreenModel.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/model/SearchScreenModel.kt
@@ -2,14 +2,19 @@ package ru.megboyzz.lks.profile.ui.model
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
+import cafe.adriel.voyager.hilt.ScreenModelFactory
+import cafe.adriel.voyager.navigator.Navigator
+import dagger.assisted.AssistedFactory
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import ru.megboyzz.lks.profile.domain.DefaultCookies
import ru.megboyzz.lks.profile.domain.entities.LksRequest
import ru.megboyzz.lks.profile.domain.entities.LksResponse
import ru.megboyzz.lks.profile.domain.repositories.LksRepository
+import ru.megboyzz.lks.profile.ui.HiltModule.MyFactory
import javax.inject.Inject
class SearchScreenModel @Inject constructor(
@@ -27,30 +32,49 @@ class SearchScreenModel @Inject constructor(
private val _responseList = MutableStateFlow(LksResponse())
val responseList = _responseList.asStateFlow()
+ sealed class UiState(val status: String? = null) {
+ data object Loading: UiState()
+ //data object Success: SignInState("Успешный вход")
+ data class Error(val _status: String) : UiState(_status)
+ data object Idle: UiState()
+ }
+
+ val state = MutableStateFlow(UiState.Idle)
+
init {
- _curPageNumber.onEach {
+ /* _curPageNumber.onEach {
update()
- }
+ }*/
+
+ _request.onEach {
+ update()
+ }.launchIn(screenModelScope)
+
}
fun nextPage() = screenModelScope.launch { _curPageNumber.emit(_curPageNumber.value++) }
private fun update() = screenModelScope.launch {
+ state.emit(UiState.Loading)
+
val result = lksRepository.getPage(_request.value, cookies, curPageNumber.value)
+ if(result.isFailure) {
+ state.emit(UiState.Error("Ошибка :-("))
+ return@launch
+ }
+
val list = result.getOrElse { LksResponse() }
_responseList.emit(list)
+
+ state.emit(UiState.Idle)
}
- fun newSearch() = screenModelScope.launch {
-
- _curPageNumber.emit(1)
- update()
-
+ fun newSearch(request: LksRequest) = screenModelScope.launch {
+ _request.emit(request)
}
-
}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/SearchScreen.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/SearchScreen.kt
index 6037b43..d809b1a 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/SearchScreen.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/SearchScreen.kt
@@ -1,44 +1,58 @@
package ru.megboyzz.lks.profile.ui.screens
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.material3.OutlinedButton
-import androidx.compose.material3.OutlinedTextField
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
import androidx.compose.ui.input.pointer.PointerIcon.Companion.Text
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.hilt.getScreenModel
-import cafe.adriel.voyager.navigator.LocalNavigator
+import cafe.adriel.voyager.navigator.bottomSheet.LocalBottomSheetNavigator
+import ru.megboyzz.lks.profile.ui.components.MainScaffold
+import ru.megboyzz.lks.profile.ui.components.ProfileCard
import ru.megboyzz.lks.profile.ui.model.SearchScreenModel
+import ru.megboyzz.lks.profile.ui.screens.sub.LongPressMenu
+import ru.megboyzz.lks.profile.ui.screens.sub.SearchBottomScreen
class SearchScreen : Screen {
@Composable
override fun Content() {
+ val bottomSheetNavigator = LocalBottomSheetNavigator.current
+
val screenModel = getScreenModel()
- Box(
- modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.TopCenter
+ val state by screenModel.state.collectAsState()
+
+ val list by screenModel.responseList.collectAsState()
+
+ MainScaffold(
+ onFloatingButtonClick = { bottomSheetNavigator.show(SearchBottomScreen()) }
) {
- Column(
- verticalArrangement = Arrangement.spacedBy(16.dp)
+
+ LazyColumn(
+ contentPadding = PaddingValues(8.dp)
) {
- Spacer(Modifier.height(20.dp))
- val navigator = LocalNavigator.current!!
-
-
-
-
+ item {
+ when(state) {
+ is SearchScreenModel.UiState.Loading -> CircularProgressIndicator()
+ is SearchScreenModel.UiState.Error -> Text(state.status ?: "Ошибка")
+ SearchScreenModel.UiState.Idle -> {}
+ }
+ }
+ items(list.students) {
+ ProfileCard(
+ lksStudent = it,
+ onLongPress = { bottomSheetNavigator.show(LongPressMenu(it)) }
+ )
+ }
}
+
}
}
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/sub/LongPressMenu.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/sub/LongPressMenu.kt
new file mode 100644
index 0000000..a461ca0
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/sub/LongPressMenu.kt
@@ -0,0 +1,25 @@
+package ru.megboyzz.lks.profile.ui.screens.sub
+
+import android.widget.Toast
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import cafe.adriel.voyager.core.screen.Screen
+import ru.megboyzz.lks.profile.domain.entities.LksStudent
+import ru.megboyzz.lks.profile.ui.components.LongPressCardContextMenu
+
+class LongPressMenu(private val lksStudent: LksStudent) : Screen {
+
+ @Composable
+ override fun Content() {
+
+ val context = LocalContext.current
+
+ LongPressCardContextMenu(
+ lksStudent = lksStudent
+ ) {
+ Toast.makeText(context, "Переход на VK", Toast.LENGTH_SHORT).show()
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/sub/SearchBottomScreen.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/sub/SearchBottomScreen.kt
new file mode 100644
index 0000000..2bb3d47
--- /dev/null
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/screens/sub/SearchBottomScreen.kt
@@ -0,0 +1,19 @@
+package ru.megboyzz.lks.profile.ui.screens.sub
+
+import androidx.compose.runtime.Composable
+import cafe.adriel.voyager.core.screen.Screen
+import cafe.adriel.voyager.hilt.getScreenModel
+import ru.megboyzz.lks.profile.ui.components.SearchContextMenu
+import ru.megboyzz.lks.profile.ui.model.SearchScreenModel
+
+class SearchBottomScreen : Screen {
+
+ @Composable
+ override fun Content() {
+
+ val screenModel = getScreenModel()
+
+ SearchContextMenu { lksRequest -> screenModel.newSearch(lksRequest) }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Theme.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Theme.kt
index fa181e4..33aa5e3 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Theme.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Theme.kt
@@ -8,6 +8,7 @@ import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme(
@@ -19,9 +20,9 @@ private val DarkColorScheme = darkColorScheme(
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
- tertiary = Pink40
+ tertiary = Pink40,
- /* Other default colors to override
+ // Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
@@ -29,7 +30,7 @@ private val LightColorScheme = lightColorScheme(
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
- */
+
)
@Composable
diff --git a/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Type.kt b/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Type.kt
index aa54b05..4a79773 100644
--- a/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Type.kt
+++ b/app/src/main/java/ru/megboyzz/lks/profile/ui/theme/Type.kt
@@ -14,11 +14,11 @@ val Typography = Typography(
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
- )
- /* Other default text styles to override
+ ),
+ // Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
+ fontWeight = FontWeight.Medium,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
@@ -30,5 +30,4 @@ val Typography = Typography(
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
- */
)
\ No newline at end of file
diff --git a/app/src/main/res/drawable/vk_ic.xml b/app/src/main/res/drawable/vk_ic.xml
new file mode 100644
index 0000000..483c2b3
--- /dev/null
+++ b/app/src/main/res/drawable/vk_ic.xml
@@ -0,0 +1,12 @@
+
+
+
+