Merge remote-tracking branch 'origin/main'
# Conflicts: # app/src/main/java/ru/myitschool/work/ui/screen/meetings/MeetingsViewModel.kt
This commit is contained in:
commit
311cab5b43
@ -1,10 +1,9 @@
|
|||||||
package ru.myitschool.work.core
|
package ru.myitschool.work.core
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
const val HOST = "http://10.0.0.14:49182" // "http://10.0.0.14:49182" or "http://10.0.2.2:8080"
|
const val HOST = "http://10.0.0.172:49182" // "http://10.0.0.14:49182" or "http://10.0.2.2:8080"
|
||||||
const val AUTH_URL = "/auth"
|
const val AUTH_URL = "/auth"
|
||||||
const val INFO_URL = "/info"
|
const val INFO_URL = "/info"
|
||||||
const val BOOKING_URL = "/booking"
|
const val BOOKING_URL = "/booking"
|
||||||
const val BOOK_URL = "/book"
|
const val BOOK_URL = "/book"
|
||||||
const val GET_TOKEN = "/getToken"
|
|
||||||
}
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package ru.myitschool.work.data.repo
|
package ru.myitschool.work.data.repo
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
@ -25,6 +26,10 @@ object AuthRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Из памяти
|
||||||
|
*/
|
||||||
suspend fun getToken(): String? {
|
suspend fun getToken(): String? {
|
||||||
if (tokenCache == null) {
|
if (tokenCache == null) {
|
||||||
tokenCache = App.context.userDataStore.data
|
tokenCache = App.context.userDataStore.data
|
||||||
@ -33,10 +38,15 @@ object AuthRepository {
|
|||||||
preferences[stringPreferencesKey(TOKEN_KEY)]
|
preferences[stringPreferencesKey(TOKEN_KEY)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log.e("getTokenCache", tokenCache.toString())
|
||||||
return tokenCache
|
return tokenCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* При обращении к серверу
|
||||||
|
*/
|
||||||
suspend fun getToken(login : String, password : String) : Result<String> {
|
suspend fun getToken(login : String, password : String) : Result<String> {
|
||||||
|
Log.e("getTokenNDSInAR", NetworkDataSource.getToken(login, password).toString())
|
||||||
return NetworkDataSource.getToken(login, password)
|
return NetworkDataSource.getToken(login, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,22 +42,29 @@ object NetworkDataSource {
|
|||||||
}
|
}
|
||||||
suspend fun getToken(login: String, password: String): Result<String> = withContext(Dispatchers.IO) {
|
suspend fun getToken(login: String, password: String): Result<String> = withContext(Dispatchers.IO) {
|
||||||
return@withContext runCatching {
|
return@withContext runCatching {
|
||||||
val response = client.post("${Constants.HOST}/api${Constants.GET_TOKEN}") {
|
val response = client.post("${Constants.HOST}/api${Constants.AUTH_URL}") {
|
||||||
contentType(ContentType.Application.Json)
|
contentType(ContentType.Application.Json)
|
||||||
setBody(
|
Log.d("bodyInToken",
|
||||||
"""
|
""" {
|
||||||
"login" : "$login",
|
"login" : "$login",
|
||||||
"password" : "$password"
|
"password" : "$password"
|
||||||
""".trimIndent()
|
} """.trimIndent()
|
||||||
|
)
|
||||||
|
setBody(
|
||||||
|
"""{
|
||||||
|
"login" : "${login}",
|
||||||
|
"password" : "${password}"
|
||||||
|
} """.trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Log.e("getTokenInNDS", response.body())
|
||||||
if (response.status != HttpStatusCode.OK) {
|
if (response.status != HttpStatusCode.OK) {
|
||||||
error(response.status)
|
Log.e("getToken", response.status.toString())
|
||||||
|
throw Exception("Неизвестная ошибка ${response.status}")
|
||||||
}
|
}
|
||||||
else if (response.status == HttpStatusCode.Unauthorized) {
|
else if (response.status == HttpStatusCode.Unauthorized) {
|
||||||
error("Неверный логин или пароль")
|
throw Exception("Неверный логин или пароль")
|
||||||
}
|
}
|
||||||
Log.e("getToken", response.status.toString())
|
|
||||||
response.body<String>()
|
response.body<String>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
package ru.myitschool.work.domain.auth
|
package ru.myitschool.work.domain.auth
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import ru.myitschool.work.data.repo.AuthRepository
|
import ru.myitschool.work.data.repo.AuthRepository
|
||||||
|
|
||||||
class GetTokenNetworkUseCase(
|
class GetTokenNetworkUseCase(
|
||||||
private val repository: AuthRepository
|
private val repository: AuthRepository
|
||||||
) {
|
) {
|
||||||
suspend operator fun invoke(login : String, password: String): Result<String> {
|
suspend operator fun invoke(login : String, password: String): Result<String> {
|
||||||
|
Log.e("GetTokenNetworkUseCase", repository.getToken(login, password).toString())
|
||||||
return repository.getToken(login, password)
|
return repository.getToken(login, password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.size
|
|||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.SecureTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -25,10 +26,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.VisualTransformation
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
import ru.myitschool.work.R
|
import ru.myitschool.work.R
|
||||||
import ru.myitschool.work.core.TestIds
|
import ru.myitschool.work.core.TestIds
|
||||||
import ru.myitschool.work.ui.custom.component.CustomButon
|
import ru.myitschool.work.ui.custom.component.CustomButon
|
||||||
@ -71,10 +74,10 @@ fun AuthScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Composable
|
//@Composable
|
||||||
fun SecureScreen(enabled: Boolean = true) {
|
//fun SecureScreen(enabled: Boolean = true) {
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
@Composable
|
@Composable
|
||||||
private fun Content(
|
private fun Content(
|
||||||
viewModel: AuthViewModel,
|
viewModel: AuthViewModel,
|
||||||
@ -112,14 +115,30 @@ private fun Content(
|
|||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.auth_sign_in))
|
Text(stringResource(R.string.auth_sign_in))
|
||||||
}
|
}
|
||||||
if (state.error != "Connection refused" && state.error != null) {
|
// if (state.error != null) {
|
||||||
|
// Text(
|
||||||
|
// modifier = Modifier.testTag(TestIds.Auth.ERROR),
|
||||||
|
// text = state.error,
|
||||||
|
// style = MaterialTheme.typography.bodyMedium,
|
||||||
|
// color = Color.Red,
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
if (state.error != null && !state.error.contains("401") && state.error.contains("Network")) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.testTag(TestIds.Auth.ERROR),
|
modifier = Modifier.testTag(TestIds.Auth.ERROR),
|
||||||
text = "Неизвестная ошибка: ${state.error}",
|
text = state.error,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = Color.Red,
|
color = Color.Red,
|
||||||
)
|
)
|
||||||
} else if (state.error == "Connection refused") {
|
}
|
||||||
|
if (state.error.toString().contains("401")) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.testTag(TestIds.Auth.ERROR),
|
||||||
|
text = "Неверный логин или пароль",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
color = Color.Red,
|
||||||
|
)
|
||||||
|
} else if (state.error.toString().contains("Network")) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.testTag(TestIds.Auth.ERROR),
|
modifier = Modifier.testTag(TestIds.Auth.ERROR),
|
||||||
text = "Отсутствует интернет-соединение",
|
text = "Отсутствует интернет-соединение",
|
||||||
|
|||||||
@ -30,10 +30,10 @@ class AuthViewModel : ViewModel() {
|
|||||||
|
|
||||||
private val _actionFlow: MutableSharedFlow<AuthAction> = MutableSharedFlow()
|
private val _actionFlow: MutableSharedFlow<AuthAction> = MutableSharedFlow()
|
||||||
val actionFlow: SharedFlow<AuthAction> = _actionFlow
|
val actionFlow: SharedFlow<AuthAction> = _actionFlow
|
||||||
|
|
||||||
fun onIntent(intent: AuthIntent) {
|
fun onIntent(intent: AuthIntent) {
|
||||||
when (intent) {
|
when (intent) {
|
||||||
is AuthIntent.Send -> {
|
is AuthIntent.Send -> {
|
||||||
|
Log.e("onIntent", intent.login)
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
getTokenNetworkUseCase.invoke(intent.login, intent.password).fold(
|
getTokenNetworkUseCase.invoke(intent.login, intent.password).fold(
|
||||||
onSuccess = {
|
onSuccess = {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package ru.myitschool.work.ui.screen.main
|
package ru.myitschool.work.ui.screen.meetings
|
||||||
|
|
||||||
object MeetingResult {
|
object MeetingResult {
|
||||||
const val REFRESH_STATUS = "refresh_status"
|
const val REFRESH_STATUS = "refresh_status"
|
||||||
@ -1,4 +1,10 @@
|
|||||||
package ru.myitschool.work.ui.screen.meetings
|
package ru.myitschool.work.ui.screen.meetings
|
||||||
|
|
||||||
class MeetingsAction {
|
import ru.myitschool.work.ui.nav.AppDestination
|
||||||
|
|
||||||
|
sealed interface MeetingsAction {
|
||||||
|
class Open(
|
||||||
|
val destination: AppDestination,
|
||||||
|
val clearBackStack: Boolean = false
|
||||||
|
): MeetingsAction
|
||||||
}
|
}
|
||||||
@ -1,18 +1,66 @@
|
|||||||
package ru.myitschool.work.ui.screen.meetings
|
package ru.myitschool.work.ui.screen.meetings
|
||||||
|
|
||||||
|
import android.provider.Settings.System.DATE_FORMAT
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import ru.myitschool.work.data.repo.AuthRepository
|
||||||
|
import ru.myitschool.work.data.repo.BookRepository
|
||||||
|
import ru.myitschool.work.domain.auth.LogoutUseCase
|
||||||
|
import ru.myitschool.work.domain.main.GetMainDataUseCase
|
||||||
|
import ru.myitschool.work.ui.nav.AuthScreenDestination
|
||||||
|
import ru.myitschool.work.ui.screen.main.MainAction
|
||||||
|
import ru.myitschool.work.ui.screen.main.MainState
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
class MeetingsViewModel: ViewModel() {
|
class MeetingsViewModel: ViewModel() {
|
||||||
private val _uiState = MutableStateFlow<MeetingsState>(MeetingsState.Loading)
|
private val _uiState = MutableStateFlow<MeetingsState>(MeetingsState.Loading)
|
||||||
val uiState: StateFlow<MeetingsState> = _uiState.asStateFlow()
|
val uiState: StateFlow<MeetingsState> = _uiState.asStateFlow()
|
||||||
|
private val _actionFlow: MutableSharedFlow<MainAction> = MutableSharedFlow()
|
||||||
private val _actionFlow: MutableSharedFlow<MeetingsAction> = MutableSharedFlow()
|
val actionFlow: SharedFlow<MainAction> = _actionFlow
|
||||||
val actionFlow: SharedFlow<MeetingsAction> = _actionFlow
|
private val logoutUseCase by lazy {
|
||||||
|
LogoutUseCase(AuthRepository)
|
||||||
|
}
|
||||||
|
private val getMeetingsDataUseCase by lazy {
|
||||||
|
GetMainDataUseCase(BookRepository(AuthRepository))
|
||||||
|
}
|
||||||
|
init {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// fun onIntent(intent: MeetingIntent) {
|
||||||
|
// when(intent) {
|
||||||
|
// is MeetingIntent.Logout -> {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// logoutUseCase.invoke()
|
||||||
|
// _actionFlow.emit(/*TODo*/)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// is MeetingIntent.Refresh -> {
|
||||||
|
// /*TODO("обновляться автоматически с заданной периодичностью")*/
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
fun refresh() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_uiState.update { MeetingsState.Loading }
|
||||||
|
_uiState.update {
|
||||||
|
getMeetingsDataUseCase.invoke().fold(
|
||||||
|
onFailure = { error ->
|
||||||
|
MeetingsState.Error(
|
||||||
|
error = error.message?.takeIf { it.isNotBlank() } ?: "Unknown error"
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onSuccess = TODO()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user