mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
WIP login workflow
This commit is contained in:
parent
1030741631
commit
2161a9de56
5 changed files with 294 additions and 4 deletions
|
|
@ -20,10 +20,10 @@ import org.jellyfin.sdk.model.serializer.UUIDSerializer
|
|||
@Serializable
|
||||
data class SeerrServer(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Int,
|
||||
val name: String?,
|
||||
val id: Int = 0,
|
||||
val url: String,
|
||||
val version: String?,
|
||||
val name: String? = null,
|
||||
val version: String? = null,
|
||||
)
|
||||
|
||||
@Entity(
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class SeerrApi(
|
|||
|
||||
fun update(
|
||||
baseUrl: String,
|
||||
apiKey: String,
|
||||
apiKey: String?,
|
||||
) {
|
||||
api = SeerrApiClient(baseUrl, apiKey, okHttpClient)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
package com.github.damontecres.wholphin.services
|
||||
|
||||
import com.github.damontecres.wholphin.api.seerr.model.AuthJellyfinPostRequest
|
||||
import com.github.damontecres.wholphin.api.seerr.model.AuthLocalPostRequest
|
||||
import com.github.damontecres.wholphin.data.SeerrServerDao
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.SeerrAuthMethod
|
||||
import com.github.damontecres.wholphin.data.model.SeerrServer
|
||||
import com.github.damontecres.wholphin.data.model.SeerrUser
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.update
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SeerrServerRepository
|
||||
@Inject
|
||||
constructor(
|
||||
private val seerrApi: SeerrApi,
|
||||
private val seerrServerDao: SeerrServerDao,
|
||||
private val serverRepository: ServerRepository,
|
||||
) {
|
||||
private val _currentServer = MutableStateFlow<SeerrServer?>(null)
|
||||
val currentServer: StateFlow<SeerrServer?> = _currentServer
|
||||
|
||||
private val _currentUser = MutableStateFlow<SeerrUser?>(null)
|
||||
val currentUser: StateFlow<SeerrUser?> = _currentUser
|
||||
|
||||
val current =
|
||||
currentServer.combine(currentUser) { server, user ->
|
||||
if (server != null && user != null) {
|
||||
CurrentSeerr(server, user)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun addAndChangeServer(
|
||||
url: String,
|
||||
apiKey: String,
|
||||
) {
|
||||
var server = seerrServerDao.getServer(url)
|
||||
if (server == null) {
|
||||
seerrServerDao.addServer(SeerrServer(url = url))
|
||||
server = seerrServerDao.getServer(url)
|
||||
}
|
||||
server?.server?.let { server ->
|
||||
serverRepository.currentUser.value?.let { jellyfinUser ->
|
||||
// TODO test api key
|
||||
val user =
|
||||
SeerrUser(
|
||||
jellyfinRowId = jellyfinUser.rowId,
|
||||
serverId = server.id,
|
||||
authMethod = SeerrAuthMethod.API_KEY,
|
||||
username = null,
|
||||
password = null,
|
||||
credential = apiKey,
|
||||
)
|
||||
seerrServerDao.addUser(user)
|
||||
// TODO user info
|
||||
seerrApi.api.usersApi.authMeGet()
|
||||
|
||||
seerrApi.update(server.url, apiKey)
|
||||
_currentServer.update {
|
||||
_currentUser.update {
|
||||
user
|
||||
}
|
||||
server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun addAndChangeServer(
|
||||
url: String,
|
||||
authMethod: SeerrAuthMethod,
|
||||
username: String,
|
||||
password: String,
|
||||
) {
|
||||
var server = seerrServerDao.getServer(url)
|
||||
if (server == null) {
|
||||
seerrServerDao.addServer(SeerrServer(url = url))
|
||||
server = seerrServerDao.getServer(url)
|
||||
}
|
||||
server?.server?.let { server ->
|
||||
serverRepository.currentUser.value?.let { jellyfinUser ->
|
||||
val response =
|
||||
when (authMethod) {
|
||||
SeerrAuthMethod.LOCAL -> {
|
||||
seerrApi.api.authApi.authLocalPostWithHttpInfo(
|
||||
AuthLocalPostRequest(
|
||||
email = username,
|
||||
password = password,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
SeerrAuthMethod.JELLYFIN -> {
|
||||
seerrApi.api.authApi.authJellyfinPostWithHttpInfo(
|
||||
AuthJellyfinPostRequest(
|
||||
username = username,
|
||||
password = password,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
SeerrAuthMethod.API_KEY -> {
|
||||
throw IllegalArgumentException("Cannot authenticate with API key using this function")
|
||||
}
|
||||
}
|
||||
response.headers["Cookies"]
|
||||
// TODO get session cookie
|
||||
val user =
|
||||
SeerrUser(
|
||||
jellyfinRowId = jellyfinUser.rowId,
|
||||
serverId = server.id,
|
||||
authMethod = SeerrAuthMethod.API_KEY,
|
||||
username = username,
|
||||
password = password,
|
||||
credential = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class CurrentSeerr(
|
||||
val server: SeerrServer,
|
||||
val user: SeerrUser,
|
||||
)
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package com.github.damontecres.wholphin.ui.setup.seerr
|
||||
|
||||
import androidx.compose.foundation.focusGroup
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
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.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.ui.components.EditTextBox
|
||||
import com.github.damontecres.wholphin.ui.components.TextButton
|
||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
|
||||
@Composable
|
||||
fun AddSeerrServerContent(
|
||||
onSubmit: (url: String, apiKey: String) -> Unit,
|
||||
errorMessage: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var error by remember(errorMessage) { mutableStateOf(errorMessage) }
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier =
|
||||
modifier
|
||||
.focusGroup()
|
||||
.padding(16.dp)
|
||||
.wrapContentSize(),
|
||||
) {
|
||||
var url by remember { mutableStateOf("") }
|
||||
var apiKey by remember { mutableStateOf("") }
|
||||
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val passwordFocusRequester = remember { FocusRequester() }
|
||||
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||
Text(
|
||||
text = "Enter URL & API Key",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
) {
|
||||
Text(
|
||||
text = "URL",
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
)
|
||||
EditTextBox(
|
||||
value = url,
|
||||
onValueChange = {
|
||||
error = null
|
||||
url = it
|
||||
},
|
||||
keyboardOptions =
|
||||
KeyboardOptions(
|
||||
capitalization = KeyboardCapitalization.None,
|
||||
autoCorrectEnabled = false,
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Next,
|
||||
),
|
||||
keyboardActions =
|
||||
KeyboardActions(
|
||||
onNext = {
|
||||
passwordFocusRequester.tryRequestFocus()
|
||||
},
|
||||
),
|
||||
isInputValid = { true },
|
||||
modifier = Modifier.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
) {
|
||||
Text(
|
||||
text = "API Key",
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
)
|
||||
EditTextBox(
|
||||
value = apiKey,
|
||||
onValueChange = {
|
||||
error = null
|
||||
apiKey = it
|
||||
},
|
||||
keyboardOptions =
|
||||
KeyboardOptions(
|
||||
capitalization = KeyboardCapitalization.None,
|
||||
autoCorrectEnabled = false,
|
||||
keyboardType = KeyboardType.Password,
|
||||
imeAction = ImeAction.Go,
|
||||
),
|
||||
keyboardActions =
|
||||
KeyboardActions(
|
||||
onGo = { onSubmit.invoke(url, apiKey) },
|
||||
),
|
||||
isInputValid = { true },
|
||||
modifier = Modifier.focusRequester(passwordFocusRequester),
|
||||
)
|
||||
}
|
||||
error?.let {
|
||||
Text(
|
||||
text = it,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
)
|
||||
}
|
||||
TextButton(
|
||||
stringRes = R.string.submit,
|
||||
onClick = { onSubmit.invoke(url, apiKey) },
|
||||
enabled = error.isNullOrBlank() && url.isNotNullOrBlank() && apiKey.isNotNullOrBlank(),
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.github.damontecres.wholphin.ui.setup.seerr
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.github.damontecres.wholphin.services.SeerrServerRepository
|
||||
import com.github.damontecres.wholphin.services.SeerrService
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import jakarta.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SwitchSeerrViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
private val seerrServerRepository: SeerrServerRepository,
|
||||
private val seerrService: SeerrService,
|
||||
) : ViewModel() {
|
||||
fun submitServer(
|
||||
url: String,
|
||||
apiKey: String,
|
||||
) {
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue