Better Jellyseerr connection error handling (#933)

## Description
Show Jellyseerr connection errors in settings. If an error occurred
trying to login, in setting it will show "Server error" and clicking
gives more error info and option to remove the server.

### Related issues
Fixes #907 

### Testing
Emulator with simulated errors

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Ray 2026-02-20 14:29:58 -05:00 committed by GitHub
parent dfd9acf561
commit 4f8f69c438
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 120 additions and 63 deletions

View file

@ -44,18 +44,33 @@ class SeerrServerRepository
private val serverRepository: ServerRepository,
@param:StandardOkHttpClient private val okHttpClient: OkHttpClient,
) {
private val _current = MutableStateFlow<CurrentSeerr?>(null)
val current: StateFlow<CurrentSeerr?> = _current
val currentServer: Flow<SeerrServer?> = current.map { it?.server }
val currentUser: Flow<SeerrUser?> = current.map { it?.user }
private val _connection =
MutableStateFlow<SeerrConnectionStatus>(SeerrConnectionStatus.NotConfigured)
val connection: StateFlow<SeerrConnectionStatus> = _connection
val current: Flow<CurrentSeerr?> =
_connection.map { (it as? SeerrConnectionStatus.Success)?.current }
val currentServer: Flow<SeerrServer?> =
connection.map { (it as? SeerrConnectionStatus.Success)?.current?.server }
val currentUser: Flow<SeerrUser?> =
connection.map { (it as? SeerrConnectionStatus.Success)?.current?.user }
/**
* Whether Seerr integration is currently active of not
*/
val active: Flow<Boolean> = current.map { it != null && seerrApi.active }
val active: Flow<Boolean> =
connection.map { it is SeerrConnectionStatus.Success && seerrApi.active }
fun clear() {
_current.update { null }
_connection.update { SeerrConnectionStatus.NotConfigured }
seerrApi.update("", null)
}
fun error(
serverUrl: String,
exception: Exception,
) {
_connection.update { SeerrConnectionStatus.Error(serverUrl, exception) }
seerrApi.update("", null)
}
@ -65,8 +80,10 @@ class SeerrServerRepository
userConfig: SeerrUserConfig,
) {
val publicSettings = seerrApi.api.settingsApi.settingsPublicGet()
_current.update {
CurrentSeerr(server, user, userConfig, publicSettings)
_connection.update {
SeerrConnectionStatus.Success(
CurrentSeerr(server, user, userConfig, publicSettings),
)
}
}
@ -154,7 +171,7 @@ class SeerrServerRepository
}
suspend fun removeServer() {
val current = _current.value ?: return
val current = (_connection.value as? SeerrConnectionStatus.Success)?.current ?: return
seerrServerDao.deleteUser(current.server.id, current.user.jellyfinUserRowId)
clear()
}
@ -165,6 +182,19 @@ class SeerrServerRepository
*/
typealias SeerrUserConfig = User
sealed interface SeerrConnectionStatus {
data object NotConfigured : SeerrConnectionStatus
data class Error(
val serverUrl: String,
val ex: Exception,
) : SeerrConnectionStatus
data class Success(
val current: CurrentSeerr,
) : SeerrConnectionStatus
}
data class CurrentSeerr(
val server: SeerrServer,
val user: SeerrUser,
@ -244,45 +274,34 @@ class UserSwitchListener
launchIO {
seerrServerDao
.getUsersByJellyfinUser(user.rowId)
.firstOrNull()
.lastOrNull()
?.let { seerrUser ->
val server =
seerrServerDao.getServer(seerrUser.serverId)?.server
if (server != null) {
Timber.i("Found a seerr user & server")
seerrApi.update(server.url, seerrUser.credential)
val userConfig =
if (seerrUser.authMethod != SeerrAuthMethod.API_KEY) {
try {
try {
seerrApi.update(server.url, seerrUser.credential)
val userConfig =
if (seerrUser.authMethod != SeerrAuthMethod.API_KEY) {
login(
seerrApi.api,
seerrUser.authMethod,
seerrUser.username,
seerrUser.password,
)
} catch (ex: Exception) {
Timber.w(
ex,
"Error logging into %s",
server.url,
)
seerrServerRepository.clear()
return@let
}
} else {
try {
} else {
seerrApi.api.usersApi.authMeGet()
} catch (ex: Exception) {
Timber.w(
ex,
"Error logging into %s",
server.url,
)
seerrServerRepository.clear()
return@let
}
}
seerrServerRepository.set(server, seerrUser, userConfig)
seerrServerRepository.set(server, seerrUser, userConfig)
} catch (ex: Exception) {
Timber.w(
ex,
"Error logging into %s",
server.url,
)
seerrServerRepository.error(server.url, ex)
}
}
}
}