fix token reset
This commit is contained in:
+4
-8
@@ -4,8 +4,6 @@ import com.arkivanov.decompose.ComponentContext
|
|||||||
import com.arkivanov.essenty.lifecycle.coroutines.coroutineScope
|
import com.arkivanov.essenty.lifecycle.coroutines.coroutineScope
|
||||||
import com.arkivanov.essenty.lifecycle.doOnStart
|
import com.arkivanov.essenty.lifecycle.doOnStart
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.ensureActive
|
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import org.koin.core.Koin
|
import org.koin.core.Koin
|
||||||
@@ -30,12 +28,10 @@ class GigaWearRootComponent(
|
|||||||
lifecycle.doOnStart {
|
lifecycle.doOnStart {
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
job = scope.launch {
|
job = scope.launch {
|
||||||
if (tokenStorage.token.firstOrNull() != null) {
|
tokenStorage.token.collect {
|
||||||
runCatching {
|
if (it != null) {
|
||||||
healthCheck.healthCheck()
|
runCatching { healthCheck.healthCheck() }
|
||||||
}.onFailure {
|
} else {
|
||||||
ensureActive()
|
|
||||||
tokenStorage.clear()
|
|
||||||
navReplace(Route.AuthScreen())
|
navReplace(Route.AuthScreen())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-13
@@ -6,7 +6,6 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
@@ -16,12 +15,15 @@ import androidx.compose.runtime.getValue
|
|||||||
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.focus.FocusRequester
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.wear.compose.foundation.ScrollInfoProvider
|
import androidx.wear.compose.foundation.requestFocusOnHierarchyActive
|
||||||
|
import androidx.wear.compose.foundation.rotary.RotaryScrollableDefaults
|
||||||
|
import androidx.wear.compose.foundation.rotary.rotaryScrollable
|
||||||
import androidx.wear.compose.material3.AppScaffold
|
import androidx.wear.compose.material3.AppScaffold
|
||||||
import androidx.wear.compose.material3.CircularProgressIndicator
|
import androidx.wear.compose.material3.CircularProgressIndicator
|
||||||
import androidx.wear.compose.material3.EdgeButton
|
import androidx.wear.compose.material3.EdgeButton
|
||||||
@@ -29,11 +31,11 @@ import androidx.wear.compose.material3.EdgeButtonSize
|
|||||||
import androidx.wear.compose.material3.Icon
|
import androidx.wear.compose.material3.Icon
|
||||||
import androidx.wear.compose.material3.MaterialTheme
|
import androidx.wear.compose.material3.MaterialTheme
|
||||||
import androidx.wear.compose.material3.ScreenScaffold
|
import androidx.wear.compose.material3.ScreenScaffold
|
||||||
import androidx.wear.compose.material3.ScrollIndicator
|
|
||||||
import androidx.wear.compose.material3.Text
|
import androidx.wear.compose.material3.Text
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import ru.shadowsparky.gigawear.R
|
import ru.shadowsparky.gigawear.R
|
||||||
import ru.shadowsparky.gigawear.presentation.WearErrorContent
|
import ru.shadowsparky.gigawear.presentation.WearErrorContent
|
||||||
|
import ru.shadowsparky.ui.components.LazyColumn
|
||||||
import ru.shadowsparky.updater.presentation.UpdateDialog
|
import ru.shadowsparky.updater.presentation.UpdateDialog
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -77,17 +79,16 @@ fun ChatScreen(component: ChatComponent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
val scrollInfoProvider = remember(listState) {
|
val rotaryBehavior = RotaryScrollableDefaults.behavior(
|
||||||
ScrollInfoProvider(listState)
|
scrollableState = listState
|
||||||
}
|
)
|
||||||
|
|
||||||
AppScaffold {
|
AppScaffold {
|
||||||
ScreenScaffold(
|
ScreenScaffold(
|
||||||
scrollInfoProvider = scrollInfoProvider,
|
scrollState = listState,
|
||||||
scrollIndicator = { ScrollIndicator(listState) },
|
|
||||||
edgeButton = {
|
edgeButton = {
|
||||||
EdgeButton(
|
EdgeButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
@@ -114,15 +115,24 @@ fun ChatScreen(component: ChatComponent) {
|
|||||||
}
|
}
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
UpdateDialog(component.updateComponent)
|
UpdateDialog(component.updateComponent)
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = listState,
|
state = listState,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.requestFocusOnHierarchyActive()
|
||||||
|
.rotaryScrollable(
|
||||||
|
behavior = rotaryBehavior,
|
||||||
|
focusRequester = focusRequester
|
||||||
|
),
|
||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
val text = state.userText ?: stringResource(R.string.input_text_to_assist)
|
val text = state.userText
|
||||||
|
?: stringResource(R.string.input_text_to_assist)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
@@ -144,12 +154,16 @@ fun ChatScreen(component: ChatComponent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.isLoading) {
|
if (state.isLoading) {
|
||||||
item { CircularProgressIndicator() }
|
item {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.error?.let { error ->
|
state.error?.let { error ->
|
||||||
item {
|
item {
|
||||||
WearErrorContent(error.message ?: error.toString())
|
WearErrorContent(
|
||||||
|
error.message ?: error.toString()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import ru.shadowsparky.http.domain.LogoutAction
|
|||||||
import ru.shadowsparky.http.domain.RefreshTokenAction
|
import ru.shadowsparky.http.domain.RefreshTokenAction
|
||||||
import ru.shadowsparky.http.domain.TokenInfo
|
import ru.shadowsparky.http.domain.TokenInfo
|
||||||
import ru.shadowsparky.http.domain.TokenStorage
|
import ru.shadowsparky.http.domain.TokenStorage
|
||||||
|
import ru.shadowsparky.http.domain.isServerFailure
|
||||||
import ru.shadowsparky.koin
|
import ru.shadowsparky.koin
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@@ -53,18 +54,19 @@ class HttpModule {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun RefreshTokensParams.refreshTokenInternal(tokenStorage: TokenStorage?): BearerTokens? {
|
private suspend fun RefreshTokensParams.refreshTokenInternal(
|
||||||
|
tokenStorage: TokenStorage?
|
||||||
|
): BearerTokens? {
|
||||||
val token = tokenStorage?.token?.firstOrNull()?.refresh ?: return null
|
val token = tokenStorage?.token?.firstOrNull()?.refresh ?: return null
|
||||||
return try {
|
return try {
|
||||||
val newToken = koin.getOrNull<RefreshTokenAction>()
|
val newToken = koin.getOrNull<RefreshTokenAction>()
|
||||||
?.refresh(this.client, token)
|
?.refresh(client, token)
|
||||||
?: return null
|
?: return null
|
||||||
tokenStorage.updateToken(newToken)
|
tokenStorage.updateToken(newToken)
|
||||||
newToken.toKtor()
|
newToken.toKtor()
|
||||||
} catch (e: Throwable) {
|
} catch (e: HttpException) {
|
||||||
if (e is HttpException) {
|
if (e.isServerFailure()) throw e
|
||||||
koin.getOrNull<LogoutAction>()?.logout()
|
koin.getOrNull<LogoutAction>()?.logout()
|
||||||
}
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,3 +8,7 @@ open class HttpException(val httpCode: Int, override val message: String?) : Run
|
|||||||
|
|
||||||
class BadRequestException(msg: String) : HttpException(HttpStatusCode.BadRequest.value, msg)
|
class BadRequestException(msg: String) : HttpException(HttpStatusCode.BadRequest.value, msg)
|
||||||
open class NotFoundException(msg: String) : HttpException(HttpStatusCode.NotFound.value, msg)
|
open class NotFoundException(msg: String) : HttpException(HttpStatusCode.NotFound.value, msg)
|
||||||
|
|
||||||
|
fun HttpException.isServerFailure(): Boolean {
|
||||||
|
return httpCode in 500..599
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user