fix token reset

This commit is contained in:
2026-09-15 13:23:04 +03:00
parent 9203209d17
commit 43528748d6
4 changed files with 43 additions and 27 deletions
@@ -4,8 +4,6 @@ import com.arkivanov.decompose.ComponentContext
import com.arkivanov.essenty.lifecycle.coroutines.coroutineScope
import com.arkivanov.essenty.lifecycle.doOnStart
import kotlinx.coroutines.Job
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import kotlinx.serialization.KSerializer
import org.koin.core.Koin
@@ -30,12 +28,10 @@ class GigaWearRootComponent(
lifecycle.doOnStart {
job?.cancel()
job = scope.launch {
if (tokenStorage.token.firstOrNull() != null) {
runCatching {
healthCheck.healthCheck()
}.onFailure {
ensureActive()
tokenStorage.clear()
tokenStorage.token.collect {
if (it != null) {
runCatching { healthCheck.healthCheck() }
} else {
navReplace(Route.AuthScreen())
}
}
@@ -6,7 +6,6 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@@ -16,12 +15,15 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
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.CircularProgressIndicator
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.MaterialTheme
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.ScrollIndicator
import androidx.wear.compose.material3.Text
import kotlinx.coroutines.flow.collectLatest
import ru.shadowsparky.gigawear.R
import ru.shadowsparky.gigawear.presentation.WearErrorContent
import ru.shadowsparky.ui.components.LazyColumn
import ru.shadowsparky.updater.presentation.UpdateDialog
@Composable
@@ -77,17 +79,16 @@ fun ChatScreen(component: ChatComponent) {
}
}
}
val listState = rememberLazyListState()
val focusRequester = remember { FocusRequester() }
val scrollInfoProvider = remember(listState) {
ScrollInfoProvider(listState)
}
val rotaryBehavior = RotaryScrollableDefaults.behavior(
scrollableState = listState
)
AppScaffold {
ScreenScaffold(
scrollInfoProvider = scrollInfoProvider,
scrollIndicator = { ScrollIndicator(listState) },
scrollState = listState,
edgeButton = {
EdgeButton(
onClick = {
@@ -114,15 +115,24 @@ fun ChatScreen(component: ChatComponent) {
}
) { contentPadding ->
UpdateDialog(component.updateComponent)
LazyColumn(
state = listState,
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.requestFocusOnHierarchyActive()
.rotaryScrollable(
behavior = rotaryBehavior,
focusRequester = focusRequester
),
contentPadding = contentPadding,
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
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,
style = MaterialTheme.typography.labelMedium,
@@ -144,12 +154,16 @@ fun ChatScreen(component: ChatComponent) {
}
if (state.isLoading) {
item { CircularProgressIndicator() }
item {
CircularProgressIndicator()
}
}
state.error?.let { error ->
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.TokenInfo
import ru.shadowsparky.http.domain.TokenStorage
import ru.shadowsparky.http.domain.isServerFailure
import ru.shadowsparky.koin
@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
return try {
val newToken = koin.getOrNull<RefreshTokenAction>()
?.refresh(this.client, token)
?.refresh(client, token)
?: return null
tokenStorage.updateToken(newToken)
newToken.toKtor()
} catch (e: Throwable) {
if (e is HttpException) {
} catch (e: HttpException) {
if (e.isServerFailure()) throw e
koin.getOrNull<LogoutAction>()?.logout()
}
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)
open class NotFoundException(msg: String) : HttpException(HttpStatusCode.NotFound.value, msg)
fun HttpException.isServerFailure(): Boolean {
return httpCode in 500..599
}