mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Refactoring to expose current configuration
This commit is contained in:
parent
ee8a4ac0ac
commit
a174d981a8
5 changed files with 312 additions and 269 deletions
|
|
@ -18,7 +18,6 @@ import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.jellyfin.sdk.Jellyfin
|
import org.jellyfin.sdk.Jellyfin
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.displayPreferencesApi
|
|
||||||
import org.jellyfin.sdk.api.client.extensions.systemApi
|
import org.jellyfin.sdk.api.client.extensions.systemApi
|
||||||
import org.jellyfin.sdk.api.client.extensions.userApi
|
import org.jellyfin.sdk.api.client.extensions.userApi
|
||||||
import org.jellyfin.sdk.model.api.AuthenticationResult
|
import org.jellyfin.sdk.model.api.AuthenticationResult
|
||||||
|
|
@ -103,27 +102,6 @@ class ServerRepository
|
||||||
currentUserId = updatedUser.id.toServerString()
|
currentUserId = updatedUser.id.toServerString()
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
val settings =
|
|
||||||
apiClient.displayPreferencesApi
|
|
||||||
.getDisplayPreferences(
|
|
||||||
displayPreferencesId = "settings",
|
|
||||||
userId = user.id,
|
|
||||||
client = "wholphin",
|
|
||||||
).content
|
|
||||||
val newSettings =
|
|
||||||
settings.copy(
|
|
||||||
customPrefs =
|
|
||||||
settings.customPrefs.toMutableMap().apply {
|
|
||||||
put("test_key", "test_value")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
apiClient.displayPreferencesApi.updateDisplayPreferences(
|
|
||||||
displayPreferencesId = "settings",
|
|
||||||
userId = user.id,
|
|
||||||
client = "wholphin",
|
|
||||||
data = newSettings,
|
|
||||||
)
|
|
||||||
Timber.v("settings=$settings")
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
_current.value = CurrentUser(updatedServer, updatedUser)
|
_current.value = CurrentUser(updatedServer, updatedUser)
|
||||||
_currentUserDto.value = userDto
|
_currentUserDto.value = userDto
|
||||||
|
|
|
||||||
|
|
@ -144,9 +144,21 @@ data class HomeRowConfigDisplay(
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("HomePageSettings")
|
@SerialName("HomePageSettings")
|
||||||
data class HomePageSettings(
|
data class HomePageSettings(
|
||||||
val version: Int = 1,
|
|
||||||
val rows: List<HomeRowConfig>,
|
val rows: List<HomeRowConfig>,
|
||||||
)
|
val version: Int = 1,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
val EMPTY = HomePageSettings(listOf())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class HomePageResolvedSettings(
|
||||||
|
val rows: List<HomeRowConfigDisplay>,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
val EMPTY = HomePageResolvedSettings(listOf())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class HomeRowViewOptions(
|
data class HomeRowViewOptions(
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,28 @@ package com.github.damontecres.wholphin.services
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.NavDrawerItemRepository
|
||||||
|
import com.github.damontecres.wholphin.data.model.HomePageResolvedSettings
|
||||||
import com.github.damontecres.wholphin.data.model.HomePageSettings
|
import com.github.damontecres.wholphin.data.model.HomePageSettings
|
||||||
|
import com.github.damontecres.wholphin.data.model.HomeRowConfig
|
||||||
|
import com.github.damontecres.wholphin.data.model.HomeRowConfigDisplay
|
||||||
|
import com.github.damontecres.wholphin.data.model.HomeRowViewOptions
|
||||||
|
import com.github.damontecres.wholphin.ui.main.settings.Library
|
||||||
|
import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem
|
||||||
import com.github.damontecres.wholphin.ui.toServerString
|
import com.github.damontecres.wholphin.ui.toServerString
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.decodeFromStream
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
import kotlinx.serialization.json.encodeToStream
|
import kotlinx.serialization.json.encodeToStream
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.displayPreferencesApi
|
import org.jellyfin.sdk.api.client.extensions.displayPreferencesApi
|
||||||
|
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||||
import org.jellyfin.sdk.model.UUID
|
import org.jellyfin.sdk.model.UUID
|
||||||
|
import org.jellyfin.sdk.model.serializer.toUUID
|
||||||
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
@ -23,7 +34,8 @@ class HomeSettingsService
|
||||||
constructor(
|
constructor(
|
||||||
@param:ApplicationContext private val context: Context,
|
@param:ApplicationContext private val context: Context,
|
||||||
private val api: ApiClient,
|
private val api: ApiClient,
|
||||||
private val serverRepository: ServerRepository,
|
private val userPreferencesService: UserPreferencesService,
|
||||||
|
private val navDrawerItemRepository: NavDrawerItemRepository,
|
||||||
) {
|
) {
|
||||||
val jsonParser =
|
val jsonParser =
|
||||||
Json {
|
Json {
|
||||||
|
|
@ -31,32 +43,35 @@ class HomeSettingsService
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val currentSettings = MutableStateFlow(HomePageResolvedSettings.EMPTY)
|
||||||
|
|
||||||
suspend fun saveToServer(
|
suspend fun saveToServer(
|
||||||
|
userId: UUID,
|
||||||
settings: HomePageSettings,
|
settings: HomePageSettings,
|
||||||
displayPreferencesId: String = DISPLAY_PREF_ID,
|
displayPreferencesId: String = DISPLAY_PREF_ID,
|
||||||
) {
|
) {
|
||||||
serverRepository.currentUser.value?.let { user ->
|
val current = getDisplayPreferences(userId, DISPLAY_PREF_ID)
|
||||||
val current = getDisplayPreferences(user.id, DISPLAY_PREF_ID)
|
val customPrefs =
|
||||||
val customPrefs =
|
current.customPrefs.toMutableMap().apply {
|
||||||
current.customPrefs.toMutableMap().apply {
|
put(CUSTOM_PREF_ID, jsonParser.encodeToString(settings))
|
||||||
put(CUSTOM_PREF_ID, jsonParser.encodeToString(settings))
|
}
|
||||||
}
|
api.displayPreferencesApi.updateDisplayPreferences(
|
||||||
api.displayPreferencesApi.updateDisplayPreferences(
|
displayPreferencesId = displayPreferencesId,
|
||||||
displayPreferencesId = displayPreferencesId,
|
userId = userId,
|
||||||
userId = user.id,
|
client = context.getString(R.string.app_name),
|
||||||
client = context.getString(R.string.app_name),
|
data = current.copy(customPrefs = customPrefs),
|
||||||
data = current.copy(customPrefs = customPrefs),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun loadFromServer(displayPreferencesId: String = DISPLAY_PREF_ID): HomePageSettings? =
|
suspend fun loadFromServer(
|
||||||
serverRepository.currentUser.value?.let { user ->
|
userId: UUID,
|
||||||
val current = getDisplayPreferences(user.id, displayPreferencesId)
|
displayPreferencesId: String = DISPLAY_PREF_ID,
|
||||||
current.customPrefs[DISPLAY_PREF_ID]?.let {
|
): HomePageSettings? {
|
||||||
Json.decodeFromString<HomePageSettings>(it)
|
val current = getDisplayPreferences(userId, displayPreferencesId)
|
||||||
}
|
return current.customPrefs[DISPLAY_PREF_ID]?.let {
|
||||||
|
Json.decodeFromString<HomePageSettings>(it)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun getDisplayPreferences(
|
private suspend fun getDisplayPreferences(
|
||||||
userId: UUID,
|
userId: UUID,
|
||||||
|
|
@ -71,27 +86,202 @@ class HomeSettingsService
|
||||||
private fun filename(userId: UUID) = "${CUSTOM_PREF_ID}_${userId.toServerString()}.json"
|
private fun filename(userId: UUID) = "${CUSTOM_PREF_ID}_${userId.toServerString()}.json"
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
suspend fun saveToLocal(settings: HomePageSettings) {
|
suspend fun saveToLocal(
|
||||||
serverRepository.currentUser.value?.let { user ->
|
userId: UUID,
|
||||||
val dir = File(context.filesDir, CUSTOM_PREF_ID)
|
settings: HomePageSettings,
|
||||||
dir.mkdirs()
|
) {
|
||||||
File(dir, filename(user.id)).outputStream().use {
|
val dir = File(context.filesDir, CUSTOM_PREF_ID)
|
||||||
jsonParser.encodeToStream(settings, it)
|
dir.mkdirs()
|
||||||
}
|
File(dir, filename(userId)).outputStream().use {
|
||||||
|
jsonParser.encodeToStream(settings, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
suspend fun loadFromLocal(): HomePageSettings? =
|
suspend fun loadFromLocal(userId: UUID): HomePageSettings? {
|
||||||
serverRepository.currentUser.value?.let { user ->
|
val dir = File(context.filesDir, CUSTOM_PREF_ID)
|
||||||
val dir = File(context.filesDir, CUSTOM_PREF_ID)
|
val file = File(dir, filename(userId))
|
||||||
val file = File(dir, filename(user.id))
|
return if (file.exists()) {
|
||||||
if (file.exists()) {
|
file.inputStream().use {
|
||||||
file.inputStream().use {
|
jsonParser.decodeFromStream<HomePageSettings>(it)
|
||||||
jsonParser.decodeFromStream<HomePageSettings>(it)
|
}
|
||||||
}
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun updateCurrent(userId: UUID) {
|
||||||
|
Timber.v("Getting setting for %s", userId)
|
||||||
|
// User local then server/remote otherwise create a default
|
||||||
|
val settings = loadFromLocal(userId) ?: loadFromServer(userId)
|
||||||
|
val resolvedSettings =
|
||||||
|
if (settings != null) {
|
||||||
|
Timber.v("Found settings")
|
||||||
|
// Resolve
|
||||||
|
val resolvedRows = settings.rows.map { convert(it) }
|
||||||
|
HomePageResolvedSettings(resolvedRows)
|
||||||
} else {
|
} else {
|
||||||
null
|
createDefault(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSettings.update { resolvedSettings }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun createDefault(userId: UUID): HomePageResolvedSettings {
|
||||||
|
Timber.v("Creating default settings")
|
||||||
|
val navDrawerItems = navDrawerItemRepository.getNavDrawerItems()
|
||||||
|
val libraries =
|
||||||
|
navDrawerItems
|
||||||
|
.filter { it is ServerNavDrawerItem }
|
||||||
|
.map {
|
||||||
|
it as ServerNavDrawerItem
|
||||||
|
Library(it.itemId, it.name, it.type)
|
||||||
|
}
|
||||||
|
val prefs =
|
||||||
|
userPreferencesService.getCurrent().appPreferences.homePagePreferences
|
||||||
|
val includedIds =
|
||||||
|
navDrawerItemRepository
|
||||||
|
.getFilteredNavDrawerItems(navDrawerItems)
|
||||||
|
.filter { it is ServerNavDrawerItem }
|
||||||
|
.mapIndexed { index, it ->
|
||||||
|
val id = (it as ServerNavDrawerItem).itemId
|
||||||
|
val name = libraries.firstOrNull { it.itemId == id }?.name
|
||||||
|
val title =
|
||||||
|
name?.let { context.getString(R.string.recently_added_in, it) }
|
||||||
|
?: context.getString(R.string.recently_added)
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
title,
|
||||||
|
HomeRowConfig.RecentlyAdded(
|
||||||
|
index,
|
||||||
|
id,
|
||||||
|
HomeRowViewOptions(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val continueWatchingRows =
|
||||||
|
if (prefs.combineContinueNext) {
|
||||||
|
listOf(
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.combine_continue_next),
|
||||||
|
HomeRowConfig.ContinueWatchingCombined(
|
||||||
|
includedIds.size + 1,
|
||||||
|
HomeRowViewOptions(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
listOf(
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.continue_watching),
|
||||||
|
HomeRowConfig.ContinueWatching(
|
||||||
|
includedIds.size + 1,
|
||||||
|
HomeRowViewOptions(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.next_up),
|
||||||
|
HomeRowConfig.NextUp(
|
||||||
|
includedIds.size + 2,
|
||||||
|
HomeRowViewOptions(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val rowConfig =
|
||||||
|
continueWatchingRows + includedIds +
|
||||||
|
// TODO remove after testing
|
||||||
|
listOf(
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
"Collection",
|
||||||
|
HomeRowConfig.ByParent(
|
||||||
|
id = 100,
|
||||||
|
parentId = "34ab6fd1f51c41bb014981f2e334f465".toUUID(),
|
||||||
|
recursive = true,
|
||||||
|
viewOptions = HomeRowViewOptions(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
"Playlist",
|
||||||
|
HomeRowConfig.ByParent(
|
||||||
|
id = 101,
|
||||||
|
parentId = "f94be36e9836127a0bccfc7843b19e5b".toUUID(),
|
||||||
|
recursive = true,
|
||||||
|
viewOptions = HomeRowViewOptions(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return HomePageResolvedSettings(rowConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun convert(config: HomeRowConfig): HomeRowConfigDisplay =
|
||||||
|
when (config) {
|
||||||
|
is HomeRowConfig.ByParent -> {
|
||||||
|
val name =
|
||||||
|
api.userLibraryApi
|
||||||
|
.getItem(itemId = config.parentId)
|
||||||
|
.content.name ?: ""
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
name,
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HomeRowConfig.ContinueWatching -> {
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.continue_watching),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HomeRowConfig.ContinueWatchingCombined -> {
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.combine_continue_next),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HomeRowConfig.Genres -> {
|
||||||
|
val name =
|
||||||
|
api.userLibraryApi
|
||||||
|
.getItem(itemId = config.parentId)
|
||||||
|
.content.name ?: ""
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.genres_in, name),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HomeRowConfig.GetItems -> {
|
||||||
|
HomeRowConfigDisplay(config.name, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HomeRowConfig.NextUp -> {
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.next_up),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HomeRowConfig.RecentlyAdded -> {
|
||||||
|
val name =
|
||||||
|
api.userLibraryApi
|
||||||
|
.getItem(itemId = config.parentId)
|
||||||
|
.content.name ?: ""
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.recently_added_in, name),
|
||||||
|
config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HomeRowConfig.RecentlyReleased -> {
|
||||||
|
val name =
|
||||||
|
api.userLibraryApi
|
||||||
|
.getItem(itemId = config.parentId)
|
||||||
|
.content.name ?: ""
|
||||||
|
HomeRowConfigDisplay(
|
||||||
|
context.getString(R.string.recently_released_in, name),
|
||||||
|
config,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import com.github.damontecres.wholphin.api.seerr.model.PublicSettings
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.User
|
import com.github.damontecres.wholphin.api.seerr.model.User
|
||||||
import com.github.damontecres.wholphin.data.SeerrServerDao
|
import com.github.damontecres.wholphin.data.SeerrServerDao
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
|
import com.github.damontecres.wholphin.data.model.HomePageResolvedSettings
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrAuthMethod
|
import com.github.damontecres.wholphin.data.model.SeerrAuthMethod
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrPermission
|
import com.github.damontecres.wholphin.data.model.SeerrPermission
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrServer
|
import com.github.damontecres.wholphin.data.model.SeerrServer
|
||||||
|
|
@ -213,6 +214,7 @@ class UserSwitchListener
|
||||||
private val seerrServerRepository: SeerrServerRepository,
|
private val seerrServerRepository: SeerrServerRepository,
|
||||||
private val seerrServerDao: SeerrServerDao,
|
private val seerrServerDao: SeerrServerDao,
|
||||||
private val seerrApi: SeerrApi,
|
private val seerrApi: SeerrApi,
|
||||||
|
private val homeSettingsService: HomeSettingsService,
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
context as AppCompatActivity
|
context as AppCompatActivity
|
||||||
|
|
@ -220,41 +222,58 @@ class UserSwitchListener
|
||||||
serverRepository.currentUser.asFlow().collect { user ->
|
serverRepository.currentUser.asFlow().collect { user ->
|
||||||
Timber.d("New user")
|
Timber.d("New user")
|
||||||
seerrServerRepository.clear()
|
seerrServerRepository.clear()
|
||||||
|
homeSettingsService.currentSettings.update { HomePageResolvedSettings.EMPTY }
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
seerrServerDao
|
// Check for home settings
|
||||||
.getUsersByJellyfinUser(user.rowId)
|
launchIO {
|
||||||
.firstOrNull()
|
homeSettingsService.updateCurrent(user.id)
|
||||||
?.let { seerrUser ->
|
}
|
||||||
val server = seerrServerDao.getServer(seerrUser.serverId)?.server
|
// Check for seerr server
|
||||||
if (server != null) {
|
launchIO {
|
||||||
Timber.i("Found a seerr user & server")
|
seerrServerDao
|
||||||
seerrApi.update(server.url, seerrUser.credential)
|
.getUsersByJellyfinUser(user.rowId)
|
||||||
val userConfig =
|
.firstOrNull()
|
||||||
if (seerrUser.authMethod != SeerrAuthMethod.API_KEY) {
|
?.let { seerrUser ->
|
||||||
try {
|
val server =
|
||||||
login(
|
seerrServerDao.getServer(seerrUser.serverId)?.server
|
||||||
seerrApi.api,
|
if (server != null) {
|
||||||
seerrUser.authMethod,
|
Timber.i("Found a seerr user & server")
|
||||||
seerrUser.username,
|
seerrApi.update(server.url, seerrUser.credential)
|
||||||
seerrUser.password,
|
val userConfig =
|
||||||
)
|
if (seerrUser.authMethod != SeerrAuthMethod.API_KEY) {
|
||||||
} catch (ex: Exception) {
|
try {
|
||||||
Timber.w(ex, "Error logging into %s", server.url)
|
login(
|
||||||
seerrServerRepository.clear()
|
seerrApi.api,
|
||||||
return@let
|
seerrUser.authMethod,
|
||||||
|
seerrUser.username,
|
||||||
|
seerrUser.password,
|
||||||
|
)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Timber.w(
|
||||||
|
ex,
|
||||||
|
"Error logging into %s",
|
||||||
|
server.url,
|
||||||
|
)
|
||||||
|
seerrServerRepository.clear()
|
||||||
|
return@let
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
seerrApi.api.usersApi.authMeGet()
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Timber.w(
|
||||||
|
ex,
|
||||||
|
"Error logging into %s",
|
||||||
|
server.url,
|
||||||
|
)
|
||||||
|
seerrServerRepository.clear()
|
||||||
|
return@let
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
seerrServerRepository.set(server, seerrUser, userConfig)
|
||||||
try {
|
}
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.data.NavDrawerItemRepository
|
import com.github.damontecres.wholphin.data.NavDrawerItemRepository
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
|
import com.github.damontecres.wholphin.data.model.HomePageResolvedSettings
|
||||||
import com.github.damontecres.wholphin.data.model.HomePageSettings
|
import com.github.damontecres.wholphin.data.model.HomePageSettings
|
||||||
import com.github.damontecres.wholphin.data.model.HomeRowConfig
|
import com.github.damontecres.wholphin.data.model.HomeRowConfig
|
||||||
import com.github.damontecres.wholphin.data.model.HomeRowConfigDisplay
|
import com.github.damontecres.wholphin.data.model.HomeRowConfigDisplay
|
||||||
|
|
@ -33,6 +34,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||||
|
|
@ -43,7 +45,6 @@ import org.jellyfin.sdk.model.api.UserDto
|
||||||
import org.jellyfin.sdk.model.api.request.GetGenresRequest
|
import org.jellyfin.sdk.model.api.request.GetGenresRequest
|
||||||
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
||||||
import org.jellyfin.sdk.model.api.request.GetLatestMediaRequest
|
import org.jellyfin.sdk.model.api.request.GetLatestMediaRequest
|
||||||
import org.jellyfin.sdk.model.serializer.toUUID
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -77,178 +78,19 @@ class HomeSettingsViewModel
|
||||||
it as ServerNavDrawerItem
|
it as ServerNavDrawerItem
|
||||||
Library(it.itemId, it.name, it.type)
|
Library(it.itemId, it.name, it.type)
|
||||||
}
|
}
|
||||||
_state.update { it.copy(libraries = libraries) }
|
val currentSettings =
|
||||||
|
homeSettingsService.currentSettings.first { it != HomePageResolvedSettings.EMPTY }
|
||||||
val localSettings =
|
Timber.v("currentSettings=%s", currentSettings)
|
||||||
try {
|
_state.update {
|
||||||
homeSettingsService.loadFromLocal()
|
it.copy(
|
||||||
} catch (ex: Exception) {
|
libraries = libraries,
|
||||||
Timber.e(ex)
|
rows = currentSettings.rows,
|
||||||
showToast(context, "Error loading settings: ${ex.localizedMessage}")
|
)
|
||||||
null
|
|
||||||
}
|
|
||||||
if (localSettings != null) {
|
|
||||||
val displays = localSettings.rows.map { convert(it) }
|
|
||||||
_state.update {
|
|
||||||
it.copy(rows = displays)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Or create default
|
|
||||||
val prefs =
|
|
||||||
userPreferencesService.getCurrent().appPreferences.homePagePreferences
|
|
||||||
val includedIds =
|
|
||||||
navDrawerItemRepository
|
|
||||||
.getFilteredNavDrawerItems(navDrawerItems)
|
|
||||||
.filter { it is ServerNavDrawerItem }
|
|
||||||
.mapIndexed { index, it ->
|
|
||||||
val id = (it as ServerNavDrawerItem).itemId
|
|
||||||
val name = libraries.firstOrNull { it.itemId == id }?.name
|
|
||||||
val title =
|
|
||||||
name?.let { context.getString(R.string.recently_added_in, it) }
|
|
||||||
?: context.getString(R.string.recently_added)
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
title,
|
|
||||||
HomeRowConfig.RecentlyAdded(
|
|
||||||
index,
|
|
||||||
id,
|
|
||||||
HomeRowViewOptions(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val continueWatchingRows =
|
|
||||||
if (prefs.combineContinueNext) {
|
|
||||||
listOf(
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.combine_continue_next),
|
|
||||||
HomeRowConfig.ContinueWatchingCombined(
|
|
||||||
includedIds.size + 1,
|
|
||||||
HomeRowViewOptions(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
listOf(
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.continue_watching),
|
|
||||||
HomeRowConfig.ContinueWatching(
|
|
||||||
includedIds.size + 1,
|
|
||||||
HomeRowViewOptions(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.next_up),
|
|
||||||
HomeRowConfig.NextUp(
|
|
||||||
includedIds.size + 2,
|
|
||||||
HomeRowViewOptions(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val rowConfig =
|
|
||||||
continueWatchingRows + includedIds +
|
|
||||||
// TODO remove after testing
|
|
||||||
listOf(
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
"Collection",
|
|
||||||
HomeRowConfig.ByParent(
|
|
||||||
id = 100,
|
|
||||||
parentId = "34ab6fd1f51c41bb014981f2e334f465".toUUID(),
|
|
||||||
recursive = true,
|
|
||||||
viewOptions = HomeRowViewOptions(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
"Playlist",
|
|
||||||
HomeRowConfig.ByParent(
|
|
||||||
id = 101,
|
|
||||||
parentId = "f94be36e9836127a0bccfc7843b19e5b".toUUID(),
|
|
||||||
recursive = true,
|
|
||||||
viewOptions = HomeRowViewOptions(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
_state.update {
|
|
||||||
it.copy(rows = rowConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchRowData()
|
fetchRowData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun convert(config: HomeRowConfig): HomeRowConfigDisplay =
|
|
||||||
when (config) {
|
|
||||||
is HomeRowConfig.ByParent -> {
|
|
||||||
val name =
|
|
||||||
api.userLibraryApi
|
|
||||||
.getItem(itemId = config.parentId)
|
|
||||||
.content.name ?: ""
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
name,
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is HomeRowConfig.ContinueWatching -> {
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.continue_watching),
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is HomeRowConfig.ContinueWatchingCombined -> {
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.combine_continue_next),
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is HomeRowConfig.Genres -> {
|
|
||||||
val name =
|
|
||||||
api.userLibraryApi
|
|
||||||
.getItem(itemId = config.parentId)
|
|
||||||
.content.name ?: ""
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.genres_in, name),
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is HomeRowConfig.GetItems -> {
|
|
||||||
HomeRowConfigDisplay(config.name, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
is HomeRowConfig.NextUp -> {
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.next_up),
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is HomeRowConfig.RecentlyAdded -> {
|
|
||||||
val name =
|
|
||||||
api.userLibraryApi
|
|
||||||
.getItem(itemId = config.parentId)
|
|
||||||
.content.name ?: ""
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.recently_added_in, name),
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is HomeRowConfig.RecentlyReleased -> {
|
|
||||||
val name =
|
|
||||||
api.userLibraryApi
|
|
||||||
.getItem(itemId = config.parentId)
|
|
||||||
.content.name ?: ""
|
|
||||||
HomeRowConfigDisplay(
|
|
||||||
context.getString(R.string.recently_released_in, name),
|
|
||||||
config,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateBackdrop(item: BaseItem) {
|
fun updateBackdrop(item: BaseItem) {
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
backdropService.submit(item)
|
backdropService.submit(item)
|
||||||
|
|
@ -709,14 +551,16 @@ class HomeSettingsViewModel
|
||||||
|
|
||||||
fun saveToLocal() {
|
fun saveToLocal() {
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
val rows = state.value.rows.map { it.config }
|
serverRepository.currentUser.value?.let { user ->
|
||||||
val settings = HomePageSettings(rows = rows)
|
val rows = state.value.rows.map { it.config }
|
||||||
try {
|
val settings = HomePageSettings(rows = rows)
|
||||||
homeSettingsService.saveToLocal(settings)
|
try {
|
||||||
showToast(context, context.getString(R.string.save), Toast.LENGTH_SHORT)
|
homeSettingsService.saveToLocal(user.id, settings)
|
||||||
} catch (ex: Exception) {
|
showToast(context, context.getString(R.string.save), Toast.LENGTH_SHORT)
|
||||||
Timber.e(ex)
|
} catch (ex: Exception) {
|
||||||
showToast(context, "Error saving: ${ex.localizedMessage}")
|
Timber.e(ex)
|
||||||
|
showToast(context, "Error saving: ${ex.localizedMessage}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue