mirror of
https://github.com/FluxaMedia/fluxa.git
synced 2026-08-18 21:18:32 +00:00
Preserve profile names during Nuvio import
This commit is contained in:
parent
cda0c17b0a
commit
b0a68d6cee
6 changed files with 46 additions and 10 deletions
|
|
@ -123,6 +123,7 @@ class AndroidSettingsDataSource(
|
|||
displayName = profile.profileName?.takeIf { it.isNotBlank() } ?: profile.email,
|
||||
avatarUrl = profile.avatarUrl,
|
||||
isGuest = profile.isGuest,
|
||||
hasNuvio = !profile.nuvioAccessToken.isNullOrBlank(),
|
||||
hasTrakt = !profile.traktAccessToken.isNullOrBlank(),
|
||||
hasSimkl = !profile.simklAccessToken.isNullOrBlank(),
|
||||
hasAnilist = !profile.anilistAccessToken.isNullOrBlank(),
|
||||
|
|
|
|||
|
|
@ -177,12 +177,13 @@ internal fun TvProfileEditScreen(
|
|||
androidx.tv.material3.Button(
|
||||
onClick = {
|
||||
val profile = initialProfile?.copy(
|
||||
email = name,
|
||||
profileName = name,
|
||||
avatarUrl = selectedAvatarUrl,
|
||||
pinHash = resolvePinHash()
|
||||
) ?: UserProfile(
|
||||
id = java.util.UUID.randomUUID().toString(),
|
||||
email = name,
|
||||
profileName = name,
|
||||
authKey = "",
|
||||
isGuest = false,
|
||||
language = "en",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.fluxa.app.ui.catalog
|
||||
|
||||
import android.util.Log
|
||||
import com.fluxa.app.common.AppStrings
|
||||
import com.fluxa.app.data.local.UserProfile
|
||||
import com.fluxa.app.data.remote.NuvioSession
|
||||
|
|
@ -192,7 +193,8 @@ internal fun MobileNuvioLoginView(
|
|||
}
|
||||
importedProfile = result
|
||||
done = true
|
||||
} catch (_: Exception) {
|
||||
} catch (importError: Exception) {
|
||||
Log.e("NuvioImport", "Nuvio account import failed", importError)
|
||||
error = AppStrings.t(lang, "auth.error.network")
|
||||
submitting = false
|
||||
view = MobileNuvioView.Credentials
|
||||
|
|
|
|||
|
|
@ -87,13 +87,14 @@ fun MobileProfileEditScreen(
|
|||
TextButton(
|
||||
onClick = {
|
||||
val profile = initialProfile?.copy(
|
||||
email = name,
|
||||
profileName = name,
|
||||
avatarUrl = selectedAvatarUrl,
|
||||
pinHash = resolvePinHash(),
|
||||
biometricEnabled = resolveBiometricEnabled()
|
||||
) ?: UserProfile(
|
||||
id = java.util.UUID.randomUUID().toString(),
|
||||
email = name,
|
||||
profileName = name,
|
||||
authKey = "",
|
||||
isGuest = false,
|
||||
language = "en",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ data class UserProfile(
|
|||
val id: String,
|
||||
val email: String,
|
||||
val authKey: String,
|
||||
val profileName: String? = null,
|
||||
val colorArgb: Int = 0xFFFFFFFF.toInt(),
|
||||
val isGuest: Boolean = false,
|
||||
val avatarUrl: String? = null,
|
||||
|
|
@ -304,6 +305,7 @@ data class UserProfile(
|
|||
val safeLibraryCollections: List<LibraryUserCollection> get() = libraryCollections ?: homeFeedSettings?.libraryCollections.orEmpty()
|
||||
|
||||
val displayName: String get() = when {
|
||||
!profileName.isNullOrBlank() -> profileName
|
||||
isGuest -> if (email.isBlank() || email == "guest") "Guest" else email
|
||||
email.contains("@") -> email.substringBefore("@")
|
||||
else -> email
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.fluxa.app.data.repository
|
||||
|
||||
import android.util.Log
|
||||
import com.fluxa.app.data.local.LibraryUserCollection
|
||||
import com.fluxa.app.data.local.LibraryUserCollectionFolder
|
||||
import com.fluxa.app.data.local.LibraryCatalogSource
|
||||
|
|
@ -91,22 +92,29 @@ class NuvioAccountImportCoordinator(
|
|||
nuvioEmail = session.user?.email ?: baseProfile.email
|
||||
)
|
||||
val token = "Bearer ${session.accessToken}"
|
||||
profileManager.saveProfile(connectedProfile)
|
||||
profileManager.setLastActiveProfile(connectedProfile)
|
||||
watchlistManager.setActiveProfile(baseProfile.id)
|
||||
|
||||
var profile = connectedProfile
|
||||
val profiles = nuvioService.pullProfiles(token).requireBody()
|
||||
val profiles = importOrDefault(NuvioImportStep.PROFILE, emptyList()) {
|
||||
nuvioService.pullProfiles(token).requireBody()
|
||||
}
|
||||
val primary = profiles.firstOrNull { it.profileIndex == connectedProfile.nuvioProfileIndex }
|
||||
?: profiles.minByOrNull { it.profileIndex }
|
||||
val profileIndex = primary?.profileIndex ?: connectedProfile.nuvioProfileIndex ?: 1
|
||||
|
||||
if (primary != null) {
|
||||
val avatarUrl = primary.avatarUrl ?: primary.avatarId?.let { avatarId ->
|
||||
nuvioService.listAvatars().requireBody()
|
||||
importOrDefault(NuvioImportStep.PROFILE, emptyList()) {
|
||||
nuvioService.listAvatars().requireBody()
|
||||
}
|
||||
?.firstOrNull { it.id == avatarId }
|
||||
?.storagePath
|
||||
?.let { "${supabaseUrl}storage/v1/object/public/avatars/$it" }
|
||||
}
|
||||
profile = profile.copy(
|
||||
profileName = primary.name?.takeIf { it.isNotBlank() } ?: profile.profileName,
|
||||
avatarUrl = avatarUrl ?: profile.avatarUrl,
|
||||
nuvioProfileIndex = profileIndex
|
||||
)
|
||||
|
|
@ -115,14 +123,18 @@ class NuvioAccountImportCoordinator(
|
|||
}
|
||||
onStep(NuvioImportStep.PROFILE)
|
||||
|
||||
val addons = nuvioService.pullAddons(token, profileId = "eq.$profileIndex").requireBody()
|
||||
val addons = importOrDefault(NuvioImportStep.ADDONS, emptyList()) {
|
||||
nuvioService.pullAddons(token, profileId = "eq.$profileIndex").requireBody()
|
||||
}
|
||||
if (addons.isNotEmpty()) {
|
||||
val enabledUrls = addons.filter { it.enabled }.sortedBy { it.sortOrder }.map { it.url }
|
||||
profile = profile.copy(localAddons = (profile.localAddons.orEmpty() + enabledUrls).distinct())
|
||||
}
|
||||
onStep(NuvioImportStep.ADDONS)
|
||||
|
||||
val libraryItems = nuvioService.pullLibrary(token, mapOf("p_profile_id" to profileIndex, "p_limit" to 500, "p_offset" to 0)).requireBody()
|
||||
val libraryItems = importOrDefault(NuvioImportStep.LIBRARY, emptyList()) {
|
||||
nuvioService.pullLibrary(token, mapOf("p_profile_id" to profileIndex, "p_limit" to 500, "p_offset" to 0)).requireBody()
|
||||
}
|
||||
val metaById = libraryItems.associate { item ->
|
||||
item.contentId to Meta(
|
||||
id = item.contentId,
|
||||
|
|
@ -143,7 +155,9 @@ class NuvioAccountImportCoordinator(
|
|||
}
|
||||
onStep(NuvioImportStep.LIBRARY)
|
||||
|
||||
val watchProgress = nuvioService.pullWatchProgress(token, mapOf("p_profile_id" to profileIndex, "p_limit" to 200)).requireBody()
|
||||
val watchProgress = importOrDefault(NuvioImportStep.PROGRESS, emptyList()) {
|
||||
nuvioService.pullWatchProgress(token, mapOf("p_profile_id" to profileIndex, "p_limit" to 200)).requireBody()
|
||||
}
|
||||
for (entry in watchProgress) {
|
||||
val meta = metaById[entry.contentId] ?: run {
|
||||
val detail = runCatching {
|
||||
|
|
@ -176,7 +190,9 @@ class NuvioAccountImportCoordinator(
|
|||
}
|
||||
onStep(NuvioImportStep.PROGRESS)
|
||||
|
||||
val watchedItems = nuvioService.pullWatchedItems(token, mapOf("p_profile_id" to profileIndex, "p_page" to 1, "p_page_size" to 500)).requireBody()
|
||||
val watchedItems = importOrDefault(NuvioImportStep.HISTORY, emptyList()) {
|
||||
nuvioService.pullWatchedItems(token, mapOf("p_profile_id" to profileIndex, "p_page" to 1, "p_page_size" to 500)).requireBody()
|
||||
}
|
||||
val watchedBySeries = mutableMapOf<String, MutableSet<String>>()
|
||||
for (item in watchedItems) {
|
||||
val videoId = if (item.season != null && item.episode != null) {
|
||||
|
|
@ -191,7 +207,9 @@ class NuvioAccountImportCoordinator(
|
|||
}
|
||||
onStep(NuvioImportStep.HISTORY)
|
||||
|
||||
val collectionRows = nuvioService.pullCollections(token, mapOf("p_profile_id" to profileIndex)).requireBody()
|
||||
val collectionRows = importOrDefault(NuvioImportStep.COLLECTIONS, emptyList()) {
|
||||
nuvioService.pullCollections(token, mapOf("p_profile_id" to profileIndex)).requireBody()
|
||||
}
|
||||
val collections = collectionRows.firstOrNull()?.collectionsJson.orEmpty().map { collection ->
|
||||
LibraryUserCollection(
|
||||
id = collection.id ?: java.util.UUID.randomUUID().toString(),
|
||||
|
|
@ -232,6 +250,17 @@ class NuvioAccountImportCoordinator(
|
|||
profileManager.setLastActiveProfile(profile)
|
||||
return profile
|
||||
}
|
||||
|
||||
private suspend fun <T> importOrDefault(
|
||||
step: NuvioImportStep,
|
||||
fallback: T,
|
||||
call: suspend () -> T
|
||||
): T = try {
|
||||
call()
|
||||
} catch (error: Exception) {
|
||||
Log.w("NuvioImport", "Import step $step failed; continuing without it", error)
|
||||
fallback
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> Response<T>.requireBody(): T {
|
||||
|
|
|
|||
Loading…
Reference in a new issue