mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 15:32:01 +00:00
update required stubs
This commit is contained in:
parent
fdde8ba1c2
commit
632d30c6c8
12 changed files with 204 additions and 9 deletions
|
|
@ -367,6 +367,19 @@ tasks.matching { it.name == "packageReleaseDistributionForCurrentOS" || it.name
|
||||||
finalizedBy(renameReleaseDmgArtifact)
|
finalizedBy(renameReleaseDmgArtifact)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val buildDesktopMpvBridge = tasks.register<Exec>("buildDesktopMpvBridge") {
|
||||||
|
onlyIf { System.getProperty("os.name").contains("Mac", ignoreCase = true) }
|
||||||
|
workingDir = rootProject.file("MPVKit")
|
||||||
|
commandLine("swift", "build", "-c", "release", "--product", "DesktopMPVBridge")
|
||||||
|
inputs.file(rootProject.file("MPVKit/Package.swift"))
|
||||||
|
inputs.dir(rootProject.file("MPVKit/Sources/DesktopMPVBridge"))
|
||||||
|
outputs.dir(rootProject.file("MPVKit/.build"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.matching { it.name == "run" || it.name == "desktopRun" }.configureEach {
|
||||||
|
dependsOn(buildDesktopMpvBridge)
|
||||||
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
exclude(group = "androidx.media3", module = "media3-exoplayer")
|
exclude(group = "androidx.media3", module = "media3-exoplayer")
|
||||||
exclude(group = "androidx.media3", module = "media3-ui")
|
exclude(group = "androidx.media3", module = "media3-ui")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.nuvio.app.core.ui
|
||||||
|
|
||||||
|
internal actual fun isLiquidGlassNativeTabBarSupported(): Boolean = false
|
||||||
|
|
||||||
|
internal actual fun publishLiquidGlassNativeTabBarEnabled(enabled: Boolean) = Unit
|
||||||
|
|
||||||
|
internal actual fun publishNativeTabBarVisible(visible: Boolean) = Unit
|
||||||
|
|
||||||
|
internal actual fun publishNativeSelectedTab(tabName: String) = Unit
|
||||||
|
|
||||||
|
internal actual fun publishNativeTabAccentColor(hexColor: String) = Unit
|
||||||
|
|
||||||
|
internal actual fun publishNativeProfileTabIcon(
|
||||||
|
name: String?,
|
||||||
|
avatarColorHex: String?,
|
||||||
|
avatarImageUrl: String?,
|
||||||
|
avatarBackgroundColorHex: String?,
|
||||||
|
) = Unit
|
||||||
|
|
@ -35,6 +35,11 @@ private val addonHttpClient: HttpClient = HttpClient.newBuilder()
|
||||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
private val addonHttpClientNoRedirects: HttpClient = HttpClient.newBuilder()
|
||||||
|
.connectTimeout(Duration.ofSeconds(60))
|
||||||
|
.followRedirects(HttpClient.Redirect.NEVER)
|
||||||
|
.build()
|
||||||
|
|
||||||
private const val maxRawResponseBodyChars = 1024 * 1024
|
private const val maxRawResponseBodyChars = 1024 * 1024
|
||||||
private const val truncationSuffix = "\n...[truncated]"
|
private const val truncationSuffix = "\n...[truncated]"
|
||||||
|
|
||||||
|
|
@ -54,6 +59,7 @@ private suspend fun executeRequest(
|
||||||
url: String,
|
url: String,
|
||||||
headers: Map<String, String>,
|
headers: Map<String, String>,
|
||||||
body: String,
|
body: String,
|
||||||
|
followRedirects: Boolean = true,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(Dispatchers.IO) {
|
||||||
val builder = HttpRequest.newBuilder()
|
val builder = HttpRequest.newBuilder()
|
||||||
.uri(URI.create(url))
|
.uri(URI.create(url))
|
||||||
|
|
@ -69,7 +75,8 @@ private suspend fun executeRequest(
|
||||||
builder.method(method.uppercase(), HttpRequest.BodyPublishers.noBody())
|
builder.method(method.uppercase(), HttpRequest.BodyPublishers.noBody())
|
||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
addonHttpClient.send(request, HttpResponse.BodyHandlers.ofString())
|
val client = if (followRedirects) addonHttpClient else addonHttpClientNoRedirects
|
||||||
|
client.send(request, HttpResponse.BodyHandlers.ofString())
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun executeTextRequest(
|
private suspend fun executeTextRequest(
|
||||||
|
|
@ -137,8 +144,9 @@ actual suspend fun httpRequestRaw(
|
||||||
url: String,
|
url: String,
|
||||||
headers: Map<String, String>,
|
headers: Map<String, String>,
|
||||||
body: String,
|
body: String,
|
||||||
|
followRedirects: Boolean,
|
||||||
): RawHttpResponse {
|
): RawHttpResponse {
|
||||||
val response = executeRequest(method, url, headers, body)
|
val response = executeRequest(method, url, headers, body, followRedirects)
|
||||||
val payload = response.body()
|
val payload = response.body()
|
||||||
val limitedPayload = if (payload.length > maxRawResponseBodyChars) {
|
val limitedPayload = if (payload.length > maxRawResponseBodyChars) {
|
||||||
payload.take(maxRawResponseBodyChars) + truncationSuffix
|
payload.take(maxRawResponseBodyChars) + truncationSuffix
|
||||||
|
|
@ -154,4 +162,4 @@ actual suspend fun httpRequestRaw(
|
||||||
key.lowercase() to values.joinToString(",")
|
key.lowercase() to values.joinToString(",")
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.nuvio.app.features.collection
|
||||||
|
|
||||||
|
import com.nuvio.app.core.storage.ProfileScopedKey
|
||||||
|
import com.nuvio.app.desktop.DesktopPreferences
|
||||||
|
|
||||||
|
internal actual object CollectionMobileSettingsStorage {
|
||||||
|
private const val preferencesName = "nuvio_collection_mobile_settings"
|
||||||
|
private const val payloadKey = "collection_mobile_settings_payload"
|
||||||
|
|
||||||
|
actual fun loadPayload(): String? =
|
||||||
|
DesktopPreferences.getString(preferencesName, ProfileScopedKey.of(payloadKey))
|
||||||
|
|
||||||
|
actual fun savePayload(payload: String) {
|
||||||
|
DesktopPreferences.putString(preferencesName, ProfileScopedKey.of(payloadKey), payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,8 @@ package com.nuvio.app.features.downloads
|
||||||
|
|
||||||
import com.nuvio.app.core.storage.ProfileScopedKey
|
import com.nuvio.app.core.storage.ProfileScopedKey
|
||||||
import com.nuvio.app.desktop.DesktopPreferences
|
import com.nuvio.app.desktop.DesktopPreferences
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
internal actual object DownloadsStorage {
|
internal actual object DownloadsStorage {
|
||||||
private const val preferencesName = "nuvio_downloads"
|
private const val preferencesName = "nuvio_downloads"
|
||||||
|
|
@ -33,12 +35,24 @@ internal actual object DownloadsPlatformDownloader {
|
||||||
actual fun removeFile(localFileUri: String?): Boolean = false
|
actual fun removeFile(localFileUri: String?): Boolean = false
|
||||||
|
|
||||||
actual fun removePartialFile(destinationFileName: String): Boolean = false
|
actual fun removePartialFile(destinationFileName: String): Boolean = false
|
||||||
|
|
||||||
|
actual fun resolveLocalFileUri(localFileUri: String?, destinationFileName: String): String? =
|
||||||
|
localFileUri
|
||||||
|
?.toLocalFileOrNull()
|
||||||
|
?.takeIf { it.exists() }
|
||||||
|
?.toURI()
|
||||||
|
?.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.toLocalFileOrNull(): File? =
|
||||||
|
runCatching {
|
||||||
|
if (startsWith("file://")) File(URI(this)) else File(this)
|
||||||
|
}.getOrNull()
|
||||||
|
|
||||||
internal actual object DownloadsLiveStatusPlatform {
|
internal actual object DownloadsLiveStatusPlatform {
|
||||||
actual fun onItemsChanged(items: List<DownloadItem>) = Unit
|
actual fun onItemsChanged(items: List<DownloadItem>) = Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
internal actual object DownloadsClock {
|
internal actual object DownloadsClock {
|
||||||
actual fun nowEpochMs(): Long = System.currentTimeMillis()
|
actual fun nowEpochMs(): Long = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,8 @@ internal actual object PlayerSettingsStorage {
|
||||||
private const val skipIntroEnabledKey = "skip_intro_enabled"
|
private const val skipIntroEnabledKey = "skip_intro_enabled"
|
||||||
private const val animeSkipEnabledKey = "animeskip_enabled"
|
private const val animeSkipEnabledKey = "animeskip_enabled"
|
||||||
private const val animeSkipClientIdKey = "animeskip_client_id"
|
private const val animeSkipClientIdKey = "animeskip_client_id"
|
||||||
|
private const val introDbApiKeyKey = "introdb_api_key"
|
||||||
|
private const val introSubmitEnabledKey = "intro_submit_enabled"
|
||||||
private const val streamAutoPlayNextEpisodeEnabledKey = "stream_auto_play_next_episode_enabled"
|
private const val streamAutoPlayNextEpisodeEnabledKey = "stream_auto_play_next_episode_enabled"
|
||||||
private const val streamAutoPlayPreferBingeGroupKey = "stream_auto_play_prefer_binge_group"
|
private const val streamAutoPlayPreferBingeGroupKey = "stream_auto_play_prefer_binge_group"
|
||||||
private const val nextEpisodeThresholdModeKey = "next_episode_threshold_mode"
|
private const val nextEpisodeThresholdModeKey = "next_episode_threshold_mode"
|
||||||
|
|
@ -496,6 +498,8 @@ internal actual object PlayerSettingsStorage {
|
||||||
skipIntroEnabledKey,
|
skipIntroEnabledKey,
|
||||||
animeSkipEnabledKey,
|
animeSkipEnabledKey,
|
||||||
animeSkipClientIdKey,
|
animeSkipClientIdKey,
|
||||||
|
introDbApiKeyKey,
|
||||||
|
introSubmitEnabledKey,
|
||||||
streamAutoPlayNextEpisodeEnabledKey,
|
streamAutoPlayNextEpisodeEnabledKey,
|
||||||
streamAutoPlayPreferBingeGroupKey,
|
streamAutoPlayPreferBingeGroupKey,
|
||||||
nextEpisodeThresholdModeKey,
|
nextEpisodeThresholdModeKey,
|
||||||
|
|
@ -661,6 +665,18 @@ internal actual object PlayerSettingsStorage {
|
||||||
saveString(animeSkipClientIdKey, clientId)
|
saveString(animeSkipClientIdKey, clientId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun loadIntroDbApiKey(): String? = loadString(introDbApiKeyKey)
|
||||||
|
|
||||||
|
actual fun saveIntroDbApiKey(apiKey: String) {
|
||||||
|
saveString(introDbApiKeyKey, apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun loadIntroSubmitEnabled(): Boolean? = loadBoolean(introSubmitEnabledKey)
|
||||||
|
|
||||||
|
actual fun saveIntroSubmitEnabled(enabled: Boolean) {
|
||||||
|
saveBoolean(introSubmitEnabledKey, enabled)
|
||||||
|
}
|
||||||
|
|
||||||
actual fun loadStreamAutoPlayNextEpisodeEnabled(): Boolean? = loadBoolean(streamAutoPlayNextEpisodeEnabledKey)
|
actual fun loadStreamAutoPlayNextEpisodeEnabled(): Boolean? = loadBoolean(streamAutoPlayNextEpisodeEnabledKey)
|
||||||
|
|
||||||
actual fun saveStreamAutoPlayNextEpisodeEnabled(enabled: Boolean) {
|
actual fun saveStreamAutoPlayNextEpisodeEnabled(enabled: Boolean) {
|
||||||
|
|
@ -726,6 +742,8 @@ internal actual object PlayerSettingsStorage {
|
||||||
loadSkipIntroEnabled()?.let { put(skipIntroEnabledKey, encodeSyncBoolean(it)) }
|
loadSkipIntroEnabled()?.let { put(skipIntroEnabledKey, encodeSyncBoolean(it)) }
|
||||||
loadAnimeSkipEnabled()?.let { put(animeSkipEnabledKey, encodeSyncBoolean(it)) }
|
loadAnimeSkipEnabled()?.let { put(animeSkipEnabledKey, encodeSyncBoolean(it)) }
|
||||||
loadAnimeSkipClientId()?.let { put(animeSkipClientIdKey, encodeSyncString(it)) }
|
loadAnimeSkipClientId()?.let { put(animeSkipClientIdKey, encodeSyncString(it)) }
|
||||||
|
loadIntroDbApiKey()?.let { put(introDbApiKeyKey, encodeSyncString(it)) }
|
||||||
|
loadIntroSubmitEnabled()?.let { put(introSubmitEnabledKey, encodeSyncBoolean(it)) }
|
||||||
loadStreamAutoPlayNextEpisodeEnabled()?.let { put(streamAutoPlayNextEpisodeEnabledKey, encodeSyncBoolean(it)) }
|
loadStreamAutoPlayNextEpisodeEnabled()?.let { put(streamAutoPlayNextEpisodeEnabledKey, encodeSyncBoolean(it)) }
|
||||||
loadStreamAutoPlayPreferBingeGroup()?.let { put(streamAutoPlayPreferBingeGroupKey, encodeSyncBoolean(it)) }
|
loadStreamAutoPlayPreferBingeGroup()?.let { put(streamAutoPlayPreferBingeGroupKey, encodeSyncBoolean(it)) }
|
||||||
loadNextEpisodeThresholdMode()?.let { put(nextEpisodeThresholdModeKey, encodeSyncString(it)) }
|
loadNextEpisodeThresholdMode()?.let { put(nextEpisodeThresholdModeKey, encodeSyncString(it)) }
|
||||||
|
|
@ -760,6 +778,8 @@ internal actual object PlayerSettingsStorage {
|
||||||
payload.decodeSyncBoolean(skipIntroEnabledKey)?.let(::saveSkipIntroEnabled)
|
payload.decodeSyncBoolean(skipIntroEnabledKey)?.let(::saveSkipIntroEnabled)
|
||||||
payload.decodeSyncBoolean(animeSkipEnabledKey)?.let(::saveAnimeSkipEnabled)
|
payload.decodeSyncBoolean(animeSkipEnabledKey)?.let(::saveAnimeSkipEnabled)
|
||||||
payload.decodeSyncString(animeSkipClientIdKey)?.let(::saveAnimeSkipClientId)
|
payload.decodeSyncString(animeSkipClientIdKey)?.let(::saveAnimeSkipClientId)
|
||||||
|
payload.decodeSyncString(introDbApiKeyKey)?.let(::saveIntroDbApiKey)
|
||||||
|
payload.decodeSyncBoolean(introSubmitEnabledKey)?.let(::saveIntroSubmitEnabled)
|
||||||
payload.decodeSyncBoolean(streamAutoPlayNextEpisodeEnabledKey)?.let(::saveStreamAutoPlayNextEpisodeEnabled)
|
payload.decodeSyncBoolean(streamAutoPlayNextEpisodeEnabledKey)?.let(::saveStreamAutoPlayNextEpisodeEnabled)
|
||||||
payload.decodeSyncBoolean(streamAutoPlayPreferBingeGroupKey)?.let(::saveStreamAutoPlayPreferBingeGroup)
|
payload.decodeSyncBoolean(streamAutoPlayPreferBingeGroupKey)?.let(::saveStreamAutoPlayPreferBingeGroup)
|
||||||
payload.decodeSyncString(nextEpisodeThresholdModeKey)?.let(::saveNextEpisodeThresholdMode)
|
payload.decodeSyncString(nextEpisodeThresholdModeKey)?.let(::saveNextEpisodeThresholdMode)
|
||||||
|
|
@ -819,7 +839,7 @@ internal actual object PlayerSettingsStorage {
|
||||||
actual fun LockPlayerToLandscape() = Unit
|
actual fun LockPlayerToLandscape() = Unit
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun EnterImmersivePlayerMode() = Unit
|
actual fun EnterImmersivePlayerMode(keepScreenAwake: Boolean) = Unit
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun ManagePlayerPictureInPicture(
|
actual fun ManagePlayerPictureInPicture(
|
||||||
|
|
@ -828,4 +848,4 @@ actual fun ManagePlayerPictureInPicture(
|
||||||
) = Unit
|
) = Unit
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun rememberPlayerGestureController(): PlayerGestureController? = null
|
actual fun rememberPlayerGestureController(): PlayerGestureController? = null
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.nuvio.app.features.profiles
|
||||||
|
|
||||||
|
import com.nuvio.app.desktop.DesktopPreferences
|
||||||
|
|
||||||
|
internal actual object AvatarStorage {
|
||||||
|
private const val preferencesName = "nuvio_avatar_cache"
|
||||||
|
private const val payloadKey = "avatar_catalog_payload"
|
||||||
|
|
||||||
|
actual fun loadPayload(): String? =
|
||||||
|
DesktopPreferences.getString(preferencesName, payloadKey)
|
||||||
|
|
||||||
|
actual fun savePayload(payload: String) {
|
||||||
|
DesktopPreferences.putString(preferencesName, payloadKey, payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.nuvio.app.features.profiles
|
||||||
|
|
||||||
|
internal actual object ProfileHoverHapticFeedback {
|
||||||
|
actual fun prepare() = Unit
|
||||||
|
actual fun perform() = Unit
|
||||||
|
actual fun release() = Unit
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.nuvio.app.features.profiles
|
||||||
|
|
||||||
|
import com.nuvio.app.desktop.DesktopPreferences
|
||||||
|
|
||||||
|
internal actual object ProfilePinCacheStorage {
|
||||||
|
private const val preferencesName = "nuvio_profile_pin_cache"
|
||||||
|
|
||||||
|
actual fun loadPayload(profileIndex: Int): String? =
|
||||||
|
DesktopPreferences.getString(preferencesName, payloadKey(profileIndex))
|
||||||
|
|
||||||
|
actual fun savePayload(profileIndex: Int, payload: String) {
|
||||||
|
DesktopPreferences.putString(preferencesName, payloadKey(profileIndex), payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun removePayload(profileIndex: Int) {
|
||||||
|
DesktopPreferences.remove(preferencesName, payloadKey(profileIndex))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun payloadKey(profileIndex: Int): String = "profile_pin_cache_$profileIndex"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.nuvio.app.features.profiles
|
||||||
|
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
internal actual object ProfilePinCrypto {
|
||||||
|
actual fun sha256Hex(value: String): String {
|
||||||
|
val digest = MessageDigest.getInstance("SHA-256").digest(value.encodeToByteArray())
|
||||||
|
return digest.joinToString(separator = "") { byte ->
|
||||||
|
byte.toUByte().toString(16).padStart(2, '0')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.buildJsonObject
|
import kotlinx.serialization.json.buildJsonObject
|
||||||
import kotlinx.serialization.json.put
|
import kotlinx.serialization.json.put
|
||||||
import nuvio.composeapp.generated.resources.Res
|
import nuvio.composeapp.generated.resources.Res
|
||||||
|
import nuvio.composeapp.generated.resources.introdb_favicon
|
||||||
import nuvio.composeapp.generated.resources.mdblist_logo
|
import nuvio.composeapp.generated.resources.mdblist_logo
|
||||||
import nuvio.composeapp.generated.resources.rating_tmdb
|
import nuvio.composeapp.generated.resources.rating_tmdb
|
||||||
import nuvio.composeapp.generated.resources.trakt_tv_favicon
|
import nuvio.composeapp.generated.resources.trakt_tv_favicon
|
||||||
|
|
@ -22,7 +23,14 @@ internal actual object ThemeSettingsStorage {
|
||||||
private const val preferencesName = "nuvio_theme_settings"
|
private const val preferencesName = "nuvio_theme_settings"
|
||||||
private const val selectedThemeKey = "selected_theme"
|
private const val selectedThemeKey = "selected_theme"
|
||||||
private const val amoledEnabledKey = "amoled_enabled"
|
private const val amoledEnabledKey = "amoled_enabled"
|
||||||
private val syncKeys = listOf(selectedThemeKey, amoledEnabledKey)
|
private const val liquidGlassNativeTabBarEnabledKey = "liquid_glass_native_tab_bar_enabled"
|
||||||
|
private const val selectedAppLanguageKey = "selected_app_language"
|
||||||
|
private val profileScopedSyncKeys = listOf(
|
||||||
|
selectedThemeKey,
|
||||||
|
amoledEnabledKey,
|
||||||
|
liquidGlassNativeTabBarEnabledKey,
|
||||||
|
)
|
||||||
|
private val globalSyncKeys = listOf(selectedAppLanguageKey)
|
||||||
|
|
||||||
actual fun loadSelectedTheme(): String? =
|
actual fun loadSelectedTheme(): String? =
|
||||||
DesktopPreferences.getString(preferencesName, ProfileScopedKey.of(selectedThemeKey))
|
DesktopPreferences.getString(preferencesName, ProfileScopedKey.of(selectedThemeKey))
|
||||||
|
|
@ -38,16 +46,43 @@ internal actual object ThemeSettingsStorage {
|
||||||
DesktopPreferences.putBoolean(preferencesName, ProfileScopedKey.of(amoledEnabledKey), enabled)
|
DesktopPreferences.putBoolean(preferencesName, ProfileScopedKey.of(amoledEnabledKey), enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual fun loadLiquidGlassNativeTabBarEnabled(): Boolean? =
|
||||||
|
DesktopPreferences.getBoolean(preferencesName, ProfileScopedKey.of(liquidGlassNativeTabBarEnabledKey))
|
||||||
|
|
||||||
|
actual fun saveLiquidGlassNativeTabBarEnabled(enabled: Boolean) {
|
||||||
|
DesktopPreferences.putBoolean(preferencesName, ProfileScopedKey.of(liquidGlassNativeTabBarEnabledKey), enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun loadSelectedAppLanguage(): String? {
|
||||||
|
val value = DesktopPreferences.getString(preferencesName, selectedAppLanguageKey)
|
||||||
|
if (value != null) return value
|
||||||
|
val legacy = DesktopPreferences.getString(preferencesName, ProfileScopedKey.of(selectedAppLanguageKey))
|
||||||
|
if (legacy != null) saveSelectedAppLanguage(legacy)
|
||||||
|
return legacy
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun saveSelectedAppLanguage(languageCode: String) {
|
||||||
|
DesktopPreferences.putString(preferencesName, selectedAppLanguageKey, languageCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun applySelectedAppLanguage(languageCode: String) = Unit
|
||||||
|
|
||||||
actual fun exportToSyncPayload(): JsonObject = buildJsonObject {
|
actual fun exportToSyncPayload(): JsonObject = buildJsonObject {
|
||||||
loadSelectedTheme()?.let { put(selectedThemeKey, encodeSyncString(it)) }
|
loadSelectedTheme()?.let { put(selectedThemeKey, encodeSyncString(it)) }
|
||||||
loadAmoledEnabled()?.let { put(amoledEnabledKey, encodeSyncBoolean(it)) }
|
loadAmoledEnabled()?.let { put(amoledEnabledKey, encodeSyncBoolean(it)) }
|
||||||
|
loadLiquidGlassNativeTabBarEnabled()?.let { put(liquidGlassNativeTabBarEnabledKey, encodeSyncBoolean(it)) }
|
||||||
|
loadSelectedAppLanguage()?.let { put(selectedAppLanguageKey, encodeSyncString(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
actual fun replaceFromSyncPayload(payload: JsonObject) {
|
||||||
syncKeys.forEach { DesktopPreferences.remove(preferencesName, ProfileScopedKey.of(it)) }
|
profileScopedSyncKeys.forEach { DesktopPreferences.remove(preferencesName, ProfileScopedKey.of(it)) }
|
||||||
|
globalSyncKeys.forEach { DesktopPreferences.remove(preferencesName, it) }
|
||||||
|
|
||||||
payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme)
|
payload.decodeSyncString(selectedThemeKey)?.let(::saveSelectedTheme)
|
||||||
payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled)
|
payload.decodeSyncBoolean(amoledEnabledKey)?.let(::saveAmoledEnabled)
|
||||||
|
payload.decodeSyncBoolean(liquidGlassNativeTabBarEnabledKey)?.let(::saveLiquidGlassNativeTabBarEnabled)
|
||||||
|
payload.decodeSyncString(selectedAppLanguageKey)?.let(::saveSelectedAppLanguage)
|
||||||
|
applySelectedAppLanguage(loadSelectedAppLanguage() ?: AppLanguage.ENGLISH.code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,4 +94,5 @@ internal actual fun integrationLogoPainter(logo: IntegrationLogo): Painter =
|
||||||
IntegrationLogo.Tmdb -> painterResource(Res.drawable.rating_tmdb)
|
IntegrationLogo.Tmdb -> painterResource(Res.drawable.rating_tmdb)
|
||||||
IntegrationLogo.Trakt -> painterResource(Res.drawable.trakt_tv_favicon)
|
IntegrationLogo.Trakt -> painterResource(Res.drawable.trakt_tv_favicon)
|
||||||
IntegrationLogo.MdbList -> painterResource(Res.drawable.mdblist_logo)
|
IntegrationLogo.MdbList -> painterResource(Res.drawable.mdblist_logo)
|
||||||
}
|
IntegrationLogo.IntroDb -> painterResource(Res.drawable.introdb_favicon)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.nuvio.app.features.trakt
|
||||||
|
|
||||||
|
import com.nuvio.app.core.storage.ProfileScopedKey
|
||||||
|
import com.nuvio.app.desktop.DesktopPreferences
|
||||||
|
|
||||||
|
internal actual object TraktSettingsStorage {
|
||||||
|
private const val preferencesName = "nuvio_trakt_settings"
|
||||||
|
private const val payloadKey = "trakt_settings_payload"
|
||||||
|
|
||||||
|
actual fun loadPayload(): String? =
|
||||||
|
DesktopPreferences.getString(preferencesName, ProfileScopedKey.of(payloadKey))
|
||||||
|
|
||||||
|
actual fun savePayload(payload: String) {
|
||||||
|
DesktopPreferences.putString(preferencesName, ProfileScopedKey.of(payloadKey), payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue