/* * Copyright (c) Double Symmetry GmbH * Commercial use requires a license. See https://rntp.dev/pricing */ package com.doublesymmetry.trackplayer.models import android.os.Bundle import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.ReadableMap import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.booleanOrNull import kotlinx.serialization.json.doubleOrNull import kotlinx.serialization.json.intOrNull import kotlinx.serialization.json.longOrNull /** Shared helpers for app-defined extras on MediaItem and BrowseItem. */ internal object MediaItemExtras { /** Key under MediaMetadata.extras used to store the app-provided extras Bundle. */ const val METADATA_KEY = "rntp.extras" fun parseBundle(map: ReadableMap): Bundle? = if (map.hasKey("extras")) map.getMap("extras")?.let { Arguments.toBundle(it) } else null /** JSON form for persisting extras inside the browse tree (@Serializable). */ fun parseJson(map: ReadableMap): JsonObject? = parseBundle(map)?.let { bundleToJsonObject(it) } fun jsonToBundle(json: JsonObject): Bundle = jsonObjectToBundle(json) fun attachToMetadataExtras(metadataExtras: Bundle, payload: Bundle?) { payload?.let { metadataExtras.putBundle(METADATA_KEY, it) } } private fun bundleToJsonObject(bundle: Bundle): JsonObject { val content = linkedMapOf() for (key in bundle.keySet()) { @Suppress("DEPRECATION") content[key] = bundleValueToJson(bundle.get(key)) } return JsonObject(content) } private fun bundleValueToJson(value: Any?): JsonElement = when (value) { null -> JsonNull is Boolean -> JsonPrimitive(value) is Int -> JsonPrimitive(value) is Long -> JsonPrimitive(value) is Double -> JsonPrimitive(value) is Float -> JsonPrimitive(value.toDouble()) is String -> JsonPrimitive(value) is Bundle -> bundleToJsonObject(value) is ArrayList<*> -> JsonArray(value.map { bundleValueToJson(it) }) else -> JsonPrimitive(value.toString()) } private fun jsonObjectToBundle(obj: JsonObject): Bundle { val bundle = Bundle() for ((key, value) in obj) { putJsonElement(bundle, key, value) } return bundle } private fun putJsonElement(bundle: Bundle, key: String, value: JsonElement) { when (value) { JsonNull -> Unit is JsonObject -> bundle.putBundle(key, jsonObjectToBundle(value)) is JsonArray -> { val list = ArrayList() for (element in value) { list.add(jsonElementToValue(element)) } @Suppress("DEPRECATION") bundle.putSerializable(key, list) } is JsonPrimitive -> { value.booleanOrNull?.let { bundle.putBoolean(key, it); return } value.longOrNull?.let { bundle.putLong(key, it); return } value.doubleOrNull?.let { bundle.putDouble(key, it); return } value.intOrNull?.let { bundle.putInt(key, it); return } bundle.putString(key, value.content) } } } private fun jsonElementToValue(element: JsonElement): Any? = when (element) { JsonNull -> null is JsonObject -> jsonObjectToBundle(element) is JsonArray -> element.map { jsonElementToValue(it) } is JsonPrimitive -> { element.booleanOrNull ?: element.longOrNull ?: element.doubleOrNull ?: element.intOrNull ?: element.content } } }