diff --git a/README.md b/README.md
index c2492c5d821..05dc88586d3 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,13 @@
# CloudStream
+⚠️ **DISCLAIMER: This application is an EXPERIMENT.**
+**The developer is NOT responsible for any improper or dangerous use of this application.**
+⛔ **Usage while driving is STRICTLY PROHIBITED.**
+
+**Always prioritize safe driving and adhere to local traffic laws.**
+**This software is provided "as is", without warranty of any kind.**
+
+
**⚠️ Warning: By default, this app doesn't provide any video sources; you have to install extensions to add functionality to the app.**
[](https://discord.gg/5Hus6fM)
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 8b2ed743622..a94d049d4de 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -63,9 +63,20 @@ android {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 67
- versionName = "4.6.2"
+ versionName = "4.6.19"
resValue("string", "commit_hash", getGitCommitHash())
+
+ resourceConfigurations.addAll(
+ listOf(
+ "en", "af", "am", "apc", "ar", "ars", "as", "az", "be", "bg", "bn", "ca", "ckb", "cs",
+ "de", "el", "eo", "es", "fa", "fil", "fr", "gl", "hi", "hr", "hu", "in", "it", "iw",
+ "ja", "kn", "ko", "lt", "lv", "mk", "ml", "ms", "mt", "my", "ne", "nl", "nn", "no",
+ "or", "pl", "pt", "pt-rBR", "ro", "ru", "sk", "so", "sv", "ta", "ti", "tl", "tr",
+ "uk", "ur", "vi", "zh", "zh-rTW"
+ )
+ )
+
manifestPlaceholders["target_sdk_version"] = libs.versions.targetSdk.get()
@@ -152,7 +163,15 @@ android {
resValues = true
}
+
+
namespace = "com.lagradost.cloudstream3"
+
+ sourceSets {
+ getByName("main") {
+ res.srcDirs("src/main/res", "src/main/res-car")
+ }
+ }
}
dependencies {
@@ -171,6 +190,7 @@ dependencies {
implementation(libs.fragment.ktx)
implementation(libs.bundles.lifecycle)
implementation(libs.bundles.navigation)
+ implementation(libs.car.app)
// Design & UI
implementation(libs.preference.ktx)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9e1bc9ac978..5ab1ff2db93 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -11,7 +11,7 @@
-
+
@@ -22,6 +22,10 @@
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
+
+
+
+
+
+
+
+
+
+
+
+
@@ -111,7 +127,7 @@
-->
@@ -231,6 +247,15 @@
android:foregroundServiceType="dataSync"
android:exported="false" />
+
+
+
+
+
+
+
? = null
@@ -1161,7 +1165,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener, BiometricCa
@Suppress("DEPRECATION_ERROR")
override fun onCreate(savedInstanceState: Bundle?) {
- app.initClient(this)
+
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
val errorFile = filesDir.resolve("last_error")
diff --git a/app/src/main/java/com/lagradost/cloudstream3/services/CSCarAppService.kt b/app/src/main/java/com/lagradost/cloudstream3/services/CSCarAppService.kt
new file mode 100644
index 00000000000..bc10bc4133e
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/services/CSCarAppService.kt
@@ -0,0 +1,16 @@
+package com.lagradost.cloudstream3.services
+
+import androidx.car.app.CarAppService
+import androidx.car.app.Session
+import androidx.car.app.validation.HostValidator
+import com.lagradost.cloudstream3.ui.car.CarSession
+
+class CSCarAppService : CarAppService() {
+ override fun createHostValidator(): HostValidator {
+ return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
+ }
+
+ override fun onCreateSession(): Session {
+ return CarSession()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt
index 42f68067b8c..dafd8141041 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/account/AccountSelectActivity.kt
@@ -36,8 +36,15 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding
import com.lagradost.cloudstream3.utils.UIHelper.openActivity
import com.lagradost.cloudstream3.utils.UIHelper.setNavigationBarColorCompat
+import android.content.Context
+import com.lagradost.cloudstream3.CloudStreamApp
+
class AccountSelectActivity : FragmentActivity(), BiometricCallback {
+ override fun attachBaseContext(base: Context?) {
+ super.attachBaseContext(CloudStreamApp.updateBaseContextLocale(base))
+ }
+
val accountViewModel: AccountViewModel by viewModels()
@SuppressLint("NotifyDataSetChanged")
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/AboutMeScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/AboutMeScreen.kt
new file mode 100644
index 00000000000..7e4c98a2780
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/AboutMeScreen.kt
@@ -0,0 +1,98 @@
+package com.lagradost.cloudstream3.ui.car
+
+import android.net.Uri
+import androidx.car.app.AppManager
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.SurfaceCallback
+import androidx.car.app.SurfaceContainer
+import androidx.car.app.model.Action
+import androidx.car.app.model.ActionStrip
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.Template
+import androidx.car.app.navigation.model.NavigationTemplate
+import androidx.core.graphics.drawable.IconCompat
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.media3.common.MediaItem
+import androidx.media3.common.Player
+import androidx.media3.exoplayer.ExoPlayer
+import com.lagradost.cloudstream3.R
+
+class AboutMeScreen(carContext: CarContext) : Screen(carContext), DefaultLifecycleObserver, SurfaceCallback {
+
+ private var player: ExoPlayer? = null
+
+ init {
+ lifecycle.addObserver(this)
+ }
+
+ override fun onCreate(owner: LifecycleOwner) {
+ super.onCreate(owner)
+ try {
+ player = ExoPlayer.Builder(carContext).build().apply {
+ val audioAttributes = androidx.media3.common.AudioAttributes.Builder()
+ .setUsage(androidx.media3.common.C.USAGE_MEDIA)
+ .setContentType(androidx.media3.common.C.AUDIO_CONTENT_TYPE_MOVIE)
+ .build()
+ setAudioAttributes(audioAttributes, true)
+
+ repeatMode = Player.REPEAT_MODE_ONE
+ volume = 1.0f
+ // android.resource://package/id
+ val uri = Uri.parse("android.resource://${carContext.packageName}/${R.raw.aboutme}")
+ setMediaItem(MediaItem.fromUri(uri))
+ prepare()
+ playWhenReady = true
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+
+ override fun onDestroy(owner: LifecycleOwner) {
+ player?.release()
+ player = null
+ super.onDestroy(owner)
+ }
+
+ override fun onStart(owner: LifecycleOwner) {
+ super.onStart(owner)
+ carContext.getCarService(AppManager::class.java).setSurfaceCallback(this)
+ player?.play()
+ }
+
+ override fun onStop(owner: LifecycleOwner) {
+ player?.pause()
+ carContext.getCarService(AppManager::class.java).setSurfaceCallback(null)
+ super.onStop(owner)
+ }
+
+ override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
+ val surface = surfaceContainer.surface
+ if (surface != null) {
+ player?.setVideoSurface(surface)
+ }
+ }
+
+
+
+ override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
+ player?.clearVideoSurface()
+ }
+
+ override fun onGetTemplate(): Template {
+ val backAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, androidx.appcompat.R.drawable.abc_ic_ab_back_material)).build())
+ .setOnClickListener { screenManager.pop() }
+ .build()
+
+ return NavigationTemplate.Builder()
+ .setActionStrip(
+ ActionStrip.Builder()
+ .addAction(backAction)
+ .build()
+ )
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/BookmarksScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/BookmarksScreen.kt
new file mode 100644
index 00000000000..6f70f191384
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/BookmarksScreen.kt
@@ -0,0 +1,104 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import com.lagradost.cloudstream3.R
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import com.lagradost.cloudstream3.TvType
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import kotlinx.coroutines.delay
+import coil3.SingletonImageLoader
+import coil3.request.ImageRequest
+import coil3.asDrawable
+
+class BookmarksScreen(carContext: CarContext) : Screen(carContext), androidx.lifecycle.DefaultLifecycleObserver {
+ private var itemList: ItemList? = null
+
+ init {
+ lifecycle.addObserver(this)
+ }
+
+ override fun onStart(owner: androidx.lifecycle.LifecycleOwner) {
+ loadBookmarks()
+ }
+
+ private fun loadBookmarks(retryCount: Int = 0) {
+ CoroutineScope(Dispatchers.IO).launch {
+ withContext(Dispatchers.Main) {
+ itemList = null
+ invalidate()
+ }
+ try {
+ // Fetch only Favorites (Heart icon)
+ val favorites = com.lagradost.cloudstream3.utils.DataStoreHelper.getAllFavorites()
+ .sortedByDescending { it.favoritesTime }
+
+ val builder = ItemList.Builder()
+ if (favorites.isEmpty()) {
+ builder.setNoItemsMessage(CarStrings.get(R.string.car_no_favorites_found))
+ } else {
+ favorites.forEach { item ->
+ builder.addItem(
+ Row.Builder()
+ .setTitle(item.name)
+ .setOnClickListener {
+ val type = item.type
+ if (type == TvType.TvSeries ||
+ type == TvType.Anime ||
+ type == TvType.Cartoon ||
+ type == TvType.OVA ||
+ type == TvType.AsianDrama ||
+ type == TvType.Documentary) {
+ screenManager.push(TvSeriesDetailScreen(carContext, item))
+ } else {
+ screenManager.push(DetailsScreen(carContext, item))
+ }
+ }
+ .build()
+ )
+ }
+ }
+
+ val builtList = builder.build()
+ withContext(Dispatchers.Main) {
+ itemList = builtList
+ invalidate()
+ }
+ } catch (e: Exception) {
+ if (retryCount < 3) {
+ delay(3000)
+ loadBookmarks(retryCount + 1)
+ } else {
+ withContext(Dispatchers.Main) {
+ itemList = ItemList.Builder()
+ .addItem(
+ Row.Builder()
+ .setTitle("${CarStrings.get(R.string.car_error)}: ${e.message}")
+ .setOnClickListener { loadBookmarks() }
+ .build()
+ )
+ .build()
+ invalidate()
+ }
+ }
+ }
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ return ListTemplate.Builder()
+ .setSingleList(itemList ?: ItemList.Builder().setNoItemsMessage(CarStrings.get(R.string.car_loading)).build())
+ .setTitle(CarStrings.get(R.string.car_favorites))
+ .setHeaderAction(Action.BACK)
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarHelper.kt
new file mode 100644
index 00000000000..78615a7e113
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarHelper.kt
@@ -0,0 +1,87 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.model.CarColor
+import androidx.car.app.model.ForegroundCarColorSpan
+import androidx.car.app.model.Pane
+import androidx.car.app.model.Row
+import android.text.SpannableString
+import android.text.Spanned
+import com.lagradost.cloudstream3.LoadResponse
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import com.lagradost.cloudstream3.utils.DataStoreHelper.FavoritesData
+
+object CarHelper {
+
+ fun toggleFavorite(
+ carContext: CarContext,
+ fullDetails: LoadResponse?,
+ isFavorite: Boolean,
+ onFavoriteChanged: (Boolean) -> Unit
+ ) {
+ val details = fullDetails ?: return
+ val api = getApiFromNameNull(details.apiName) ?: return
+ val id = details.url.replace(api.mainUrl, "").replace("/", "").hashCode()
+
+ if (isFavorite) {
+ DataStoreHelper.removeFavoritesData(id)
+ onFavoriteChanged(false)
+ androidx.car.app.CarToast.makeText(carContext, CarStrings.get(R.string.car_removed_from_favorites), androidx.car.app.CarToast.LENGTH_SHORT).show()
+ } else {
+ val favoritesData = FavoritesData(
+ favoritesTime = System.currentTimeMillis(),
+ id = id,
+ latestUpdatedTime = System.currentTimeMillis(),
+ name = details.name,
+ url = details.url,
+ apiName = details.apiName,
+ type = details.type,
+ posterUrl = details.posterUrl,
+ year = details.year,
+ quality = null,
+ posterHeaders = details.posterHeaders,
+ plot = details.plot,
+ score = details.score,
+ tags = details.tags
+ )
+ DataStoreHelper.setFavoritesData(id, favoritesData)
+ onFavoriteChanged(true)
+ androidx.car.app.CarToast.makeText(carContext, CarStrings.get(R.string.car_added_to_favorites), androidx.car.app.CarToast.LENGTH_SHORT).show()
+ }
+ }
+
+ fun addPlotAndCast(paneBuilder: Pane.Builder, details: LoadResponse) {
+ // Plot Row
+ if (!details.plot.isNullOrEmpty()) {
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(CarStrings.get(R.string.car_plot))
+ .addText(details.plot!!)
+ .build()
+ )
+ }
+
+ // Cast Row
+ if (!details.actors.isNullOrEmpty()) {
+ val castList = details.actors!!.groupBy { it.roleString }.flatMap { it.value }.take(5).joinToString(", ") { it.actor.name }
+ if (castList.isNotEmpty()) {
+ val s = SpannableString(castList)
+ s.setSpan(
+ ForegroundCarColorSpan.create(CarColor.SECONDARY),
+ 0,
+ s.length,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(CarStrings.get(R.string.car_cast))
+ .addText(s)
+ .build()
+ )
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarSession.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarSession.kt
new file mode 100644
index 00000000000..0207176830b
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarSession.kt
@@ -0,0 +1,31 @@
+package com.lagradost.cloudstream3.ui.car
+
+import android.content.Intent
+import android.util.Log
+import androidx.car.app.Screen
+import androidx.car.app.Session
+import androidx.lifecycle.coroutineScope
+import com.lagradost.cloudstream3.plugins.PluginManager
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+class CarSession : Session() {
+ companion object {
+ private const val TAG = "CarSession"
+ }
+
+ init {
+ lifecycle.coroutineScope.launch(Dispatchers.IO) {
+ try {
+ @Suppress("DEPRECATION_ERROR")
+ PluginManager.___DO_NOT_CALL_FROM_A_PLUGIN_loadAllOnlinePlugins(carContext)
+ } catch (e: Exception) {
+ Log.e(TAG, "Error loading plugins", e)
+ }
+ }
+ }
+
+ override fun onCreateScreen(intent: Intent): Screen {
+ return MainCarScreen(carContext)
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarStrings.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarStrings.kt
new file mode 100644
index 00000000000..3d27aab57f4
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CarStrings.kt
@@ -0,0 +1,51 @@
+package com.lagradost.cloudstream3.ui.car
+
+import android.content.Context
+import android.content.res.Configuration
+import android.content.res.Resources
+import androidx.annotation.StringRes
+import androidx.preference.PreferenceManager
+import com.lagradost.cloudstream3.R
+import java.util.Locale
+
+/**
+ * Singleton helper for Android Auto localization.
+ * Wraps Android Resources to support overriding the language based on app settings,
+ * independent of the system locale.
+ */
+object CarStrings {
+ private var resources: Resources? = null
+
+ /**
+ * Initialize the helper with the application context.
+ * Call this in Application.onCreate().
+ */
+ fun init(context: Context) {
+ // Read user preference
+ val prefs = PreferenceManager.getDefaultSharedPreferences(context)
+ val localeCode = prefs.getString(context.getString(R.string.locale_key), null)
+
+ // If a specific locale is set (e.g. "it"), force it.
+ // Otherwise, use system default.
+ if (!localeCode.isNullOrEmpty()) {
+ val locale = Locale(localeCode)
+ val config = Configuration(context.resources.configuration)
+ config.setLocale(locale)
+ resources = context.createConfigurationContext(config).resources
+ } else {
+ resources = context.resources
+ }
+ }
+
+ /**
+ * Get a localized string by Resource ID.
+ */
+ fun get(@StringRes id: Int, vararg args: Any): String {
+ val res = resources ?: throw IllegalStateException("CarStrings not initialized! Call init() in Application.onCreate()")
+ return if (args.isEmpty()) {
+ res.getString(id)
+ } else {
+ res.getString(id, *args)
+ }
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/CategoryScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CategoryScreen.kt
new file mode 100644
index 00000000000..0c0cc4daf65
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/CategoryScreen.kt
@@ -0,0 +1,108 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import androidx.core.graphics.drawable.toBitmap
+import coil3.asDrawable
+import coil3.request.ImageRequest
+import coil3.size.Scale
+import coil3.size.Precision
+import coil3.SingletonImageLoader
+import com.lagradost.cloudstream3.HomePageList
+import com.lagradost.cloudstream3.R
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+
+class CategoryScreen(
+ carContext: CarContext,
+ private val homePageList: HomePageList
+) : Screen(carContext) {
+
+ private val scope = CoroutineScope(Dispatchers.IO + Job())
+ private val iconCache = mutableMapOf()
+ private val loadingUrls = mutableSetOf()
+
+ private fun loadIcon(imageUrl: String) {
+ if (loadingUrls.contains(imageUrl)) return
+ loadingUrls.add(imageUrl)
+
+ scope.launch {
+ try {
+ val request = ImageRequest.Builder(carContext)
+ .data(imageUrl)
+ .size(256, 256)
+ .build()
+ val result = SingletonImageLoader.get(carContext).execute(request)
+ val bitmap = result.image?.asDrawable(carContext.resources)?.toBitmap()
+ if (bitmap != null) {
+ val icon = CarIcon.Builder(IconCompat.createWithBitmap(bitmap)).build()
+ synchronized(iconCache) {
+ iconCache[imageUrl] = icon
+ }
+ invalidate()
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ } finally {
+ loadingUrls.remove(imageUrl)
+ }
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ val listBuilder = ItemList.Builder()
+
+ homePageList.list.forEach { item ->
+ val imageUrl = item.posterUrl
+
+ // Check cache or trigger load
+ val icon = if (!imageUrl.isNullOrEmpty()) {
+ synchronized(iconCache) {
+ iconCache[imageUrl]
+ } ?: run {
+ loadIcon(imageUrl)
+ CarIcon.Builder(IconCompat.createWithResource(carContext, R.mipmap.ic_launcher)).build()
+ }
+ } else {
+ CarIcon.Builder(IconCompat.createWithResource(carContext, R.mipmap.ic_launcher)).build()
+ }
+
+ // Use Row with LARGE image for maximum visibility in a list
+ val row = Row.Builder()
+ .setTitle(if (item.name.isNullOrEmpty()) "Untitled" else item.name)
+ .setImage(icon, Row.IMAGE_TYPE_LARGE)
+ .setOnClickListener {
+ val type = item.type
+ if (type == com.lagradost.cloudstream3.TvType.TvSeries ||
+ type == com.lagradost.cloudstream3.TvType.Anime ||
+ type == com.lagradost.cloudstream3.TvType.Cartoon ||
+ type == com.lagradost.cloudstream3.TvType.OVA ||
+ type == com.lagradost.cloudstream3.TvType.AsianDrama ||
+ type == com.lagradost.cloudstream3.TvType.Documentary) {
+ screenManager.push(TvSeriesDetailScreen(carContext, item))
+ } else if (type == com.lagradost.cloudstream3.TvType.Live) {
+ screenManager.push(PlayerCarScreen(carContext, item = item))
+ } else {
+ screenManager.push(DetailsScreen(carContext, item))
+ }
+ }
+ .build()
+ listBuilder.addItem(row)
+ }
+
+ return ListTemplate.Builder()
+ .setTitle(homePageList.name)
+ .setHeaderAction(Action.BACK)
+ .setSingleList(listBuilder.build())
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/DetailsScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/DetailsScreen.kt
new file mode 100644
index 00000000000..58d8d45d0e1
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/DetailsScreen.kt
@@ -0,0 +1,270 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.CarColor
+import androidx.car.app.model.Pane
+import androidx.car.app.model.PaneTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import com.lagradost.cloudstream3.SearchResponse
+import com.lagradost.cloudstream3.TvSeriesLoadResponse
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.TvType
+import com.lagradost.cloudstream3.newTvSeriesSearchResponse
+import com.lagradost.cloudstream3.ui.player.DownloadedPlayerActivity
+import android.content.Intent
+import android.net.Uri
+import android.util.Log
+import android.text.SpannableString
+import android.text.Spanned
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ForegroundCarColorSpan
+import androidx.core.graphics.drawable.IconCompat
+import androidx.core.graphics.drawable.toBitmap
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import coil3.asDrawable
+import coil3.request.ImageRequest
+import coil3.SingletonImageLoader
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.LoadResponse
+import com.lagradost.cloudstream3.mvvm.Resource
+import com.lagradost.cloudstream3.ui.APIRepository
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import com.lagradost.cloudstream3.ui.result.ResultViewModel2
+import com.lagradost.cloudstream3.utils.DataStoreHelper.FavoritesData
+import com.lagradost.cloudstream3.utils.ExtractorLink
+import com.lagradost.cloudstream3.MovieLoadResponse
+
+class DetailsScreen(
+ carContext: CarContext,
+ private val item: SearchResponse
+) : Screen(carContext) {
+
+ private var fullDetails: LoadResponse? = null
+ private var isLoading = true
+ private var errorMessage: String? = null
+
+ private var posterBitmap: android.graphics.Bitmap? = null
+ private var isFavorite: Boolean = false
+ private val scope = CoroutineScope(Dispatchers.IO + Job())
+
+ // Selected source for playback
+ private var selectedSource: ExtractorLink? = null
+
+ init {
+ loadData()
+ }
+
+ private fun loadData() {
+ scope.launch {
+ try {
+ // Load Image
+ if (!item.posterUrl.isNullOrEmpty()) {
+ try {
+ val request = ImageRequest.Builder(carContext)
+ .data(item.posterUrl)
+ .data(item.posterUrl)
+ .size(600, 900) // Higher resolution for hero image
+ .build()
+ val result = SingletonImageLoader.get(carContext).execute(request)
+ posterBitmap = result.image?.asDrawable(carContext.resources)?.toBitmap()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+
+ // Load Details
+ val api = getApiFromNameNull(item.apiName)
+ if (api != null) {
+ val repo = APIRepository(api)
+ when (val result = repo.load(item.url)) {
+ is Resource.Success -> {
+ fullDetails = result.value
+
+ // Redirect if Type Mismatch (e.g. Provider reported Movie, but it's a Series)
+ // We check if the response is structurally a Series (has episodes etc)
+ // This fixes providers that return "Movie" type but provide series data.
+ if (result.value is TvSeriesLoadResponse) {
+ val detectedType = result.value.type
+ // If the provider says "Movie" but sends TvSeriesLoadResponse, force TvSeries type
+ val isTv = detectedType == TvType.TvSeries ||
+ detectedType == TvType.Anime ||
+ detectedType == TvType.Cartoon ||
+ detectedType == TvType.OVA ||
+ detectedType == TvType.AsianDrama ||
+ detectedType == TvType.Documentary
+
+ val finalType = if (isTv) detectedType else TvType.TvSeries
+
+ val correctItem = api.newTvSeriesSearchResponse(
+ name = result.value.name,
+ url = result.value.url,
+ type = finalType,
+ ) {
+ this.posterUrl = result.value.posterUrl ?: item.posterUrl
+ }
+ withContext(Dispatchers.Main) {
+ screenManager.pop()
+ screenManager.push(TvSeriesDetailScreen(carContext, correctItem))
+ }
+ return@launch
+ }
+
+ // Check ID logic matches standard
+ val id = result.value.url.replace(api.mainUrl, "").replace("/", "").hashCode()
+ isFavorite = DataStoreHelper.getFavoritesData(id) != null
+ isLoading = false
+ }
+ is Resource.Failure -> {
+ errorMessage = result.errorString
+ isLoading = false
+ }
+ is Resource.Loading -> {}
+ }
+ } else {
+ errorMessage = CarStrings.get(R.string.car_provider_not_found)
+ isLoading = false
+ }
+ } catch (e: Exception) {
+ errorMessage = e.message
+ isLoading = false
+ }
+ invalidate()
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ val paneBuilder = Pane.Builder()
+
+ if (isLoading) {
+ paneBuilder.setLoading(true)
+ } else {
+ buildContent(paneBuilder)
+ }
+
+ buildActions(paneBuilder)
+
+ return PaneTemplate.Builder(paneBuilder.build())
+ .setTitle(fullDetails?.name ?: item.name)
+ .setHeaderAction(Action.BACK)
+ .build()
+ }
+
+ private fun buildContent(paneBuilder: Pane.Builder) {
+ val details = fullDetails
+
+ // Header: Title
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(details?.name ?: item.name)
+ .build()
+ )
+
+ // Set Hero Image on the Pane itself for maximum size
+ posterBitmap?.let {
+ paneBuilder.setImage(CarIcon.Builder(IconCompat.createWithBitmap(it)).build())
+ } ?: run {
+ paneBuilder.setImage(CarIcon.Builder(IconCompat.createWithResource(carContext, R.mipmap.ic_launcher)).build())
+ }
+
+ if (details != null) {
+ // Meta Row: Year • Rating • Duration
+ val metaStringBuilder = StringBuilder()
+ details.year?.let { metaStringBuilder.append("$it") }
+
+ // Add Score if available
+ val score = details.score
+ if (score != null) {
+ if (metaStringBuilder.isNotEmpty()) metaStringBuilder.append(" • ")
+ metaStringBuilder.append(String.format("%.1f/10", score.toDouble(10)))
+ }
+
+ details.duration?.let {
+ if (metaStringBuilder.isNotEmpty()) metaStringBuilder.append(" • ")
+ metaStringBuilder.append("${it}m")
+ }
+
+ if (metaStringBuilder.isNotEmpty()) {
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(metaStringBuilder.toString())
+ .build()
+ )
+ }
+
+ // Plot and Cast
+ CarHelper.addPlotAndCast(paneBuilder, details)
+ } else if (errorMessage != null) {
+ paneBuilder.addRow(Row.Builder().setTitle("${CarStrings.get(R.string.car_error)}: $errorMessage").build())
+ }
+ }
+
+ private fun buildActions(paneBuilder: Pane.Builder) {
+ // Play Button: White background with Black Icon
+ val playIcon = IconCompat.createWithResource(carContext, android.R.drawable.ic_media_play)
+ .setTint(android.graphics.Color.BLACK)
+
+ val playAction = Action.Builder()
+ .setIcon(CarIcon.Builder(playIcon).build())
+ .setBackgroundColor(CarColor.createCustom(android.graphics.Color.WHITE, android.graphics.Color.WHITE))
+ .setOnClickListener {
+ screenManager.push(PlayerCarScreen(
+ carContext = carContext,
+ item = item,
+ preSelectedSource = selectedSource
+ ))
+ }
+ .build()
+
+ // Source Selection Button
+ val sourceIcon = IconCompat.createWithResource(carContext, R.drawable.ic_baseline_source_24)
+
+ val sourceActionTitle = if (selectedSource != null) {
+ selectedSource!!.name
+ } else {
+ CarStrings.get(R.string.car_source)
+ }
+
+ val sourceAction = Action.Builder()
+ .setIcon(CarIcon.Builder(sourceIcon).build())
+ .setTitle(sourceActionTitle)
+ .setOnClickListener {
+ val details = fullDetails
+ val dataUrl = when (details) {
+ is MovieLoadResponse -> details.dataUrl
+ else -> details?.url
+ }
+ if (dataUrl != null && details != null) {
+ screenManager.push(
+ SourceSelectionScreen(
+ carContext = carContext,
+ apiName = details.apiName,
+ dataUrl = dataUrl,
+ currentSourceUrl = selectedSource?.url,
+ onSourceSelected = { source ->
+ selectedSource = source
+ invalidate()
+ }
+ )
+ )
+ }
+ }
+ .build()
+
+ paneBuilder.addAction(playAction)
+ paneBuilder.addAction(sourceAction)
+ }
+
+ private fun toggleFavorite() {
+ CarHelper.toggleFavorite(carContext, fullDetails, isFavorite) { newStatus ->
+ isFavorite = newStatus
+ invalidate()
+ }
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/DownloadsScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/DownloadsScreen.kt
new file mode 100644
index 00000000000..424d3bbb116
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/DownloadsScreen.kt
@@ -0,0 +1,213 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import com.lagradost.cloudstream3.utils.VideoDownloadHelper
+import com.lagradost.cloudstream3.utils.VideoDownloadManager
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.utils.DataStore.getKey
+import com.lagradost.cloudstream3.utils.DataStore.getKeys
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
+import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
+import com.lagradost.cloudstream3.utils.DataStore.getFolderName
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import com.lagradost.cloudstream3.isEpisodeBased
+
+class DownloadsScreen(
+ carContext: CarContext,
+ private val parentId: Int? = null,
+ private val headerName: String? = null
+) : Screen(carContext) {
+ private val scope = CoroutineScope(Dispatchers.IO)
+ private var itemList: ItemList? = null
+
+ init {
+ loadContent()
+ }
+
+ private fun loadContent() {
+ if (parentId != null) {
+ loadEpisodes(parentId)
+ } else {
+ loadHeaders()
+ }
+ }
+
+ private fun loadEpisodes(id: Int) {
+ scope.launch {
+ val context = carContext
+ val children = context.getKeys(DOWNLOAD_EPISODE_CACHE)
+ .mapNotNull { context.getKey(it) }
+ .filter { it.parentId == id }
+ .filter {
+ val info = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, it.id)
+ (info?.fileLength ?: 0L) > 0
+ }
+ .sortedWith(compareBy({ it.season }, { it.episode }))
+
+ val builder = ItemList.Builder()
+
+ if (children.isEmpty()) {
+ builder.setNoItemsMessage(CarStrings.get(R.string.car_no_episodes_found))
+ } else {
+ children.forEach { episode ->
+ val name = "S${episode.season}:E${episode.episode} - ${episode.name ?: CarStrings.get(R.string.car_episode)}"
+ builder.addItem(
+ Row.Builder()
+ .setTitle(name)
+ .setOnClickListener {
+ playEpisode(episode.id, id)
+ }
+ .build()
+ )
+ }
+ }
+
+ val builtList = builder.build()
+ withContext(Dispatchers.Main) {
+ itemList = builtList
+ invalidate()
+ }
+ }
+ }
+
+ private fun loadHeaders() {
+ scope.launch {
+ val headers = carContext.getKeys(DOWNLOAD_HEADER_CACHE)
+ .mapNotNull { carContext.getKey(it) }
+ .sortedBy { it.name }
+
+ val builder = ItemList.Builder()
+
+ // Filter and find valid items
+ val validHeaders = headers.filter { header ->
+ val context = carContext
+ val id = header.id
+
+ // Get all children (episodes or movies) for this header
+ val children = context.getKeys(DOWNLOAD_EPISODE_CACHE)
+ .mapNotNull { context.getKey(it) }
+ .filter { it.parentId == id }
+
+ // Check if AT LEAST ONE child is valid (> 0 bytes)
+ children.any { child ->
+ val info = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, child.id)
+ (info?.fileLength ?: 0L) > 0
+ }
+ }
+
+ if (validHeaders.isEmpty()) {
+ builder.setNoItemsMessage(CarStrings.get(R.string.car_no_downloads_found))
+ } else {
+ validHeaders.forEach { header ->
+ val lastWatched = DataStoreHelper.getLastWatched(header.id)
+ val subtitle = if (lastWatched != null && lastWatched.season != null && lastWatched.episode != null) {
+ "S${lastWatched.season}E${lastWatched.episode}"
+ } else {
+ null
+ }
+
+ val rowBuilder = Row.Builder()
+ .setTitle(header.name)
+ .setOnClickListener {
+ onHeaderClick(header)
+ }
+
+ if (subtitle != null) {
+ rowBuilder.addText(subtitle)
+ }
+
+ builder.addItem(rowBuilder.build())
+ }
+ }
+
+ val builtList = builder.build()
+ withContext(Dispatchers.Main) {
+ itemList = builtList
+ invalidate()
+ }
+ }
+ }
+
+ private fun playEpisode(episodeId: Int, parentId: Int) {
+ scope.launch {
+ val context = carContext
+ val fileInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, episodeId)
+ if (fileInfo?.path == null) {
+ withContext(Dispatchers.Main) {
+ androidx.car.app.CarToast.makeText(carContext, CarStrings.get(R.string.car_file_not_found), androidx.car.app.CarToast.LENGTH_SHORT).show()
+ }
+ return@launch
+ }
+
+ // Get saved resume position
+ val savedPos = DataStoreHelper.getViewPos(episodeId)
+ val startTime = savedPos?.position ?: 0L
+
+ withContext(Dispatchers.Main) {
+ screenManager.push(
+ PlayerCarScreen(
+ carContext = carContext,
+ fileUri = fileInfo.path.toString(),
+ videoId = episodeId,
+ parentId = parentId,
+ startTime = startTime
+ )
+ )
+ }
+ }
+ }
+
+ private fun onHeaderClick(header: VideoDownloadHelper.DownloadHeaderCached) {
+ scope.launch {
+ val context = carContext
+ val id = header.id
+
+ // Get children
+ val children = context.getKeys(DOWNLOAD_EPISODE_CACHE)
+ .mapNotNull { context.getKey(it) }
+ .filter { it.parentId == id }
+ .filter {
+ val info = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, it.id)
+ (info?.fileLength ?: 0L) > 0
+ }
+
+ if (children.isEmpty()) {
+ withContext(Dispatchers.Main) {
+ androidx.car.app.CarToast.makeText(carContext, CarStrings.get(R.string.car_no_valid_episode), androidx.car.app.CarToast.LENGTH_SHORT).show()
+ }
+ return@launch
+ }
+
+ if (header.type.isEpisodeBased()) {
+ // Series: Always go to episode list
+ withContext(Dispatchers.Main) {
+ screenManager.push(DownloadsScreen(carContext, id, header.name))
+ }
+ } else {
+ // Movie: Just pick the first/only one
+ val episodeId = children.firstOrNull()?.id
+ if (episodeId != null) {
+ playEpisode(episodeId, id)
+ }
+ }
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ return ListTemplate.Builder()
+ .setTitle(headerName ?: CarStrings.get(R.string.car_downloads))
+ .setHeaderAction(Action.BACK)
+ .setSingleList(itemList ?: ItemList.Builder().setNoItemsMessage(CarStrings.get(R.string.car_loading)).build())
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/EpisodeDetailScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/EpisodeDetailScreen.kt
new file mode 100644
index 00000000000..84060f26909
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/EpisodeDetailScreen.kt
@@ -0,0 +1,155 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.CarColor
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.Pane
+import androidx.car.app.model.PaneTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import androidx.core.graphics.drawable.toBitmap
+import coil3.asDrawable
+import coil3.request.ImageRequest
+import coil3.SingletonImageLoader
+import com.lagradost.cloudstream3.Episode
+import com.lagradost.cloudstream3.TvSeriesLoadResponse
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
+import com.lagradost.cloudstream3.utils.ExtractorLink
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+
+class EpisodeDetailScreen(
+ carContext: CarContext,
+ private val seriesDetails: TvSeriesLoadResponse,
+ private val episode: Episode,
+ private val playlist: List
+) : Screen(carContext) {
+
+ private val scope = CoroutineScope(Dispatchers.IO + Job())
+ private var posterBitmap: android.graphics.Bitmap? = null
+ private var isLoadingImage = true
+
+ // Selected source for playback
+ private var selectedSource: ExtractorLink? = null
+
+ init {
+ loadImage()
+ }
+
+ private fun loadImage() {
+ scope.launch {
+ // Try episode poster first, then series poster
+ val url = episode.posterUrl ?: seriesDetails.posterUrl
+ if (!url.isNullOrEmpty()) {
+ try {
+ val request = ImageRequest.Builder(carContext)
+ .data(url)
+ .size(600, 900)
+ .build()
+ val result = SingletonImageLoader.get(carContext).execute(request)
+ posterBitmap = result.image?.asDrawable(carContext.resources)?.toBitmap()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ isLoadingImage = false
+ invalidate()
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ val paneBuilder = Pane.Builder()
+
+ // Title Row
+ val title = "${episode.episode}. ${episode.name ?: "${CarStrings.get(R.string.car_episode)} ${episode.episode}"}"
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(title)
+ .addText("${CarStrings.get(R.string.car_season)} ${episode.season ?: "?"}")
+ .build()
+ )
+
+ // Image
+ posterBitmap?.let {
+ paneBuilder.setImage(CarIcon.Builder(IconCompat.createWithBitmap(it)).build())
+ } ?: run {
+ // Fallback icon if no image loaded yet or error
+ paneBuilder.setImage(CarIcon.Builder(IconCompat.createWithResource(carContext, R.mipmap.ic_launcher)).build())
+ }
+
+ // Description Row
+ if (!episode.description.isNullOrEmpty()) {
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(CarStrings.get(R.string.car_plot))
+ .addText(episode.description!!)
+ .build()
+ )
+ }
+
+ // Play Button action
+ val playIcon = IconCompat.createWithResource(carContext, android.R.drawable.ic_media_play)
+ .setTint(android.graphics.Color.BLACK)
+
+ val playAction = Action.Builder()
+ .setIcon(CarIcon.Builder(playIcon).build())
+ .setBackgroundColor(CarColor.createCustom(android.graphics.Color.WHITE, android.graphics.Color.WHITE))
+ .setOnClickListener {
+ // Get saved position for resume
+ val startTime = getViewPos(episode.data.hashCode())?.position ?: 0L
+ screenManager.push(
+ PlayerCarScreen(
+ carContext = carContext,
+ loadResponse = seriesDetails,
+ selectedEpisode = episode,
+ playlist = playlist,
+ startTime = startTime,
+ preSelectedSource = selectedSource
+ )
+ )
+ }
+ .build()
+
+ // Source Selection Button
+ val sourceIcon = IconCompat.createWithResource(carContext, R.drawable.ic_baseline_source_24)
+
+ val sourceActionTitle = if (selectedSource != null) {
+ selectedSource!!.name
+ } else {
+ CarStrings.get(R.string.car_source)
+ }
+
+ val sourceAction = Action.Builder()
+ .setIcon(CarIcon.Builder(sourceIcon).build())
+ .setTitle(sourceActionTitle)
+ .setOnClickListener {
+ screenManager.push(
+ SourceSelectionScreen(
+ carContext = carContext,
+ apiName = seriesDetails.apiName,
+ dataUrl = episode.data,
+ currentSourceUrl = selectedSource?.url,
+ onSourceSelected = { source ->
+ selectedSource = source
+ invalidate()
+ }
+ )
+ )
+ }
+ .build()
+
+ paneBuilder.addAction(playAction)
+ paneBuilder.addAction(sourceAction)
+
+ return PaneTemplate.Builder(paneBuilder.build())
+ .setTitle(seriesDetails.name) // Header Title is Series Name
+ .setHeaderAction(Action.BACK)
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/EpisodeListScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/EpisodeListScreen.kt
new file mode 100644
index 00000000000..44c3fe6baa3
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/EpisodeListScreen.kt
@@ -0,0 +1,98 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.ActionStrip
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import com.lagradost.cloudstream3.TvSeriesLoadResponse
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
+
+class EpisodeListScreen(
+ carContext: CarContext,
+ private val details: TvSeriesLoadResponse,
+ private val isExpressMode: Boolean = false
+) : Screen(carContext) {
+
+ private val availableSeasons: List = details.episodes.mapNotNull { it.season }.distinct().sorted()
+ private var currentSeasonIndex: Int = 0 // Index in availableSeasons list
+
+ override fun onGetTemplate(): Template {
+ if (availableSeasons.isEmpty()) {
+ return ListTemplate.Builder()
+ .setTitle(details.name)
+ .setHeaderAction(Action.BACK)
+ .setSingleList(ItemList.Builder().addItem(Row.Builder().setTitle(CarStrings.get(R.string.car_no_episodes_found)).build()).build())
+ .build()
+ }
+
+ val currentSeason = availableSeasons[currentSeasonIndex]
+ val seasonEpisodes = details.episodes.filter { it.season == currentSeason }.sortedBy { it.episode }
+
+ val listBuilder = ItemList.Builder()
+
+ seasonEpisodes.forEach { episode ->
+ val title = "${episode.episode}. ${episode.name ?: "${CarStrings.get(R.string.car_episode)} ${episode.episode}"}"
+ val rowBuilder = Row.Builder()
+ .setTitle(title)
+ .setOnClickListener {
+ if (isExpressMode) {
+ // Get saved position for resume
+ val startTime = getViewPos(episode.data.hashCode())?.position ?: 0L
+ screenManager.push(
+ PlayerCarScreen(
+ carContext = carContext,
+ loadResponse = details,
+ selectedEpisode = episode,
+ playlist = seasonEpisodes,
+ startTime = startTime
+ )
+ )
+ } else {
+ screenManager.push(
+ EpisodeDetailScreen(
+ carContext = carContext,
+ seriesDetails = details,
+ episode = episode,
+ playlist = seasonEpisodes
+ )
+ )
+ }
+ }
+
+ episode.description?.let {
+ // Truncate to avoid huge texts, though AA handles some wrapping
+ val desc = if (it.length > 100) it.substring(0, 97) + "..." else it
+ rowBuilder.addText(desc)
+ }
+
+ listBuilder.addItem(rowBuilder.build())
+ }
+
+ val seasonAction = Action.Builder()
+ .setTitle("${CarStrings.get(R.string.car_season)} $currentSeason")
+ .setOnClickListener {
+ // Cycle through seasons
+ currentSeasonIndex = (currentSeasonIndex + 1) % availableSeasons.size
+ invalidate()
+ }
+ .build()
+
+ return ListTemplate.Builder()
+ .setTitle("${details.name} - ${CarStrings.get(R.string.car_season)} $currentSeason")
+ .setHeaderAction(Action.BACK)
+ .setSingleList(listBuilder.build())
+ .setActionStrip(
+ ActionStrip.Builder()
+ .addAction(seasonAction)
+ .build()
+ )
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/HistoryScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/HistoryScreen.kt
new file mode 100644
index 00000000000..2e7d92e484b
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/HistoryScreen.kt
@@ -0,0 +1,218 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import android.util.Log
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllResumeStateIds
+import com.lagradost.cloudstream3.utils.DataStoreHelper.getLastWatched
+import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
+import com.lagradost.cloudstream3.utils.VideoDownloadHelper
+import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
+import com.lagradost.cloudstream3.CloudStreamApp.Companion.getKey
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.ui.APIRepository
+import com.lagradost.cloudstream3.mvvm.Resource
+import com.lagradost.cloudstream3.TvSeriesLoadResponse
+import com.lagradost.cloudstream3.SearchResponse
+import com.lagradost.cloudstream3.newMovieSearchResponse
+import com.lagradost.cloudstream3.newTvSeriesSearchResponse
+import com.lagradost.cloudstream3.isMovieType
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import kotlinx.coroutines.delay
+
+class HistoryScreen(carContext: CarContext) : Screen(carContext), DefaultLifecycleObserver {
+ private val scope = CoroutineScope(Dispatchers.IO)
+ private var itemList: ItemList? = null
+
+ init {
+ lifecycle.addObserver(this)
+ }
+
+ override fun onStart(owner: LifecycleOwner) {
+ loadHistory()
+ }
+
+ private fun loadHistory(retryCount: Int = 0) {
+ scope.launch {
+ withContext(Dispatchers.Main) {
+ itemList = null
+ invalidate()
+ }
+ try {
+ // Strict logic copied from HomeViewModel.getResumeWatching()
+ val resumeWatchingResult = withContext(Dispatchers.IO) {
+ val ids = getAllResumeStateIds()
+ Log.d("HistoryDebug", "Loading history. IDs found: ${ids?.size ?: 0}")
+ ids?.mapNotNull { id ->
+ getLastWatched(id)
+ }?.sortedBy { -it.updateTime }?.mapNotNull { resume ->
+ val data = getKey(
+ DOWNLOAD_HEADER_CACHE,
+ resume.parentId.toString()
+ )
+ if (data == null) {
+ Log.e("HistoryDebug", "MISSING HEADER for parentId: ${resume.parentId}")
+ return@mapNotNull null
+ }
+ Log.d("HistoryDebug", "Found HEADER for parentId: ${resume.parentId} -> ${data.name}")
+
+ Pair(resume, data)
+ }
+ }
+
+ val builder = ItemList.Builder()
+
+ if (resumeWatchingResult.isNullOrEmpty()) {
+ builder.setNoItemsMessage(CarStrings.get(R.string.car_no_continue_watching))
+ } else {
+ resumeWatchingResult.forEach { (resume, cachedData) ->
+ val title = cachedData.name
+ val subtitle = if (resume.episode != null && resume.season != null) {
+ "S${resume.season}E${resume.episode} (${cachedData.apiName})"
+ } else {
+ cachedData.apiName
+ }
+
+ builder.addItem(
+ Row.Builder()
+ .setTitle(title)
+ .addText(subtitle)
+ .setOnClickListener {
+ playResumeItem(resume, cachedData)
+ }
+ .build()
+ )
+ }
+ }
+
+ val builtList = builder.build()
+ withContext(Dispatchers.Main) {
+ itemList = builtList
+ invalidate()
+ }
+ } catch (e: Exception) {
+ if (retryCount < 3) {
+ delay(3000)
+ loadHistory(retryCount + 1)
+ } else {
+ withContext(Dispatchers.Main) {
+ itemList = ItemList.Builder()
+ .addItem(
+ Row.Builder()
+ .setTitle("Errore: ${e.message}")
+ .setOnClickListener { loadHistory() }
+ .build()
+ )
+ .build()
+ invalidate()
+ }
+ }
+ }
+ }
+ }
+
+ private fun playResumeItem(resume: VideoDownloadHelper.ResumeWatching, cachedData: VideoDownloadHelper.DownloadHeaderCached) {
+ scope.launch {
+ withContext(Dispatchers.Main) {
+ androidx.car.app.CarToast.makeText(carContext, CarStrings.get(R.string.car_resuming, cachedData.name), androidx.car.app.CarToast.LENGTH_LONG).show()
+ }
+
+ val api = getApiFromNameNull(cachedData.apiName) ?: return@launch
+ val repo = APIRepository(api)
+
+ val loadResult = when(val result = repo.load(cachedData.url)) {
+ is Resource.Success -> result.value
+ else -> null
+ } ?: return@launch
+
+ if (loadResult is TvSeriesLoadResponse) {
+ // Find the specific episode to resume
+ // resume.episodeId should match episode.data.hashCode() used by PlayerCarScreen
+ val episodeToResume = loadResult.episodes.find { episode ->
+ // Promiscuous check: try multiple ways to match the episode
+ // Note: Episode class does not have an 'id' field, so we skip direct ID check
+ val urlHashMatch = episode.data.hashCode() == resume.episodeId
+ val numberMatch = episode.episode == resume.episode && episode.season == resume.season
+
+ urlHashMatch || numberMatch
+ }
+
+ if (episodeToResume != null) {
+ val startTime = getViewPos(resume.episodeId)?.position ?: 0L
+ val seasonEpisodes = loadResult.episodes.filter { it.season == episodeToResume.season }
+
+ withContext(Dispatchers.Main) {
+ screenManager.push(
+ PlayerCarScreen(
+ carContext = carContext,
+ loadResponse = loadResult,
+ selectedEpisode = episodeToResume,
+ playlist = seasonEpisodes,
+ startTime = startTime
+ )
+ )
+ }
+ } else {
+ // Fallback to episode list if episode not found
+ withContext(Dispatchers.Main) {
+ screenManager.push(EpisodeListScreen(carContext, loadResult, isExpressMode = true))
+ }
+ }
+ } else {
+ val startTime = getViewPos(resume.episodeId)?.position ?: 0L
+
+ // Prepare SearchResponse item for PlayerCarScreen
+ val item: SearchResponse = if (cachedData.type.isMovieType()) {
+ api.newMovieSearchResponse(
+ name = cachedData.name,
+ url = cachedData.url,
+ type = cachedData.type,
+ ) {
+ this.posterUrl = cachedData.poster
+ }
+ } else {
+ api.newTvSeriesSearchResponse(
+ name = cachedData.name,
+ url = cachedData.url,
+ type = cachedData.type,
+ ) {
+ this.posterUrl = cachedData.poster
+ }
+ }
+
+ withContext(Dispatchers.Main) {
+ screenManager.push(
+ PlayerCarScreen(
+ carContext = carContext,
+ item = item,
+ loadResponse = loadResult,
+ selectedEpisode = null,
+ startTime = startTime
+ )
+ )
+ }
+ }
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ val list = itemList ?: ItemList.Builder().setNoItemsMessage(CarStrings.get(R.string.car_loading)).build()
+
+ return ListTemplate.Builder()
+ .setTitle(CarStrings.get(R.string.car_history))
+ .setHeaderAction(Action.BACK)
+ .setSingleList(list)
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/LibraryCarScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/LibraryCarScreen.kt
new file mode 100644
index 00000000000..50dbb980a26
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/LibraryCarScreen.kt
@@ -0,0 +1,44 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
+import com.lagradost.cloudstream3.utils.DataStoreHelper.getLastWatched
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+class LibraryCarScreen(carContext: CarContext) : Screen(carContext) {
+
+ override fun onGetTemplate(): Template {
+ return ListTemplate.Builder()
+ .setSingleList(
+ ItemList.Builder()
+ .addItem(
+ Row.Builder()
+ .setTitle(CarStrings.get(R.string.car_bookmarks))
+ .setOnClickListener { screenManager.push(BookmarksScreen(carContext)) }
+ .setBrowsable(true)
+ .build()
+ )
+ .addItem(
+ Row.Builder()
+ .setTitle(CarStrings.get(R.string.car_history))
+ .setOnClickListener { screenManager.push(HistoryScreen(carContext)) }
+ .setBrowsable(true)
+ .build()
+ )
+ .build()
+ )
+ .setTitle(CarStrings.get(R.string.car_library))
+ .setHeaderAction(Action.BACK)
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/MainCarScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/MainCarScreen.kt
new file mode 100644
index 00000000000..14177dc66ff
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/MainCarScreen.kt
@@ -0,0 +1,213 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.ActionStrip
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.SectionedItemList
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.HomePageList
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.mvvm.Resource
+import com.lagradost.cloudstream3.ui.APIRepository
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class MainCarScreen(carContext: CarContext) : Screen(carContext), DefaultLifecycleObserver {
+ private var homePageLists: List = emptyList()
+ private var isLoading = true
+ private var errorMessage: String? = null
+ private var currentApiName: String = ""
+
+ companion object {
+ private const val LOADING_DELAY_MS = 500L
+ private const val MAX_LOADING_ATTEMPTS = 20
+ }
+
+ init {
+ lifecycle.addObserver(this)
+ }
+
+ override fun onResume(owner: LifecycleOwner) {
+ super.onResume(owner)
+ // Reload data on resume to catch provider changes
+ loadData()
+ }
+
+ private fun loadData() {
+ isLoading = true
+ errorMessage = null
+ currentApiName = DataStoreHelper.currentHomePage ?: ""
+ invalidate()
+
+ CoroutineScope(Dispatchers.IO).launch {
+ try {
+ var api = getApiFromNameNull(currentApiName)
+ var attempts = 0
+ // Retry waiting for plugins to load
+ while (api == null && attempts < MAX_LOADING_ATTEMPTS) {
+ delay(LOADING_DELAY_MS)
+ api = getApiFromNameNull(currentApiName)
+ attempts++
+ }
+
+ if (api == null) {
+ errorMessage = "${CarStrings.get(R.string.car_provider_not_found)}: $currentApiName"
+ isLoading = false
+ invalidate()
+ return@launch
+ }
+
+ val repo = APIRepository(api)
+ when (val result = repo.getMainPage(1, null)) {
+ is Resource.Success -> {
+ homePageLists = result.value.filterNotNull().flatMap { it.items }
+ isLoading = false
+ }
+ is Resource.Failure -> {
+ errorMessage = result.errorString ?: CarStrings.get(R.string.car_loading_content)
+ isLoading = false
+ }
+ is Resource.Loading -> {}
+ }
+ } catch (e: Exception) {
+ errorMessage = e.message
+ isLoading = false
+ }
+ invalidate()
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ return ListTemplate.Builder()
+ .setTitle(carContext.getString(R.string.app_name))
+ .addSectionedList(
+ SectionedItemList.create(
+ buildMenuSection(),
+ CarStrings.get(R.string.car_menu)
+ )
+ )
+ .addSectionedList(
+ SectionedItemList.create(
+ buildContentSection(),
+ CarStrings.get(R.string.car_home_content)
+ )
+ )
+ .setActionStrip(buildActionStrip())
+ .build()
+ }
+
+ private fun buildMenuSection(): ItemList {
+ val menuListBuilder = ItemList.Builder()
+
+ menuListBuilder.addItem(
+ createMenuRow(
+ title = CarStrings.get(R.string.car_favorites),
+ iconRes = R.drawable.ic_baseline_favorite_24,
+ screen = { BookmarksScreen(carContext) }
+ )
+ )
+
+ menuListBuilder.addItem(
+ createMenuRow(
+ title = CarStrings.get(R.string.car_history),
+ iconRes = android.R.drawable.ic_menu_recent_history,
+ screen = { HistoryScreen(carContext) }
+ )
+ )
+
+ menuListBuilder.addItem(
+ createMenuRow(
+ title = CarStrings.get(R.string.car_downloads),
+ iconRes = android.R.drawable.stat_sys_download,
+ screen = { DownloadsScreen(carContext) }
+ )
+ )
+
+ menuListBuilder.addItem(
+ Row.Builder()
+ .setTitle(CarStrings.get(R.string.car_provider))
+ .addText("${CarStrings.get(R.string.car_current)}: $currentApiName")
+ .setImage(CarIcon.Builder(IconCompat.createWithResource(carContext, android.R.drawable.ic_menu_manage)).build())
+ .setOnClickListener { screenManager.push(ProviderCarScreen(carContext)) }
+ .setBrowsable(true)
+ .build()
+ )
+
+ menuListBuilder.addItem(
+ createMenuRow(
+ title = CarStrings.get(R.string.car_about_me),
+ iconRes = android.R.drawable.ic_menu_info_details,
+ screen = { AboutMeScreen(carContext) }
+ )
+ )
+
+ return menuListBuilder.build()
+ }
+
+ private fun createMenuRow(title: String, iconRes: Int, screen: () -> Screen): Row {
+ return Row.Builder()
+ .setTitle(title)
+ .setImage(CarIcon.Builder(IconCompat.createWithResource(carContext, iconRes)).build())
+ .setOnClickListener { screenManager.push(screen()) }
+ .setBrowsable(true)
+ .build()
+ }
+
+ private fun buildContentSection(): ItemList {
+ val contentListBuilder = ItemList.Builder()
+
+ if (isLoading) {
+ contentListBuilder.addItem(Row.Builder().setTitle(CarStrings.get(R.string.car_loading)).setBrowsable(false).build())
+ } else if (errorMessage != null) {
+ contentListBuilder.addItem(Row.Builder().setTitle("${CarStrings.get(R.string.car_error)}: $errorMessage").setBrowsable(false).build())
+ } else if (homePageLists.isEmpty()) {
+ contentListBuilder.addItem(Row.Builder().setTitle(CarStrings.get(R.string.car_no_content_from_provider)).setBrowsable(false).build())
+ } else {
+ homePageLists.forEach { homePageList ->
+ contentListBuilder.addItem(
+ Row.Builder()
+ .setTitle(homePageList.name)
+ .setOnClickListener {
+ screenManager.push(CategoryScreen(carContext, homePageList))
+ }
+ .setBrowsable(true)
+ .build()
+ )
+ }
+ }
+ return contentListBuilder.build()
+ }
+
+ private fun buildActionStrip(): ActionStrip {
+ return ActionStrip.Builder()
+ .addAction(
+ Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, android.R.drawable.ic_menu_search)).build())
+ .setOnClickListener {
+ screenManager.push(SearchCarScreen(carContext))
+ }
+ .build()
+ )
+ .addAction(
+ Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_refresh)).build())
+ .setOnClickListener {
+ loadData()
+ }
+ .build()
+ )
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/PlayerCarScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/PlayerCarScreen.kt
new file mode 100644
index 00000000000..76cc34e1980
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/PlayerCarScreen.kt
@@ -0,0 +1,704 @@
+package com.lagradost.cloudstream3.ui.car
+
+import android.view.Surface
+import androidx.car.app.AppManager
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.SurfaceCallback
+import androidx.car.app.SurfaceContainer
+import androidx.car.app.model.Action
+import androidx.car.app.model.ActionStrip
+import androidx.car.app.model.CarColor
+import androidx.car.app.model.Template
+import androidx.car.app.navigation.model.NavigationTemplate
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.media3.common.AudioAttributes
+import androidx.media3.common.C
+import androidx.media3.common.MediaItem
+import androidx.media3.common.MimeTypes
+import androidx.media3.common.Player
+import androidx.media3.exoplayer.ExoPlayer
+import androidx.media3.session.MediaSession
+import androidx.car.app.model.CarIcon
+import androidx.core.graphics.drawable.IconCompat
+import com.lagradost.cloudstream3.R
+import androidx.media3.common.MediaMetadata
+import android.net.Uri
+import coil3.request.ImageRequest
+import coil3.SingletonImageLoader
+import coil3.asDrawable
+import androidx.core.graphics.drawable.toBitmap
+import androidx.media3.common.C.VIDEO_SCALING_MODE_SCALE_TO_FIT
+import androidx.media3.common.C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.SearchResponse
+import com.lagradost.cloudstream3.mvvm.Resource
+import com.lagradost.cloudstream3.ui.APIRepository
+import com.lagradost.cloudstream3.utils.ExtractorLink
+import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
+import com.lagradost.cloudstream3.utils.VideoDownloadHelper
+import com.lagradost.cloudstream3.CloudStreamApp.Companion.setKey
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import android.util.Log
+import com.lagradost.cloudstream3.utils.DataStore
+import com.lagradost.cloudstream3.utils.DataStore.getKey
+import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
+import com.lagradost.cloudstream3.Episode
+
+import com.lagradost.cloudstream3.LoadResponse
+import com.lagradost.cloudstream3.TvSeriesLoadResponse
+import com.lagradost.cloudstream3.AnimeLoadResponse
+import com.lagradost.cloudstream3.MovieLoadResponse
+import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
+import com.lagradost.cloudstream3.TvType
+import kotlinx.coroutines.delay
+
+class PlayerCarScreen(
+ carContext: CarContext,
+ val item: SearchResponse? = null,
+ val loadResponse: LoadResponse? = null,
+ val selectedEpisode: Episode? = null,
+ val playlist: List? = null,
+ val startTime: Long = 0L,
+ val fileUri: String? = null,
+ val videoId: Int? = null,
+ val parentId: Int? = null,
+ val preSelectedSource: ExtractorLink? = null
+) : Screen(carContext), SurfaceCallback {
+
+ private var activeEpisode: Episode? = selectedEpisode
+ private val scope = CoroutineScope(Dispatchers.IO + Job())
+ private var player: ExoPlayer? = null
+ private var surface: Surface? = null
+ private var mediaSession: MediaSession? = null
+ private var isPlaying = true
+
+ private var resizeMode = VIDEO_SCALING_MODE_SCALE_TO_FIT
+
+ private var currentEpisodeId: Int? = null
+ private var currentParentId: Int? = null
+ private var saveProgressJob: Job? = null
+ private var showSeekControls = false
+
+ init {
+ lifecycle.addObserver(object : LifecycleEventObserver {
+ override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
+ when (event) {
+ Lifecycle.Event.ON_START -> {
+ carContext.getCarService(AppManager::class.java).setSurfaceCallback(this@PlayerCarScreen)
+ player?.playWhenReady = true
+ }
+ Lifecycle.Event.ON_STOP -> {
+ player?.playWhenReady = false
+ saveProgress()
+ carContext.getCarService(AppManager::class.java).setSurfaceCallback(null)
+ }
+ Lifecycle.Event.ON_DESTROY -> {
+ mediaSession?.release()
+ mediaSession = null
+ player?.release()
+ player = null
+ scope.cancel()
+ }
+ else -> {}
+ }
+ }
+ })
+
+ if (fileUri != null) {
+ currentEpisodeId = videoId
+ currentParentId = parentId
+
+ // Fix: Populate selectedEpisode metadata for Downloads so saveProgress works correctly
+ if (this.activeEpisode == null) {
+ scope.launch(Dispatchers.IO) {
+ try {
+ val cachedEp = carContext.getKey(
+ DOWNLOAD_EPISODE_CACHE,
+ videoId.toString()
+ )
+ if (cachedEp != null) {
+ @Suppress("DEPRECATION_ERROR")
+ val ep = Episode(
+ data = "", // URL not available in cache, but ID is used from videoId so acceptable
+ name = cachedEp.name,
+ season = cachedEp.season,
+ episode = cachedEp.episode,
+ posterUrl = cachedEp.poster
+ )
+ this@PlayerCarScreen.activeEpisode = ep
+ Log.d("PlayerCarScreen", "Populated activeEpisode from Download: S${cachedEp.season} E${cachedEp.episode}")
+ }
+ } catch (e: Exception) {
+ Log.e("PlayerCarScreen", "Error loading download metadata", e)
+ }
+ withContext(Dispatchers.Main) {
+ startPlayback(fileUri)
+ }
+ }
+ } else {
+ scope.launch { startPlayback(fileUri) }
+ }
+ } else {
+ loadMedia(item?.url)
+ }
+ }
+
+ override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
+ val newSurface = surfaceContainer.surface
+ if (newSurface != null) {
+ surface = newSurface
+ player?.setVideoSurface(newSurface)
+ }
+ }
+
+ override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
+ surface = null
+ player?.setVideoSurface(null)
+ }
+
+ private fun loadMedia(url: String?) {
+ updateStatus(CarStrings.get(R.string.car_loading))
+ scope.launch {
+ val data = getLoadResponse()
+
+ if (data == null) {
+ if (item?.type == TvType.Live) {
+ Log.d("PlayerCarScreen", "Details load failed, attempting direct playback for Live content")
+ withContext(Dispatchers.Main) {
+ startPlayback(item!!.url)
+ }
+ return@launch
+ }
+ showToast(CarStrings.get(R.string.car_unable_to_load_details))
+ return@launch
+ }
+
+ resolveIds(data)
+ loadLinks(data)
+ }
+ }
+
+ private suspend fun getLoadResponse(): LoadResponse? {
+ // If we already have the LoadResponse (passed from Details), use it.
+ // Otherwise, fetch it using item.url
+ return if (loadResponse != null) {
+ loadResponse
+ } else if (item != null) {
+ val apiName = item.apiName
+ val api = getApiFromNameNull(apiName) ?: return null
+ val repo = APIRepository(api)
+ try {
+ when(val result = repo.load(item.url)) {
+ is Resource.Success -> result.value
+ else -> null
+ }
+ } catch (e: Exception) {
+ Log.e("PlayerCarScreen", "Error loading details for ${item.url}", e)
+ null
+ }
+ } else {
+ null
+ }
+ }
+
+ private fun resolveIds(data: LoadResponse) {
+ val apiName = data.apiName
+ val api = getApiFromNameNull(apiName) ?: return
+
+ // Resolve IDs for syncing BEFORE starting playback
+ // This ensures IDs are available for saveProgress() calls during playback
+ val mainUrl = api.mainUrl
+ val idFromUrl = data.url.replace(mainUrl, "").replace("/", "").hashCode()
+
+ // Priority: 1. Item ID (if available from Home/Search and valid)
+ // 2. Data URL Hashcode (using strict cleaning logic)
+ currentParentId = item?.id ?: idFromUrl
+ saveHeaderCache(data)
+
+ if (data is TvSeriesLoadResponse && activeEpisode != null) {
+ currentEpisodeId = activeEpisode!!.data.hashCode()
+ } else {
+ // For movies, we use the parent ID
+ currentEpisodeId = currentParentId
+ }
+
+ Log.d("PlayerCarScreen", "Resolved IDs (STRICT) - Name: ${data.name} | Parent: $currentParentId | Episode: $currentEpisodeId | Type: ${data.javaClass.simpleName} | ItemID: ${item?.id} | IdFromUrl: $idFromUrl")
+ }
+
+ private suspend fun loadLinks(data: LoadResponse) {
+ val apiName = data.apiName
+ val api = getApiFromNameNull(apiName) ?: return
+ val links = mutableListOf()
+ try {
+ val urlToLoad = when {
+ activeEpisode != null -> activeEpisode!!.data
+ data is com.lagradost.cloudstream3.TvSeriesLoadResponse -> {
+ // Auto-select first episode if none selected
+ data.episodes.firstOrNull()?.data
+ }
+ data is com.lagradost.cloudstream3.AnimeLoadResponse -> {
+ // Auto-select first episode from first available category
+ data.episodes.values.flatten().firstOrNull()?.data
+ }
+ data is com.lagradost.cloudstream3.MovieLoadResponse -> {
+ data.dataUrl
+ }
+ else -> data.url
+ }
+
+ if (urlToLoad == null) {
+ showToast(CarStrings.get(R.string.car_no_playable_content))
+ return
+ }
+
+ // Use pre-selected source if provided, otherwise load and auto-select best
+ if (preSelectedSource != null) {
+ startPlayback(preSelectedSource)
+ } else {
+ // Load links using the API
+ val success = api.loadLinks(urlToLoad, false, {}, { link ->
+ links.add(link)
+ })
+
+ if(links.isNotEmpty()) {
+ val bestLink = links.sortedByDescending { it.quality }.first()
+ startPlayback(bestLink)
+ } else {
+ showToast(CarStrings.get(R.string.car_no_link_found))
+ }
+ }
+ } catch (e: Exception) {
+ showToast("${CarStrings.get(R.string.car_error_loading_links)}: ${e.message}")
+ e.printStackTrace()
+ }
+ }
+
+ private fun saveHeaderCache(data: LoadResponse? = null) {
+ try {
+ Log.d("PlayerCarScreen", "saveHeaderCache called. Item: ${item?.url}, Data: ${data?.url}, ParentID: $currentParentId")
+
+ val url = item?.url ?: data?.url ?: return
+ val apiName = item?.apiName ?: data?.apiName ?: return
+ val name = item?.name ?: data?.name ?: return
+ val type = item?.type ?: data?.type ?: TvType.Movie
+ val poster = item?.posterUrl ?: data?.posterUrl
+
+ val api = getApiFromNameNull(apiName)
+ val mainUrl = api?.mainUrl ?: ""
+ val id = url.replace(mainUrl, "").replace("/", "").hashCode()
+
+ val header = VideoDownloadHelper.DownloadHeaderCached(
+ apiName = apiName,
+ url = url,
+ type = type,
+ name = name,
+ poster = poster,
+ id = id,
+ cacheTime = System.currentTimeMillis()
+ )
+ Log.e("PlayerCarScreen", "Saving Header Cache: ID=$id, ParentID=$currentParentId, Name=${name}, Type=${header.type}")
+ setKey(DOWNLOAD_HEADER_CACHE, id.toString(), header)
+ // Ensure parentId is also covered if different
+ currentParentId?.let { parentId ->
+ if (parentId != id) {
+ setKey(DOWNLOAD_HEADER_CACHE, parentId.toString(), header.copy(id = parentId))
+ Log.e("PlayerCarScreen", "Saved extra copy for ParentID: $parentId")
+ }
+ }
+ } catch (e: Exception) {
+ Log.e("PlayerCarScreen", "Error saving header cache", e)
+ }
+ }
+
+ private fun saveProgress() {
+ val p = player ?: return
+ val pos = p.currentPosition
+ val dur = p.duration
+
+ Log.d("PlayerCarScreen", "saveProgress - Pos: $pos, Dur: $dur, IsPlaying: $isPlaying")
+
+ if (item?.type == TvType.Live) {
+ Log.d("PlayerCarScreen", "Skipping saveProgress for Live content")
+ return
+ }
+
+ if (dur <= 0) return
+
+ // 1. Save detailed position (setViewPos)
+ // Only if we have a valid ID. For Movies, currentEpisodeId might be enough.
+ // For Episodes, we need the specific episode ID.
+ if (currentEpisodeId != null) {
+ DataStoreHelper.setViewPos(currentEpisodeId, pos, dur)
+ Log.d("PlayerCarScreen", "Called setViewPos for EpisodeID: $currentEpisodeId")
+ } else {
+ Log.d("PlayerCarScreen", "Skipping setViewPos (EpisodeID is null)")
+ }
+
+ // 2. Save "Last Watched" for Continue Watching list
+ // This requires parentId.
+ if (currentParentId != null) {
+ // Logic to check if finished (95% rule)
+ val percentage = pos * 100L / dur
+ if (percentage > 95) {
+ // Mark as finished / remove from resume
+ DataStoreHelper.removeLastWatched(currentParentId)
+ Log.d("PlayerCarScreen", "Removed Last Watched (Finished)")
+ } else {
+ // Update resume state
+ val epNum = activeEpisode?.episode
+ val seasonNum = activeEpisode?.season
+
+ DataStoreHelper.setLastWatched(
+ parentId = currentParentId,
+ episodeId = currentEpisodeId,
+ episode = epNum,
+ season = seasonNum,
+ isFromDownload = false,
+ updateTime = System.currentTimeMillis()
+ )
+ Log.d("PlayerCarScreen", "Set Last Watched for ParentID: $currentParentId")
+ }
+ } else {
+ Log.d("PlayerCarScreen", "Skipping setLastWatched (ParentID is null)")
+ }
+ }
+
+ @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
+ private suspend fun startPlayback(link: Any) {
+ val url = when(link) {
+ is ExtractorLink -> link.url
+ is String -> link
+ else -> return
+ }
+
+ withContext(Dispatchers.Main) {
+ updateStatus(CarStrings.get(R.string.car_starting_playback))
+ if (player == null) {
+ player = ExoPlayer.Builder(carContext).build().apply {
+ val audioAttributes = AudioAttributes.Builder()
+ .setUsage(C.USAGE_MEDIA)
+ .setContentType(C.AUDIO_CONTENT_TYPE_MOVIE)
+ .build()
+ setAudioAttributes(audioAttributes, true)
+ }
+ }
+ player?.let { p ->
+ // Wrap in ForwardingPlayer to intercept commands
+ val forwardingPlayer = object : androidx.media3.common.ForwardingPlayer(p) {
+ override fun seekToNext() {
+ Log.d("PlayerCarScreen", "ForwardingPlayer seekToNext")
+ scope.launch { loadNextEpisode() }
+ }
+
+ override fun seekToPrevious() {
+ Log.d("PlayerCarScreen", "ForwardingPlayer seekToPrevious")
+ seekBack()
+ }
+ }
+
+ // Initialize MediaSession with ForwardingPlayer
+ if (mediaSession == null) {
+ mediaSession = MediaSession.Builder(carContext, forwardingPlayer)
+ .setCallback(object : MediaSession.Callback {
+ override fun onConnect(
+ session: MediaSession,
+ controller: MediaSession.ControllerInfo
+ ): MediaSession.ConnectionResult {
+ val availableCommands = androidx.media3.common.Player.Commands.Builder()
+ .add(androidx.media3.common.Player.COMMAND_PLAY_PAUSE)
+ .add(androidx.media3.common.Player.COMMAND_STOP)
+ .add(androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT)
+ .add(androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS)
+ .build()
+
+ return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
+ .setAvailablePlayerCommands(availableCommands)
+ .build()
+ }
+ })
+ .build()
+ }
+
+ p.addListener(object : Player.Listener {
+ override fun onIsPlayingChanged(isPlaying: Boolean) {
+ this@PlayerCarScreen.isPlaying = isPlaying
+ invalidate()
+
+ this@PlayerCarScreen.saveProgressJob?.cancel()
+ if (isPlaying) {
+ this@PlayerCarScreen.saveProgressJob = scope.launch {
+ while(true) {
+ kotlinx.coroutines.delay(10_000)
+ withContext(Dispatchers.Main) {
+ saveProgress()
+ }
+ }
+ }
+ } else {
+ saveProgress()
+ }
+ }
+ })
+
+ surface?.let { p.setVideoSurface(it) }
+ p.videoScalingMode = resizeMode
+
+ // Create MediaMetadata
+ val metadataBuilder = MediaMetadata.Builder()
+ .setTitle(item?.name ?: activeEpisode?.name ?: "Video")
+ .setDisplayTitle(item?.name ?: activeEpisode?.name ?: "Video")
+ .setArtist(activeEpisode?.name ?: item?.apiName ?: "Cloudstream")
+
+ // Try to load artwork
+ val posterUrl = activeEpisode?.posterUrl ?: item?.posterUrl
+ if (!posterUrl.isNullOrEmpty()) {
+ try {
+ val request = ImageRequest.Builder(carContext)
+ .data(posterUrl)
+ .size(512, 512)
+ .build()
+ val result = SingletonImageLoader.get(carContext).execute(request)
+ val bitmap = result.image?.asDrawable(carContext.resources)?.toBitmap()
+ if (bitmap != null) {
+ metadataBuilder.setArtworkData(
+ bitmap.let {
+ val stream = java.io.ByteArrayOutputStream()
+ it.compress(android.graphics.Bitmap.CompressFormat.PNG, 100, stream)
+ stream.toByteArray()
+ },
+ MediaMetadata.PICTURE_TYPE_FRONT_COVER
+ )
+ }
+ } catch (e: Exception) {
+ Log.e("PlayerCarScreen", "Failed to load artwork for metadata", e)
+ }
+ }
+
+ val mediaItemBuilder = MediaItem.Builder()
+ .setUri(url)
+ .setMediaMetadata(metadataBuilder.build())
+
+ if (link is ExtractorLink && link.isM3u8) {
+ mediaItemBuilder.setMimeType(MimeTypes.APPLICATION_M3U8)
+ }
+
+ p.setMediaItem(mediaItemBuilder.build())
+ p.prepare()
+ if (startTime > 0L) {
+ p.seekTo(startTime)
+ }
+ p.play()
+ updateStatus(CarStrings.get(R.string.car_playing))
+
+ // Start periodic save loop
+ // startSaveLoop()
+ }
+ }
+ }
+
+ private fun startSaveLoop() {
+ saveProgressJob?.cancel()
+ saveProgressJob = scope.launch {
+ Log.d("PlayerCarScreen", "Starting Save Loop")
+ while (true) {
+ delay(15_000) // Save every 15 seconds
+ if (isPlaying) {
+ withContext(Dispatchers.Main) {
+ saveProgress()
+ }
+ }
+ }
+ }
+ }
+
+ private fun showToast(msg: String) {
+ androidx.car.app.CarToast.makeText(carContext, msg, androidx.car.app.CarToast.LENGTH_LONG).show()
+ }
+
+ // Using a minimal Navigation Template to get the surface
+ // Using a minimal Navigation Template to get the surface
+ override fun onGetTemplate(): Template {
+ val playPauseAction = Action.Builder()
+ .setIcon(
+ CarIcon.Builder(
+ IconCompat.createWithResource(
+ carContext,
+ if (isPlaying) R.drawable.ic_baseline_pause_24 else R.drawable.ic_baseline_play_arrow_24
+ )
+ ).build()
+ )
+ .setOnClickListener {
+ if (isPlaying) {
+ player?.pause()
+ saveProgress() // Save immediately when pausing
+ } else {
+ player?.play()
+ }
+ }
+ .build()
+
+ val actionStripBuilder = ActionStrip.Builder()
+
+ if (showSeekControls) {
+ // SEEK MODE: [Back (to menu)], [-10], [Play], [+30]
+
+ val backToMenuAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_baseline_arrow_back_24)).build())
+ .setOnClickListener {
+ showSeekControls = false
+ invalidate()
+ }
+ .build()
+
+ val seekBackAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.go_back_30)).build())
+ .setOnClickListener { seekBack() }
+ .build()
+
+ val seekForwardAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.go_forward_30)).build())
+ .setOnClickListener { seekForward() }
+ .build()
+
+ val resizeAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_baseline_aspect_ratio_24)).build())
+ .setOnClickListener {
+ resizeMode = if (resizeMode == VIDEO_SCALING_MODE_SCALE_TO_FIT) {
+ VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
+ } else {
+ VIDEO_SCALING_MODE_SCALE_TO_FIT
+ }
+ player?.videoScalingMode = resizeMode
+ showToast(if (resizeMode == VIDEO_SCALING_MODE_SCALE_TO_FIT) CarStrings.get(R.string.car_fit_to_screen) else CarStrings.get(R.string.car_fill_screen))
+ }
+ .build()
+
+ actionStripBuilder.addAction(backToMenuAction)
+ .addAction(seekBackAction)
+ .addAction(seekForwardAction)
+ .addAction(resizeAction)
+
+ } else {
+ // DEFAULT MODE: [Back (Exit)], [Play], [Resize], [Seek Controls]
+
+ val exitAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_baseline_arrow_back_24)).build())
+ .setOnClickListener { screenManager.pop() }
+ .build()
+
+
+
+ val seekBackAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.go_back_30)).build())
+ .setOnClickListener {
+ seekBack()
+ }
+ .build()
+
+ val openSeekAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_baseline_tune_24)).build())
+ .setOnClickListener {
+ showSeekControls = true
+ invalidate()
+ }
+ .build()
+
+ val nextAction = Action.Builder()
+ .setIcon(CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_baseline_skip_next_24)).build())
+ .setOnClickListener {
+ scope.launch { loadNextEpisode() }
+ }
+ .setEnabled(playlist != null && activeEpisode != null && playlist.indexOf(activeEpisode) < playlist.size - 1)
+ .build()
+
+ actionStripBuilder.addAction(exitAction)
+ .addAction(playPauseAction)
+ .addAction(nextAction)
+ .addAction(openSeekAction)
+ }
+
+ return NavigationTemplate.Builder()
+ .setActionStrip(actionStripBuilder.build())
+ .setBackgroundColor(CarColor.createCustom(android.graphics.Color.BLACK, android.graphics.Color.BLACK))
+ .build()
+ }
+
+ private fun seekBack() {
+ player?.let { p ->
+ val newPos = p.currentPosition - 30_000 // -30 seconds
+ p.seekTo(if (newPos < 0) 0 else newPos)
+ updateStatus("-30s")
+ }
+ }
+
+ private suspend fun loadNextEpisode() {
+ if (playlist == null || activeEpisode == null) {
+ showToast("No playlist available")
+ return
+ }
+
+
+ // Fix: Episode class does not have 'id'. Use 'data' or calculate hash.
+ val currentIndex = playlist.indexOfFirst { it.data == activeEpisode!!.data } // Comparing by data url is safest
+ if (currentIndex != -1 && currentIndex < playlist.size - 1) {
+ val nextEp = playlist[currentIndex + 1]
+ activeEpisode = nextEp
+ // Generate a consistent ID from the data URL, similar to how it's done elsewhere
+ val nextId = nextEp.data.hashCode()
+ currentEpisodeId = nextId
+
+ showToast("Loading: ${nextEp.name}")
+
+ // Re-use logic to load media
+ withContext(Dispatchers.Main) {
+ // Determine if we have a direct URL (download) or need to fetch links
+ val downloadEp = carContext.getKey(
+ DOWNLOAD_EPISODE_CACHE,
+ nextId.toString()
+ )
+
+ if (downloadEp != null) {
+ // Verify file exists? For now assume yes if cached.
+ // We need the file URI. The original PlayerCarScreen invocation usually gets a fileUri passed in.
+ // But here we are switching. We might need to find the file path.
+ // Simplified: If in download mode, try to find the download.
+ // If streaming, just fetch links.
+ // For now, assume streaming or that loadMedia handles it via APIRepository if needed.
+ // But wait, loadMedia takes a URL. Episode.data is the url for load().
+
+ loadMedia(nextEp.data)
+ } else {
+ loadMedia(nextEp.data)
+ }
+ }
+ } else {
+ showToast("No more episodes")
+ }
+ }
+
+ private fun seekForward() {
+ player?.let { p ->
+ val newPos = p.currentPosition + 30_000 // +30 seconds
+ val duration = p.duration
+ p.seekTo(if (newPos > duration) duration else newPos)
+ updateStatus("+30s")
+ }
+ }
+
+ private fun updateStatus(status: String) {
+ if(status != "Playing") {
+ showToast(status)
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/ProviderCarScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/ProviderCarScreen.kt
new file mode 100644
index 00000000000..e2f86a2f4e4
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/ProviderCarScreen.kt
@@ -0,0 +1,42 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.APIHolder.apis
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+
+class ProviderCarScreen(carContext: CarContext) : Screen(carContext) {
+ override fun onGetTemplate(): Template {
+ val listBuilder = ItemList.Builder()
+
+ // Filter APIs mostly for simplicity, or show all
+ val current = DataStoreHelper.currentHomePage
+
+ apis.forEach { api ->
+ val row = Row.Builder()
+ .setTitle(api.name)
+ .setOnClickListener {
+ DataStoreHelper.currentHomePage = api.name
+ screenManager.pop() // Go back to Home which will reload
+ }
+
+ if (api.name == current) {
+ row.addText(CarStrings.get(R.string.car_selected))
+ }
+
+ listBuilder.addItem(row.build())
+ }
+
+ return ListTemplate.Builder()
+ .setSingleList(listBuilder.build())
+ .setTitle(CarStrings.get(R.string.car_select_provider))
+ .setHeaderAction(Action.BACK)
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/SearchCarScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/SearchCarScreen.kt
new file mode 100644
index 00000000000..03742ed5ff0
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/SearchCarScreen.kt
@@ -0,0 +1,119 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.Row
+import androidx.car.app.model.SearchTemplate
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.mvvm.Resource
+import com.lagradost.cloudstream3.ui.APIRepository
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.launch
+import androidx.car.app.CarToast
+import coil3.request.ImageRequest
+import coil3.SingletonImageLoader
+import coil3.asDrawable
+import androidx.core.graphics.drawable.toBitmap
+
+
+class SearchCarScreen(carContext: CarContext) : Screen(carContext) {
+
+ private var itemList: ItemList? = null
+ private var searchJob: Job? = null
+
+ private val searchCallback = object : SearchTemplate.SearchCallback {
+ override fun onSearchTextChanged(searchText: String) {
+ // Optional: Implement autocomplete here
+ }
+
+ override fun onSearchSubmitted(searchText: String) {
+ performSearch(searchText)
+ }
+ }
+
+ private fun performSearch(query: String) {
+ searchJob?.cancel()
+ searchJob = CoroutineScope(Dispatchers.IO).launch {
+ val apiName = DataStoreHelper.currentHomePage ?: return@launch
+ val api = getApiFromNameNull(apiName) ?: return@launch
+ val repo = APIRepository(api)
+
+ // Check if search requires page
+ when(val result = repo.search(query, 1)) {
+ is Resource.Success -> {
+ val builder = ItemList.Builder()
+ val items = result.value.items
+ if (items.isEmpty()) {
+ builder.setNoItemsMessage(CarStrings.get(R.string.car_no_results_found))
+ }
+
+ // Text-only results
+ items.map { item ->
+ val image = try {
+ if (!item.posterUrl.isNullOrEmpty()) {
+ val request = ImageRequest.Builder(carContext)
+ .data(item.posterUrl)
+ .size(128, 128)
+ .build()
+ val result = SingletonImageLoader.get(carContext).execute(request)
+ val bitmap = result.image?.asDrawable(carContext.resources)?.toBitmap()
+ if (bitmap != null) {
+ CarIcon.Builder(IconCompat.createWithBitmap(bitmap)).build()
+ } else null
+ } else null
+ } catch (e: Exception) {
+ null
+ } ?: CarIcon.Builder(IconCompat.createWithResource(carContext, R.mipmap.ic_launcher)).build()
+
+ builder.addItem(
+ Row.Builder()
+ .setTitle(item.name)
+ .setImage(image, Row.IMAGE_TYPE_LARGE)
+ .setOnClickListener {
+ val type = item.type
+ if (type == com.lagradost.cloudstream3.TvType.TvSeries ||
+ type == com.lagradost.cloudstream3.TvType.Anime ||
+ type == com.lagradost.cloudstream3.TvType.Cartoon ||
+ type == com.lagradost.cloudstream3.TvType.OVA ||
+ type == com.lagradost.cloudstream3.TvType.AsianDrama ||
+ type == com.lagradost.cloudstream3.TvType.Documentary) {
+ screenManager.push(TvSeriesDetailScreen(carContext, item))
+ } else {
+ screenManager.push(DetailsScreen(carContext, item))
+ }
+ }
+ .build()
+ )
+ }
+
+ itemList = builder.build()
+ invalidate()
+ }
+ is Resource.Failure -> {
+ // Handle error
+ }
+ else -> {}
+ }
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ return SearchTemplate.Builder(searchCallback)
+ .setSearchHint("${CarStrings.get(R.string.car_search)}...")
+ .setHeaderAction(Action.BACK)
+ .setShowKeyboardByDefault(true)
+ .setItemList(itemList ?: ItemList.Builder().build())
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/SourceSelectionScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/SourceSelectionScreen.kt
new file mode 100644
index 00000000000..ba49f0f6e4a
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/SourceSelectionScreen.kt
@@ -0,0 +1,132 @@
+package com.lagradost.cloudstream3.ui.car
+
+import android.graphics.Color
+import androidx.car.app.CarContext
+import androidx.car.app.CarToast
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ItemList
+import androidx.car.app.model.ListTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.utils.ExtractorLink
+import com.lagradost.cloudstream3.utils.Qualities
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Screen that displays available streaming sources for a content item.
+ * User can select a source, which will be used for playback.
+ *
+ * @param apiName The API/provider name to use for loading links
+ * @param dataUrl The data URL to load links for (movie URL or episode data)
+ * @param currentSourceUrl The currently selected source URL (for showing check mark)
+ * @param onSourceSelected Callback when a source is selected
+ */
+class SourceSelectionScreen(
+ carContext: CarContext,
+ private val apiName: String,
+ private val dataUrl: String,
+ private val currentSourceUrl: String? = null,
+ private val onSourceSelected: (ExtractorLink) -> Unit
+) : Screen(carContext) {
+
+ private val scope = CoroutineScope(Dispatchers.IO + Job())
+ private var isLoading = true
+ private var sources: List = emptyList()
+ private var errorMessage: String? = null
+
+ init {
+ loadSources()
+ }
+
+ private fun loadSources() {
+ scope.launch {
+ try {
+ val api = getApiFromNameNull(apiName)
+ if (api == null) {
+ errorMessage = CarStrings.get(R.string.car_provider_not_found)
+ isLoading = false
+ invalidate()
+ return@launch
+ }
+
+ val links = mutableListOf()
+ api.loadLinks(dataUrl, false, {}, { link ->
+ links.add(link)
+ })
+
+ withContext(Dispatchers.Main) {
+ if (links.isEmpty()) {
+ errorMessage = CarStrings.get(R.string.car_no_source_found)
+ } else {
+ // Sort by quality (highest first)
+ sources = links.sortedByDescending { it.quality }
+ }
+ isLoading = false
+ invalidate()
+ }
+ } catch (e: Exception) {
+ withContext(Dispatchers.Main) {
+ errorMessage = "${CarStrings.get(R.string.car_error)}: ${e.message}"
+ isLoading = false
+ invalidate()
+ }
+ }
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ val templateBuilder = ListTemplate.Builder()
+ .setTitle(CarStrings.get(R.string.car_sources))
+ .setHeaderAction(Action.BACK)
+
+ if (isLoading) {
+ // When loading, just set loading state without any list
+ templateBuilder.setLoading(true)
+ } else {
+ // Not loading - build the list
+ val listBuilder = ItemList.Builder()
+
+ if (errorMessage != null) {
+ listBuilder.setNoItemsMessage(errorMessage!!)
+ } else if (sources.isEmpty()) {
+ listBuilder.setNoItemsMessage(CarStrings.get(R.string.car_no_source_available))
+ } else {
+ // Add each source as a row
+ for (source in sources) {
+ val qualityStr = Qualities.getStringByInt(source.quality)
+ val title = if (qualityStr.isNotEmpty()) {
+ "${source.name} - $qualityStr"
+ } else {
+ source.name
+ }
+
+ val rowBuilder = Row.Builder()
+ .setTitle(title)
+ .addText(source.source)
+ .setOnClickListener {
+ onSourceSelected(source)
+ CarToast.makeText(carContext, "${CarStrings.get(R.string.car_source_selected)}: ${source.name}", CarToast.LENGTH_SHORT).show()
+ screenManager.pop()
+ }
+
+
+ listBuilder.addItem(rowBuilder.build())
+ }
+ }
+
+ templateBuilder.setSingleList(listBuilder.build())
+ templateBuilder.setLoading(false)
+ }
+
+ return templateBuilder.build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/car/TvSeriesDetailScreen.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/car/TvSeriesDetailScreen.kt
new file mode 100644
index 00000000000..5c41951ccc4
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/car/TvSeriesDetailScreen.kt
@@ -0,0 +1,195 @@
+package com.lagradost.cloudstream3.ui.car
+
+import androidx.car.app.CarContext
+import androidx.car.app.Screen
+import androidx.car.app.model.Action
+import androidx.car.app.model.CarColor
+import androidx.car.app.model.CarIcon
+import androidx.car.app.model.ForegroundCarColorSpan
+import androidx.car.app.model.Pane
+import androidx.car.app.model.PaneTemplate
+import androidx.car.app.model.Row
+import androidx.car.app.model.Template
+import androidx.core.graphics.drawable.IconCompat
+import androidx.core.graphics.drawable.toBitmap
+import coil3.asDrawable
+import coil3.request.ImageRequest
+import coil3.SingletonImageLoader
+import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
+import com.lagradost.cloudstream3.R
+import com.lagradost.cloudstream3.LoadResponse
+import com.lagradost.cloudstream3.SearchResponse
+import com.lagradost.cloudstream3.TvSeriesLoadResponse
+import com.lagradost.cloudstream3.mvvm.Resource
+import com.lagradost.cloudstream3.ui.APIRepository
+import com.lagradost.cloudstream3.utils.DataStoreHelper
+import com.lagradost.cloudstream3.utils.DataStoreHelper.FavoritesData
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import android.text.SpannableString
+import android.text.Spanned
+
+class TvSeriesDetailScreen(
+ carContext: CarContext,
+ private val item: SearchResponse
+) : Screen(carContext) {
+
+ private val scope = CoroutineScope(Dispatchers.IO + Job())
+ private var fullDetails: TvSeriesLoadResponse? = null
+ private var isLoading = true
+ private var errorMessage: String? = null
+ private var posterBitmap: android.graphics.Bitmap? = null
+ private var isFavorite: Boolean = false
+
+ init {
+ loadDetails()
+ }
+
+ private fun loadDetails() {
+ scope.launch {
+ // Load header image
+ if (!item.posterUrl.isNullOrEmpty()) {
+ try {
+ val request = ImageRequest.Builder(carContext)
+ .data(item.posterUrl)
+ .size(600, 900)
+ .build()
+ val result = SingletonImageLoader.get(carContext).execute(request)
+ posterBitmap = result.image?.asDrawable(carContext.resources)?.toBitmap()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+
+ // Load full details
+ val api = getApiFromNameNull(item.apiName)
+ if (api != null) {
+ val repo = APIRepository(api)
+ when (val result = repo.load(item.url)) {
+ is Resource.Success -> {
+ val data = result.value
+ if (data is TvSeriesLoadResponse) {
+ fullDetails = data
+ // Check Favorite status
+ val id = data.url.replace(api.mainUrl, "").replace("/", "").hashCode()
+ isFavorite = DataStoreHelper.getFavoritesData(id) != null
+ } else {
+ errorMessage = CarStrings.get(R.string.car_not_tv_series)
+ }
+ isLoading = false
+ }
+ is Resource.Failure -> {
+ errorMessage = result.errorString ?: CarStrings.get(R.string.car_error_loading_details)
+ isLoading = false
+ }
+ is Resource.Loading -> {}
+ }
+ } else {
+ errorMessage = CarStrings.get(R.string.car_provider_not_found)
+ isLoading = false
+ }
+ invalidate()
+ }
+ }
+
+ private fun toggleFavorite() {
+ CarHelper.toggleFavorite(carContext, fullDetails, isFavorite) { newStatus ->
+ isFavorite = newStatus
+ invalidate()
+ }
+ }
+
+ override fun onGetTemplate(): Template {
+ val paneBuilder = Pane.Builder()
+
+ if (isLoading) {
+ paneBuilder.setLoading(true)
+ } else {
+ val details = fullDetails
+
+ // Header: Title
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(details?.name ?: item.name)
+ .build()
+ )
+
+ // Include Hero Image if available
+ posterBitmap?.let {
+ paneBuilder.setImage(CarIcon.Builder(IconCompat.createWithBitmap(it)).build())
+ } ?: run {
+ paneBuilder.setImage(CarIcon.Builder(IconCompat.createWithResource(carContext, R.mipmap.ic_launcher)).build())
+ }
+
+ if (details != null) {
+ // Meta Row: Year • Score • Duration/Seasons
+ val metaStringBuilder = StringBuilder()
+ details.year?.let { metaStringBuilder.append("$it") }
+
+ val score = details.score
+ if (score != null) {
+ if (metaStringBuilder.isNotEmpty()) metaStringBuilder.append(" • ")
+ metaStringBuilder.append(String.format("%.1f/10", score.toDouble(10)))
+ }
+
+ // Show season count in meta
+ // details.seasonNames could be used, or just aggregating episodes
+ val seasonCount = details.episodes.mapNotNull { it.season }.distinct().count()
+ if (metaStringBuilder.isNotEmpty()) metaStringBuilder.append(" • ")
+ metaStringBuilder.append("$seasonCount ${CarStrings.get(R.string.car_seasons)}")
+
+ if (metaStringBuilder.isNotEmpty()) {
+ paneBuilder.addRow(
+ Row.Builder()
+ .setTitle(metaStringBuilder.toString())
+ .build()
+ )
+ }
+
+ // Favorite Action
+ val favoriteIconRes = if (isFavorite) R.drawable.ic_baseline_favorite_24 else R.drawable.ic_baseline_favorite_border_24
+ val favoriteIcon = IconCompat.createWithResource(carContext, favoriteIconRes)
+ if (isFavorite) {
+ favoriteIcon.setTint(0xFFFF0000.toInt()) // Red
+ } else {
+ favoriteIcon.setTint(android.graphics.Color.WHITE) // White
+ }
+
+ val favoriteAction = Action.Builder()
+ .setIcon(CarIcon.Builder(favoriteIcon).build())
+ .setOnClickListener {
+ toggleFavorite()
+ }
+ .build()
+
+ // Episodes Button Action
+ // "Episode List >"
+ paneBuilder.addAction(
+ Action.Builder()
+ .setTitle(CarStrings.get(R.string.car_episode_list))
+ .setBackgroundColor(CarColor.PRIMARY)
+ .setOnClickListener {
+ screenManager.push(EpisodeListScreen(carContext, details))
+ }
+ .build()
+ )
+
+ paneBuilder.addAction(favoriteAction)
+
+ // Plot and Cast
+ CarHelper.addPlotAndCast(paneBuilder, details)
+
+ } else if (errorMessage != null) {
+ paneBuilder.addRow(Row.Builder().setTitle("${CarStrings.get(R.string.car_error)}: $errorMessage").build())
+ }
+ }
+
+ return PaneTemplate.Builder(paneBuilder.build())
+ .setTitle(item.name)
+ .setHeaderAction(Action.BACK)
+ .build()
+ }
+}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt
index 49c6d0d7732..6fe20e4e648 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt
@@ -847,6 +847,11 @@ class HomeFragment : BaseFragment(
return@observeNullable
}
+ // Fix: Prevent WindowLeaked crash if activity is not in a valid state (e.g. when using Android Auto)
+ if (activity?.isFinishing == true || activity?.isDestroyed == true || !lifecycle.currentState.isAtLeast(androidx.lifecycle.Lifecycle.State.RESUMED)) {
+ return@observeNullable
+ }
+
// don't recreate
if (bottomSheetDialog != null) {
return@observeNullable
diff --git a/app/src/main/res-car/values-b+af/strings_car.xml b/app/src/main/res-car/values-b+af/strings_car.xml
new file mode 100644
index 00000000000..f39d2aacfe2
--- /dev/null
+++ b/app/src/main/res-car/values-b+af/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Laai tans...
+ Fout
+ Fout met laai van inhoud
+ Gunstelinge
+ Geskiedenis
+ Aflaaie
+ Verskaffer
+ Huidige
+ Kieslys
+ Tuisinhoud
+ Geen inhoud van verskaffer
+ Verskaffer nie gevind nie
+ Bron
+ Bronne
+ Storielyn
+ Rolverdeling
+ Fout met laai van besonderhede
+ Episode lys
+ Seisoen
+ Seisoene
+ Episode
+ Geen episodes gevind nie
+ Nie \'n TV-reeks nie
+ By gunstelinge gevoeg
+ Van gunstelinge verwyder
+ Geen gunstelinge gevind nie
+ Begin terugspeel...
+ Speel tans
+ Geen skakel gevind nie
+ Geen speelbare inhoud gevind nie
+ Kan nie besonderhede laai nie
+ Fout met laai van skakels
+ Pas by skerm
+ Vul skerm
+ Geen bron gevind nie
+ Geen bron beskikbaar nie
+ Bron gekies
+ Soek
+ Geen resultate gevind nie
+ \'Gaan voort om te kyk\' nie gevind nie
+ Geen aflaaie gevind nie
+ Lêer nie gevind nie
+ Geen geldige episode gevind nie
+ Kies Verskaffer
+ Gekies
+ Biblioteek
+ Boekmerke
+ Hervat %1$s...
+
diff --git a/app/src/main/res-car/values-b+am/strings_car.xml b/app/src/main/res-car/values-b+am/strings_car.xml
new file mode 100644
index 00000000000..73d1b93ae2e
--- /dev/null
+++ b/app/src/main/res-car/values-b+am/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ በመጫን ላይ...
+ ስህተት
+ ይዘት በመጫን ላይ ስህተት
+ ተወዳጆች
+ ታሪክ
+ ውርዶች
+ አቅራቢ
+ የአሁኑ
+ ምናሌ
+ የመነሻ ይዘት
+ ከአቅራቢው ምንም ይዘት የለም
+ አቅራቢ አልተገኘም
+ ምንጭ
+ ምንጮች
+ ሴራ
+ ተዋንያን
+ ዝርዝሮችን በመጫን ላይ ስህተት
+ የክፍሎች ዝርዝር
+ ወቅት
+ ወቅቶች
+ ክፍል
+ ምንም ክፍሎች አልተገኙም
+ የቲቪ ተከታታይ አይደለም
+ ወደ ተወዳጆች ታክሏል
+ ከተወዳጆች ተወግዷል
+ ምንም ተወዳጆች አልተገኙም
+ ማጫወት በመጀመር ላይ...
+ በማጫወት ላይ
+ ምንም አገናኝ አልተገኘም
+ ምንም የሚጫወት ይዘት አልተገኘም
+ ዝርዝሮችን መጫን አልተቻለም
+ አገናኞችን በመጫን ላይ ስህተት
+ ስክሪን ላይ ይግጠም
+ ስክሪን ይሙሉ
+ ምንም ምንጭ አልተገኘም
+ ምንም ምንጭ የለም
+ ምንጭ ተመርጧል
+ ፈልግ
+ ምንም ውጤቶች አልተገኙም
+ \'መመልከት ይቀጥሉ\' አልተገኘም
+ ምንም ውርዶች አልተገኙም
+ ፋይል አልተገኘም
+ ምንም ትክክለኛ ክፍል አልተገኘም
+ አቅራቢ ይምረጡ
+ ተመርጧል
+ ቤተ-መጽሐፍት
+ ዕልባቶች
+ %1$s በመቀጠል ላይ...
+
diff --git a/app/src/main/res-car/values-b+apc/strings_car.xml b/app/src/main/res-car/values-b+apc/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+apc/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+ar/strings_car.xml b/app/src/main/res-car/values-b+ar/strings_car.xml
new file mode 100644
index 00000000000..2f75de73f8e
--- /dev/null
+++ b/app/src/main/res-car/values-b+ar/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ جارٍ التحميل...
+ خطأ
+ خطأ في تحميل المحتوى
+ المفضلة
+ السجل
+ التنزيلات
+ المزود
+ الحالي
+ القائمة
+ محتوى الصفحة الرئيسية
+ لا يوجد محتوى من المزود
+ المزود غير موجود
+ المصدر
+ المصادر
+ القصة
+ الممثلون
+ خطأ في تحميل التفاصيل
+ قائمة الحلقات
+ الموسم
+ المواسم
+ الحلقة
+ لم يتم العثور على حلقات
+ ليس مسلسلاً تلفزيونياً
+ تمت الإضافة إلى المفضلة
+ تمت الإزالة من المفضلة
+ لم يتم العثور على مفضلة
+ بدء التشغيل...
+ تشغيل
+ لم يتم العثور على رابط
+ لم يتم العثور على محتوى قابل للتشغيل
+ تعذر تحميل التفاصيل
+ خطأ في تحميل الروابط
+ ملاءمة للشاشة
+ ملء الشاشة
+ لم يتم العثور على مصدر
+ لا يوجد مصدر متاح
+ تم اختيار المصدر
+ بحث
+ لم يتم العثور على نتائج
+ لم يتم العثور على \'متابعة المشاهدة\'
+ لم يتم العثور على تنزيلات
+ الملف غير موجود
+ لا توجد حلقة صالحة
+ اختر المزود
+ محدد
+ المكتبة
+ الإشارات المرجعية
+ استئناف %1$s...
+
diff --git a/app/src/main/res-car/values-b+ars/strings_car.xml b/app/src/main/res-car/values-b+ars/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+ars/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+as/strings_car.xml b/app/src/main/res-car/values-b+as/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+as/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+az/strings_car.xml b/app/src/main/res-car/values-b+az/strings_car.xml
new file mode 100644
index 00000000000..2d7a522db98
--- /dev/null
+++ b/app/src/main/res-car/values-b+az/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Yüklənir...
+ Xəta
+ Məzmun yüklənərkən xəta
+ Sevimlilər
+ Tarixçə
+ Yükləmələr
+ Provayder
+ Cari
+ Menyu
+ Ana səhifə məzmunu
+ Provayderdən məzmun yoxdur
+ Provayder tapılmadı
+ Mənbə
+ Mənbələr
+ Süjet
+ Rollarda
+ Təfərrüatları yükləyərkən xəta
+ Epizod siyahısı
+ Mövsüm
+ Mövsümlər
+ Epizod
+ Epizod tapılmadı
+ TV serialı deyil
+ Sevimlilərə əlavə edildi
+ Sevimlilərdən silindi
+ Sevimli tapılmadı
+ Oxutma başlayır...
+ Oxudulur
+ Link tapılmadı
+ Oxudula bilən məzmun tapılmadı
+ Təfərrüatları yükləmək mümkün olmadı
+ Linkləri yükləyərkən xəta
+ Ekranı uyğunlaşdır
+ Ekranı doldur
+ Mənbə tapılmadı
+ Mövcud mənbə yoxdur
+ Mənbə seçildi
+ Axtarış
+ Nəticə tapılmadı
+ \'İzləməyə davam et\' tapılmadı
+ Yükləmə tapılmadı
+ Fayl tapılmadı
+ Etibarlı epizod tapılmadı
+ Provayder seç
+ Seçildi
+ Kitabxana
+ Əlfəcinlər
+ %1$s davam etdirilir...
+
diff --git a/app/src/main/res-car/values-b+be/strings_car.xml b/app/src/main/res-car/values-b+be/strings_car.xml
new file mode 100644
index 00000000000..4601e262724
--- /dev/null
+++ b/app/src/main/res-car/values-b+be/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Загрузка...
+ Памылка
+ Памылка загрузкі кантэнту
+ Выбранае
+ Гісторыя
+ Спампоўкі
+ Пастаўшчык
+ Бягучы
+ Меню
+ Галоўны кантэнт
+ Няма кантэнту ад пастаўшчыка
+ Пастаўшчык не знойдзены
+ Крыніца
+ Крыніцы
+ Сюжэт
+ Акцёры
+ Памылка загрузкі дэталяў
+ Спіс серый
+ Сезон
+ Сезоны
+ Серыя
+ Серый не знойдзена
+ Не серыял
+ Дададзена ў выбранае
+ Выдалена з выбранага
+ Няма выбранага
+ Пачатак прайгравання...
+ Прайграванне
+ Спасылка не знойдзена
+ Няма кантэнту для прайгравання
+ Не ўдалося загрузіць дэталі
+ Памылка загрузкі спасылак
+ Па памеры экрана
+ Запоўніць экран
+ Крыніца не знойдзена
+ Няма даступных крыніц
+ Крыніца выбрана
+ Пошук
+ Вынікаў не знойдзена
+ \'Працягнуць прагляд\' не знойдзена
+ Няма спамповак
+ Файл не знойдзены
+ Няма сапраўднай серыі
+ Выберыце пастаўшчыка
+ Выбрана
+ Бібліятэка
+ Закладкі
+ Аднаўленне %1$s...
+
diff --git a/app/src/main/res-car/values-b+bg/strings_car.xml b/app/src/main/res-car/values-b+bg/strings_car.xml
new file mode 100644
index 00000000000..9c7ba83e426
--- /dev/null
+++ b/app/src/main/res-car/values-b+bg/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Зареждане...
+ Грешка
+ Грешка при зареждане на съдържание
+ Любими
+ История
+ Изтегляния
+ Доставчик
+ Текущ
+ Меню
+ Начално съдържание
+ Няма съдържание от доставчика
+ Доставчикът не е намерен
+ Източник
+ Източници
+ Сюжет
+ Актьорски състав
+ Грешка при зареждане на детайли
+ Списък с епизоди
+ Сезон
+ Сезони
+ Епизод
+ Няма намерени епизоди
+ Не е ТВ сериал
+ Добавено към любими
+ Премахнато от любими
+ Няма намерени любими
+ Стартиране на възпроизвеждане...
+ Възпроизвеждане
+ Няма намерена връзка
+ Няма намерено съдържание за възпроизвеждане
+ Не може да се заредят детайли
+ Грешка при зареждане на връзки
+ Побиране на екрана
+ Запълване на екрана
+ Няма намерен източник
+ Няма наличен източник
+ Избран източник
+ Търсене
+ Няма намерени резултати
+ Няма намерено \'Продължи гледането\'
+ Няма намерени изтегляния
+ Файлът не е намерен
+ Няма намерен валиден епизод
+ Избор на доставчик
+ Избрано
+ Библиотека
+ Отметки
+ Възобновяване %1$s...
+
diff --git a/app/src/main/res-car/values-b+bn/strings_car.xml b/app/src/main/res-car/values-b+bn/strings_car.xml
new file mode 100644
index 00000000000..fb8281709e4
--- /dev/null
+++ b/app/src/main/res-car/values-b+bn/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ লোড হচ্ছে...
+ ত্রুটি
+ কন্টেন্ট লোড করতে ত্রুটি
+ পছন্দ
+ ইতিহাস
+ ডাউনলোড
+ প্রদানকারী
+ বর্তমান
+ মেনু
+ হোম কন্টেন্ট
+ প্রদানকারী থেকে কোন কন্টেন্ট নেই
+ প্রদানকারী পাওয়া যায়নি
+ উৎস
+ উৎসসমূহ
+ কাহিনী
+ কুশীলব
+ বিস্তারিত লোড করতে ত্রুটি
+ পর্বের তালিকা
+ সিজন
+ সিজনসমূহ
+ পর্ব
+ কোন পর্ব পাওয়া যায়নি
+ টিভি সিরিজ নয়
+ পছন্দে যোগ করা হয়েছে
+ পছন্দ থেকে সরানো হয়েছে
+ কোন পছন্দ পাওয়া যায়নি
+ প্লেব্যাক শুরু হচ্ছে...
+ চলছে
+ কোন লিঙ্ক পাওয়া যায়নি
+ কোন চালানোর যোগ্য কন্টেন্ট পাওয়া যায়নি
+ বিস্তারিত লোড করা যায়নি
+ লিঙ্ক লোড করতে ত্রুটি
+ স্ক্রিনে মানানসই করুন
+ স্ক্রিন পূর্ণ করুন
+ কোন উৎস পাওয়া যায়নি
+ কোন উৎস উপলব্ধ নেই
+ উৎস নির্বাচিত
+ অনুসন্ধান
+ কোন ফলাফল পাওয়া যায়নি
+ \'দেখা চালিয়ে যান\' পাওয়া যায়নি
+ কোন ডাউনলোড পাওয়া যায়নি
+ ফাইল পাওয়া যায়নি
+ কোন বৈধ পর্ব পাওয়া যায়নি
+ প্রদানকারী নির্বাচন করুন
+ নির্বাচিত
+ লাইব্রেরি
+ বুকমার্ক
+ %1$s পুনরায় শুরু হচ্ছে...
+
diff --git a/app/src/main/res-car/values-b+bs/strings_car.xml b/app/src/main/res-car/values-b+bs/strings_car.xml
new file mode 100644
index 00000000000..dfbc9fef949
--- /dev/null
+++ b/app/src/main/res-car/values-b+bs/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Učitavanje...
+ Greška
+ Greška pri učitavanju sadržaja
+ Omiljeni
+ Historija
+ Preuzimanja
+ Provajder
+ Trenutno
+ Meni
+ Početni sadržaj
+ Nema sadržaja od provajdera
+ Provajder nije pronađen
+ Izvor
+ Izvori
+ Radnja
+ Uloge
+ Greška pri učitavanju detalja
+ Lista epizoda
+ Sezona
+ Sezone
+ Epizoda
+ Nema pronađenih epizoda
+ Nije TV serija
+ Dodano u omiljene
+ Uklonjeno iz omiljenih
+ Nema omiljenih
+ Pokretanje reprodukcije...
+ Reprodukcija
+ Link nije pronađen
+ Sadržaj za reprodukciju nije pronađen
+ Nije moguće učitati detalje
+ Greška pri učitavanju linkova
+ Prilagodi ekranu
+ Popuni ekran
+ Izvor nije pronađen
+ Izvor nije dostupan
+ Izvor odabran
+ Pretraga
+ Nema rezultata
+ \'Nastavi gledanje\' nije pronađeno
+ Nema preuzimanja
+ Datoteka nije pronađena
+ Nema važeće epizode
+ Izaberi provajdera
+ Odabrano
+ Biblioteka
+ Obeleživači
+ Nastavljanje %1$s...
+
diff --git a/app/src/main/res-car/values-b+ca/strings_car.xml b/app/src/main/res-car/values-b+ca/strings_car.xml
new file mode 100644
index 00000000000..6a7e285ec11
--- /dev/null
+++ b/app/src/main/res-car/values-b+ca/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Carregant...
+ Error
+ Error carregant contingut
+ Preferits
+ Historial
+ Descàrregues
+ Proveïdor
+ Actual
+ Menú
+ Contingut d\'inici
+ Sense contingut del proveïdor
+ Proveïdor no trobat
+ Font
+ Fonts
+ Argument
+ Repartiment
+ Error carregant detalls
+ Llista d\'episodis
+ Temporada
+ Temporades
+ Episodi
+ No s\'han trobat episodis
+ No és una sèrie de TV
+ Afegit a preferits
+ Eliminat de preferits
+ Cap preferit trobat
+ Iniciant reproducció...
+ Reproduint
+ Enllaç no trobat
+ Contingut reproduïble no trobat
+ No es poden carregar els detalls
+ Error carregant enllaços
+ Ajustar a la pantalla
+ Omplir la pantalla
+ Font no trobada
+ Cap font disponible
+ Font seleccionada
+ Cercar
+ Sense resultats
+ \'Continuar mirant\' no trobat
+ Sense descàrregues
+ Fitxer no trobat
+ Cap episodi vàlid
+ Seleccionar proveïdor
+ Seleccionat
+ Biblioteca
+ Marcadors
+ Reprenent %1$s...
+
diff --git a/app/src/main/res-car/values-b+ckb/strings_car.xml b/app/src/main/res-car/values-b+ckb/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+ckb/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+cs/strings_car.xml b/app/src/main/res-car/values-b+cs/strings_car.xml
new file mode 100644
index 00000000000..d9011304d0a
--- /dev/null
+++ b/app/src/main/res-car/values-b+cs/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Načítání...
+ Chyba
+ Chyba při načítání obsahu
+ Oblíbené
+ Historie
+ Stažené
+ Poskytovatel
+ Aktuální
+ Menu
+ Domovský obsah
+ Žádný obsah od poskytovatele
+ Poskytovatel nenalezen
+ Zdroj
+ Zdroje
+ Děj
+ Obsazení
+ Chyba při načítání podrobností
+ Seznam epizod
+ Série
+ Série
+ Epizoda
+ Nenalezeny žádné epizody
+ Není TV seriál
+ Přidáno do oblíbených
+ Odebráno z oblíbených
+ Nenalezeny žádné oblíbené
+ Spouštění přehrávání...
+ Přehrávání
+ Odkaz nenalezen
+ Nenalezen žádný přehrávatelný obsah
+ Nelze načíst podrobnosti
+ Chyba při načítání odkazů
+ Přizpůsobit obrazovce
+ Vyplnit obrazovku
+ Zdroj nenalezen
+ Žádný zdroj k dispozici
+ Zdroj vybrán
+ Hledat
+ Nenalezeny žádné výsledky
+ Nenalezeno \'Pokračovat ve sledování\'
+ Nenalezeny žádné stažené soubory
+ Soubor nenalezen
+ Nenalezena žádná platná epizoda
+ Vybrat poskytovatele
+ Vybráno
+ Knihovna
+ Záložky
+ Obnovování %1$s...
+
diff --git a/app/src/main/res-car/values-b+da/strings_car.xml b/app/src/main/res-car/values-b+da/strings_car.xml
new file mode 100644
index 00000000000..afb929b5b50
--- /dev/null
+++ b/app/src/main/res-car/values-b+da/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Indlæser...
+ Fejl
+ Fejl ved indlæsning af indhold
+ Favoritter
+ Historik
+ Downloads
+ Udbydere
+ Nuværende
+ Menu
+ Hjemmeindhold
+ Intet indhold fra udbyder
+ Udbyder ikke fundet
+ Kilde
+ Kilder
+ Handling
+ Medvirkende
+ Fejl ved indlæsning af detaljer
+ Afsnitsliste
+ Sæson
+ Sæsoner
+ Afsnit
+ Ingen afsnit fundet
+ Ikke en TV-serie
+ Tilføjet til favoritter
+ Fjernet fra favoritter
+ Ingen favoritter fundet
+ Starter afspilning...
+ Afspiller
+ Intet link fundet
+ Intet afspilleligt indhold fundet
+ Kunne ikke indlæse detaljer
+ Fejl ved indlæsning af links
+ Tilpas til skærm
+ Fyld skærm
+ Ingen kilde fundet
+ Ingen kilde tilgængelig
+ Kilde valgt
+ Søg
+ Ingen resultater fundet
+ \'Fortsæt med at se\' ikke fundet
+ Ingen downloads fundet
+ Fil ikke fundet
+ Intet gyldigt afsnit fundet
+ Vælg udbyder
+ Valgt
+ Bibliotek
+ Bogmærker
+ Genoptager %1$s...
+
diff --git a/app/src/main/res-car/values-b+de/strings_car.xml b/app/src/main/res-car/values-b+de/strings_car.xml
new file mode 100644
index 00000000000..2c88723f817
--- /dev/null
+++ b/app/src/main/res-car/values-b+de/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Laden...
+ Fehler
+ Fehler beim Laden des Inhalts
+ Favoriten
+ Verlauf
+ Downloads
+ Anbieter
+ Aktuell
+ Menü
+ Startseiteninhalt
+ Kein Inhalt vom Anbieter
+ Anbieter nicht gefunden
+ Quelle
+ Quellen
+ Handlung
+ Besetzung
+ Fehler beim Laden der Details
+ Episodenliste
+ Staffel
+ Staffeln
+ Episode
+ Keine Episoden gefunden
+ Keine TV-Serie
+ Zu Favoriten hinzugefügt
+ Aus Favoriten entfernt
+ Keine Favoriten gefunden
+ Wiedergabe wird gestartet...
+ Wiedergabe
+ Kein Link gefunden
+ Kein abspielbarer Inhalt gefunden
+ Details konnten nicht geladen werden
+ Fehler beim Laden der Links
+ An Bildschirm anpassen
+ Bildschirm füllen
+ Keine Quelle gefunden
+ Keine Quelle verfügbar
+ Quelle ausgewählt
+ Suchen
+ Keine Ergebnisse gefunden
+ Keine \'Weiterschauen\'-Elemente gefunden
+ Keine Downloads gefunden
+ Datei nicht gefunden
+ Keine gültige Episode gefunden
+ Anbieter auswählen
+ Ausgewählt
+ Bibliothek
+ Lesezeichen
+ Setze %1$s fort...
+
diff --git a/app/src/main/res-car/values-b+el/strings_car.xml b/app/src/main/res-car/values-b+el/strings_car.xml
new file mode 100644
index 00000000000..fd08dfb2f56
--- /dev/null
+++ b/app/src/main/res-car/values-b+el/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Φόρτωση...
+ Σφάλμα
+ Σφάλμα φόρτωσης περιεχομένου
+ Αγαπημένα
+ Ιστορικό
+ Λήψεις
+ Πάροχος
+ Τρέχον
+ Μενού
+ Περιεχόμενο αρχικής σελίδας
+ Δεν υπάρχει περιεχόμενο από τον πάροχο
+ Ο πάροχος δεν βρέθηκε
+ Πηγή
+ Πηγές
+ Πλοκή
+ Ηθοποιοί
+ Σφάλμα φόρτωσης λεπτομερειών
+ Λίστα επεισοδίων
+ Σεζόν
+ Σεζόν
+ Επεισόδιο
+ Δεν βρέθηκαν επεισόδια
+ Δεν είναι τηλεοπτική σειρά
+ Προστέθηκε στα αγαπημένα
+ Αφαιρέθηκε από τα αγαπημένα
+ Δεν βρέθηκαν αγαπημένα
+ Έναρξη αναπαραγωγής...
+ Αναπαραγωγή
+ Δεν βρέθηκε σύνδεσμος
+ Δεν βρέθηκε περιεχόμενο για αναπαραγωγή
+ Αδυναμία φόρτωσης λεπτομερειών
+ Σφάλμα φόρτωσης συνδέσμων
+ Προσαρμογή στην οθόνη
+ Γέμισμα οθόνης
+ Δεν βρέθηκε πηγή
+ Καμία διαθέσιμη πηγή
+ Επιλέχθηκε πηγή
+ Αναζήτηση
+ Δεν βρέθηκαν αποτελέσματα
+ Δεν βρέθηκε \'Συνέχεια παρακολούθησης\'
+ Δεν βρέθηκαν λήψεις
+ Το αρχείο δεν βρέθηκε
+ Δεν βρέθηκε έγκυρο επεισόδιο
+ Επιλογή παρόχου
+ Επιλεγμένο
+ Βιβλιοθήκη
+ Σελιδοδείκτες
+ Συνέχιση %1$s...
+
diff --git a/app/src/main/res-car/values-b+eo/strings_car.xml b/app/src/main/res-car/values-b+eo/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+eo/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+es/strings_car.xml b/app/src/main/res-car/values-b+es/strings_car.xml
new file mode 100644
index 00000000000..515293d8a82
--- /dev/null
+++ b/app/src/main/res-car/values-b+es/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Cargando...
+ Error
+ Error al cargar contenido
+ Favoritos
+ Historial
+ Descargas
+ Proveedor
+ Actual
+ Menú
+ Contenido de inicio
+ Sin contenido del proveedor
+ Proveedor no encontrado
+ Fuente
+ Fuentes
+ Trama
+ Reparto
+ Error al cargar detalles
+ Lista de episodios
+ Temporada
+ Temporadas
+ Episodio
+ No se encontraron episodios
+ No es una serie de TV
+ Añadido a favoritos
+ Eliminado de favoritos
+ No se encontraron favoritos
+ Iniciando reproducción...
+ Reproduciendo
+ No se encontró enlace
+ No se encontró contenido reproducible
+ No se pudieron cargar los detalles
+ Error al cargar enlaces
+ Ajustar a la pantalla
+ Llenar pantalla
+ No se encontró fuente
+ Ninguna fuente disponible
+ Fuente seleccionada
+ Buscar
+ No se encontraron resultados
+ No se encontró \'Continuar viendo\'
+ No se encontraron descargas
+ Archivo no encontrado
+ No se encontró episodio válido
+ Seleccionar proveedor
+ Seleccionado
+ Biblioteca
+ Marcadores
+ Reanudando %1$s...
+
diff --git a/app/src/main/res-car/values-b+et/strings_car.xml b/app/src/main/res-car/values-b+et/strings_car.xml
new file mode 100644
index 00000000000..64067503545
--- /dev/null
+++ b/app/src/main/res-car/values-b+et/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Laadimine...
+ Viga
+ Sisu laadimise viga
+ Lemmikud
+ Ajalugu
+ Allalaadimised
+ Teenusepakkuja
+ Praegune
+ Menüü
+ Avalehe sisu
+ Teenusepakkujalt puudub sisu
+ Teenusepakkujat ei leitud
+ Allikas
+ Allikad
+ Sisu
+ Osades
+ Viga üksikasjade laadimisel
+ Episoodide loend
+ Hooaeg
+ Hooajad
+ Episood
+ Episoode ei leitud
+ Ei ole telesari
+ Lisatud lemmikutesse
+ Eemaldatud lemmikutest
+ Lemmikuid ei leitud
+ Taasesituse alustamine...
+ Esitamine
+ Link ei leitud
+ Mängitavat sisu ei leitud
+ Üksikasju ei saa laadida
+ Viga linkide laadimisel
+ Mahuta ekraanile
+ Täida ekraan
+ Allikat ei leitud
+ Ühtegi allikat pole saadaval
+ Allikas valitud
+ Otsi
+ Tulemusi ei leitud
+ \'Jätka vaatamist\' ei leitud
+ Allalaadimisi ei leitud
+ Faili ei leitud
+ Kehtivat episoodi ei leitud
+ Vali teenusepakkuja
+ Valitud
+ Raamatukogu
+ Järjehoidjad
+ Jätkamine %1$s...
+
diff --git a/app/src/main/res-car/values-b+eu/strings_car.xml b/app/src/main/res-car/values-b+eu/strings_car.xml
new file mode 100644
index 00000000000..dd794473078
--- /dev/null
+++ b/app/src/main/res-car/values-b+eu/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Kargatzen...
+ Errorea
+ Errorea edukia kargatzean
+ Gogokoak
+ Historia
+ Deskargak
+ Hornitzailea
+ Unekoa
+ Menua
+ Hasierako edukia
+ Hornitzailearen edukirik ez
+ Hornitzailea ez da aurkitu
+ Iturburua
+ Iturburuak
+ Argumentua
+ Aktoreak
+ Errorea xehetasunak kargatzean
+ Atalen zerrenda
+ Denboraldia
+ Denboraldiak
+ Atala
+ Ez da atalik aurkitu
+ Ez da telebista saioa
+ Gogokoetan gehitu da
+ Gogokoetatik kendu da
+ Ez da gogokorik aurkitu
+ Erreprodukzioa hasten...
+ Erreproduzitzen
+ Ez da estekarik aurkitu
+ Ez da erreproduzitzeko edukirik aurkitu
+ Ezin dira xehetasunak kargatu
+ Errorea estekak kargatzean
+ Doitu pantailara
+ Bete pantaila
+ Ez da iturbururik aurkitu
+ Ez dago iturbururik eskuragarri
+ Iturburua hautatuta
+ Bilatu
+ Ez da emaitzarik aurkitu
+ Ez da \'Jarraitu ikusten\' aurkitu
+ Ez da deskargarik aurkitu
+ Ez da fitxategia aurkitu
+ Ez da baliozko atalik aurkitu
+ Hautatu hornitzailea
+ Hautatuta
+ Liburutegia
+ Laster-markak
+ %1$s jarraitzen...
+
diff --git a/app/src/main/res-car/values-b+fa/strings_car.xml b/app/src/main/res-car/values-b+fa/strings_car.xml
new file mode 100644
index 00000000000..8c23b79e7fd
--- /dev/null
+++ b/app/src/main/res-car/values-b+fa/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ درحال بارگذاری...
+ خطا
+ خطا در بارگذاری محتوا
+ علاقهمندیها
+ تاریخچه
+ دانلودها
+ ارائهدهنده
+ کنونی
+ منو
+ محتوای خانه
+ بدون محتوا از ارائهدهنده
+ ارائهدهنده یافت نشد
+ منبع
+ منابع
+ داستان
+ بازیگران
+ خطا در بارگذاری جزئیات
+ لیست قسمتها
+ فصل
+ فصلها
+ قسمت
+ قسمتی یافت نشد
+ سریال تلویزیونی نیست
+ به علاقهمندیها اضافه شد
+ از علاقهمندیها حذف شد
+ علاقهمندی یافت نشد
+ شروع پخش...
+ درحال پخش
+ لینکی یافت نشد
+ محتوای قابل پخش یافت نشد
+ ناتوان در بارگذاری جزئیات
+ خطا در بارگذاری لینکها
+ فیت صفحه
+ پر کردن صفحه
+ منبع یافت نشد
+ منبعی در دسترس نیست
+ منبع انتخاب شد
+ جستجو
+ نتیجهای یافت نشد
+ \'ادامه تماشا\' یافت نشد
+ دانلودی یافت نشد
+ فایل یافت نشد
+ قسمت معتبری یافت نشد
+ انتخاب ارائهدهنده
+ انتخاب شد
+ کتابخانه
+ نشانکها
+ درحال ادامه %1$s...
+
diff --git a/app/src/main/res-car/values-b+fi/strings_car.xml b/app/src/main/res-car/values-b+fi/strings_car.xml
new file mode 100644
index 00000000000..4c609c8cfcb
--- /dev/null
+++ b/app/src/main/res-car/values-b+fi/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Ladataan...
+ Virhe
+ Virhe ladattaessa sisältöä
+ Suosikit
+ Historia
+ Lataukset
+ Palveluntarjoaja
+ Nykyinen
+ Valikko
+ Etusivun sisältö
+ Ei sisältöä palveluntarjoajalta
+ Palveluntarjoajaa ei löytynyt
+ Lähde
+ Lähteet
+ Juoni
+ Näyttelijät
+ Virhe ladattaessa tietoja
+ Jaksot
+ Kausi
+ Kaudet
+ Jakso
+ Jaksoja ei löytynyt
+ Ei TV-sarja
+ Lisätty suosikkeihin
+ Poistettu suosikeista
+ Ei suosikkeja löytynyt
+ Aloitetaan toistoa...
+ Toistetaan
+ Linkkiä ei löytynyt
+ Toistettavaa sisältöä ei löytynyt
+ Tietoja ei voitu ladata
+ Virhe ladattaessa linkkejä
+ Sovita näyttöön
+ Täytä näyttö
+ Lähdettä ei löytynyt
+ Ei lähdettä saatavilla
+ Lähde valittu
+ Haku
+ Tuloksia ei löytynyt
+ \'Jatka katselua\' ei löytynyt
+ Latauksia ei löytynyt
+ Tiedostoa ei löytynyt
+ Kelvollista jaksoa ei löytynyt
+ Valitse palveluntarjoaja
+ Valittu
+ Kirjasto
+ Kirjanmerkit
+ Jatketaan %1$s...
+
diff --git a/app/src/main/res-car/values-b+fil/strings_car.xml b/app/src/main/res-car/values-b+fil/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+fil/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+fr/strings_car.xml b/app/src/main/res-car/values-b+fr/strings_car.xml
new file mode 100644
index 00000000000..86f178c5683
--- /dev/null
+++ b/app/src/main/res-car/values-b+fr/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Chargement...
+ Erreur
+ Erreur de chargement du contenu
+ Favoris
+ Historique
+ Téléchargements
+ Fournisseur
+ Actuel
+ Menu
+ Contenu d\'accueil
+ Aucun contenu du fournisseur
+ Fournisseur non trouvé
+ Source
+ Sources
+ Intrigue
+ Distribution
+ Erreur de chargement des détails
+ Liste des épisodes
+ Saison
+ Saisons
+ Épisode
+ Aucun épisode trouvé
+ Pas une série TV
+ Ajouté aux favoris
+ Retiré des favoris
+ Aucun favori trouvé
+ Démarrage de la lecture...
+ Lecture
+ Aucun lien trouvé
+ Aucun contenu lisible trouvé
+ Impossible de charger les détails
+ Erreur de chargement des liens
+ Adapter à l\'écran
+ Remplir l\'écran
+ Aucune source trouvée
+ Aucune source disponible
+ Source sélectionnée
+ Rechercher
+ Aucun résultat trouvé
+ Aucun élément \'Continuer à regarder\' trouvé
+ Aucun téléchargement trouvé
+ Fichier non trouvé
+ Aucun épisode valide trouvé
+ Sélectionner le fournisseur
+ Sélectionné
+ Bibliothèque
+ Marque-pages
+ Reprise %1$s...
+
diff --git a/app/src/main/res-car/values-b+gl/strings_car.xml b/app/src/main/res-car/values-b+gl/strings_car.xml
new file mode 100644
index 00000000000..7ae2aa29f06
--- /dev/null
+++ b/app/src/main/res-car/values-b+gl/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Cargando...
+ Erro
+ Erro cargando contido
+ Favoritos
+ Historial
+ Descargas
+ Provedor
+ Actual
+ Menú
+ Contido de inicio
+ Sen contido do provedor
+ Provedor non atopado
+ Fonte
+ Fontes
+ Argumento
+ Reparto
+ Erro cargando detalles
+ Lista de episodios
+ Tempada
+ Tempadas
+ Episodio
+ Non se atoparon episodios
+ Non é unha serie de TV
+ Engadido a favoritos
+ Eliminado de favoritos
+ Non se atoparon favoritos
+ Iniciando reprodución...
+ Reproducindo
+ Ligazón non atopada
+ Contido reproducible non atopado
+ Non se poden cargar os detalles
+ Erro cargando ligazóns
+ Axustar á pantalla
+ Encher pantalla
+ Fonte non atopada
+ Non hai fonte dispoñible
+ Fonte seleccionada
+ Buscar
+ Sen resultados
+ \'Continuar vendo\' non atopado
+ Sen descargas
+ Ficheiro non atopado
+ Sen episodio válido
+ Seleccionar provedor
+ Seleccionado
+ Biblioteca
+ Marcadores
+ Retomando %1$s...
+
diff --git a/app/src/main/res-car/values-b+gu/strings_car.xml b/app/src/main/res-car/values-b+gu/strings_car.xml
new file mode 100644
index 00000000000..458737dab3b
--- /dev/null
+++ b/app/src/main/res-car/values-b+gu/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ લોડ થઈ રહ્યું છે...
+ ભૂલ
+ સામગ્રી લોડ કરવામાં ભૂલ
+ મનપસંદ
+ ઇતિહાસ
+ ડાઉનલોડ્સ
+ પ્રદાતા
+ વર્તમાન
+ મેનુ
+ હોમ સામગ્રી
+ પ્રદાતા તરફથી કોઈ સામગ્રી નથી
+ પ્રદાતા મળ્યા નથી
+ સ્ત્રોત
+ સ્ત્રોતો
+ પ્લોટ
+ કલાકારો
+ વિગતો લોડ કરવામાં ભૂલ
+ એ એપિસોડ સૂચિ
+ સીઝન
+ સીઝન
+ એપિસોડ
+ કોઈ એપિસોડ મળ્યા નથી
+ ટીવી શ્રેણી નથી
+ મનપસંદમાં ઉમેર્યું
+ મનપસંદમાંથી દૂર કર્યું
+ કોઈ મનપસંદ મળ્યા નથી
+ પ્લેબેક શરૂ થઈ રહ્યું છે...
+ રમી રહ્યું છે
+ કોઈ લિંક મળી નથી
+ કોઈ રમી શકાય તેવી સામગ્રી મળી નથી
+ વિગતો લોડ કરવામાં અસમર્થ
+ લિંક્સ લોડ કરવામાં ભૂલ
+ સ્ક્રીન પર ફિટ કરો
+ સ્ક્રીન ભરો
+ કોઈ સ્ત્રોત મળ્યો નથી
+ કોઈ સ્ત્રોત ઉપલબ્ધ નથી
+ સ્ત્રોત પસંદ કર્યો
+ શોધો
+ કોઈ પરિણામ મળ્યા નથી
+ \'જોવાનું ચાલુ રાખો\' મળ્યું નથી
+ કોઈ ડાઉનલોડ્સ મળ્યા નથી
+ ફાઇલ મળી નથી
+ કોઈ માન્ય એપિસોડ મળ્યો નથી
+ પ્રદાતા પસંદ કરો
+ પસંદ કરેલ
+ લાઇબ્રેરી
+ બુકમાર્ક્સ
+ %1$s ફરી શરૂ કરી રહ્યું છે...
+
diff --git a/app/src/main/res-car/values-b+hi/strings_car.xml b/app/src/main/res-car/values-b+hi/strings_car.xml
new file mode 100644
index 00000000000..f3418c0e4e3
--- /dev/null
+++ b/app/src/main/res-car/values-b+hi/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ 로드 중...
+ गलती
+ सामग्री लोड हो रही है
+ पसंदीदा
+ इतिहास
+ डाउनलोड
+ प्रदाता
+ वर्तमान
+ मेन्यू
+ गृह सामग्री
+ प्रदाता से कोई सामग्री नहीं
+ प्रदाता नहीं मिला
+ स्रोत
+ सूत्रों
+ भूखंड
+ ढालना
+ विवरण लोड करने में त्रुटि
+ एपिसोड सूची
+ मौसम
+ मौसम
+ प्रसंग
+ कोई एपिसोड नहीं मिला
+ टीवी श्रृंखला नहीं
+ पसंदीदा में जोड़ा गया
+ पसंदीदा से हटाया गया
+ कोई पसंदीदा नहीं मिला
+ प्लेबैक प्रारंभ हो रहा है...
+ खेल
+ कोई लिंक नहीं मिला
+ कोई खेलने योग्य सामग्री नहीं मिली
+ विवरण लोड करने में असमर्थ
+ लिंक लोड करने में त्रुटि
+ स्क्रीन पर फिट करें
+ स्क्रीन भरें
+ कोई स्रोत नहीं मिला
+ कोई स्रोत उपलब्ध नहीं है
+ स्रोत चयनित
+ खोज
+ कोई परिणाम नहीं मिला
+ \'देखना जारी रखें\' नहीं मिला
+ कोई डाउनलोड नहीं मिला
+ फ़ाइल नहीं मिली
+ कोई मान्य एपिसोड नहीं मिला
+ प्रदाता का चयन करें
+ चयनित
+ पुस्तकालय
+ बुकमार्क
+ %1$s फिर से शुरू...
+
diff --git a/app/src/main/res-car/values-b+hr/strings_car.xml b/app/src/main/res-car/values-b+hr/strings_car.xml
new file mode 100644
index 00000000000..8bf55c3fab5
--- /dev/null
+++ b/app/src/main/res-car/values-b+hr/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Učitavanje...
+ Greška
+ Greška pri učitavanju sadržaja
+ Favoriti
+ Povijest
+ Preuzimanja
+ Pružatelj
+ Trenutno
+ Izbornik
+ Početni sadržaj
+ Nema sadržaja od pružatelja
+ Pružatelj nije pronađen
+ Izvor
+ Izvori
+ Radnja
+ Glumci
+ Greška pri učitavanju detalja
+ Popis epizoda
+ Sezona
+ Sezone
+ Epizoda
+ Nema pronađenih epizoda
+ Nije TV serija
+ Dodano u favorite
+ Uklonjeno iz favorita
+ Nema favorita
+ Pokretanje reprodukcije...
+ Reprodukcija
+ Poveznica nije pronađena
+ Sadržaj za reprodukciju nije pronađen
+ Nije moguće učitati detalje
+ Greška pri učitavanju poveznica
+ Prilagodi ekranu
+ Ispuni ekran
+ Izvor nije pronađen
+ Izvor nije dostupan
+ Izvor odabran
+ Pretraži
+ Nema rezultata
+ \'Nastavi gledanje\' nije pronađeno
+ Nema preuzimanja
+ Datoteka nije pronađena
+ Nema važeće epizode
+ Odaberi pružatelja
+ Odabrano
+ Knjižnica
+ Oznake
+ Nastavljanje %1$s...
+
diff --git a/app/src/main/res-car/values-b+hu/strings_car.xml b/app/src/main/res-car/values-b+hu/strings_car.xml
new file mode 100644
index 00000000000..3434ca4a290
--- /dev/null
+++ b/app/src/main/res-car/values-b+hu/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Betöltés...
+ Hiba
+ Tartalom betöltési hiba
+ Kedvencek
+ Előzmények
+ Letöltések
+ Szolgáltató
+ Jelenlegi
+ Menü
+ Kezdőlap tartalom
+ Nincs tartalom a szolgáltatótól
+ Szolgáltató nem található
+ Forrás
+ Források
+ Cselekmény
+ Szereplők
+ Részletek betöltési hiba
+ Epizódlista
+ Évad
+ Évadok
+ Epizód
+ Nem található epizód
+ Nem TV sorozat
+ Hozzáadva a kedvencekhez
+ Eltávolítva a kedvencekből
+ Nincs kedvenc
+ Lejátszás indítása...
+ Lejátszás
+ Link nem található
+ Nincs lejátszható tartalom
+ Nem sikerült betölteni a részleteket
+ Link betöltési hiba
+ Képernyőhöz igazítás
+ Kitöltés
+ Forrás nem található
+ Nincs elérhető forrás
+ Forrás kiválasztva
+ Keresés
+ Nincs találat
+ Nincs \'Nézés folytatása\'
+ Nincs letöltés
+ Fájl nem található
+ Nincs érvényes epizód
+ Válassz szolgáltatót
+ Kiválasztva
+ Könyvtár
+ Könyvjelzők
+ %1$s folytatása...
+
diff --git a/app/src/main/res-car/values-b+hy/strings_car.xml b/app/src/main/res-car/values-b+hy/strings_car.xml
new file mode 100644
index 00000000000..414748b3d8b
--- /dev/null
+++ b/app/src/main/res-car/values-b+hy/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Բեռնում...
+ Սխալ
+ Բովանդակության բեռնման սխալ
+ Ընտրյալներ
+ Պատմություն
+ Ներբեռնումներ
+ Մատակարար
+ Ընթացիկ
+ Մենյու
+ Գլխավոր էջի բովանդակություն
+ Մատակարարից բովանդակություն չկա
+ Մատակարարը չի գտնվել
+ Աղբյուր
+ Աղբյուրներ
+ Սյուժե
+ Դերասանական կազմ
+ Մանրամասների բեռնման սխալ
+ Սերիաների ցանկ
+ Եթերաշրջան
+ Եթերաշրջաններ
+ Սերիա
+ Սերիաներ չեն գտնվել
+ Հեռուստասերիալ չէ
+ Ավելացվել է ընտրյալներին
+ Հեռացվել է ընտրյալներից
+ Ընտրյալներ չեն գտնվել
+ Նվագարկման մեկնարկ...
+ Նվագարկվում է
+ Հղում չի գտնվել
+ Նվագարկվող բովանդակություն չի գտնվել
+ Հնարավոր չէ բեռնել մանրամասները
+ Հղումների բեռնման սխալ
+ Հարմարեցնել էկրանին
+ Լրացնել էկրանը
+ Աղբյուր չի գտնվել
+ Հասանելի աղբյուր չկա
+ Աղբյուրն ընտրված է
+ Որոնել
+ Արդյունքներ չեն գտնվել
+ \'Շարունակել դիտել\' չի գտնվել
+ Ներբեռնումներ չեն գտնվել
+ Ֆայլը չի գտնվել
+ Վավեր սերիա չի գտնվել
+ Ընտրեք մատակարար
+ Ընտրված է
+ Գրադարան
+ Էջանիշեր
+ Շարունակվում է %1$s...
+
diff --git a/app/src/main/res-car/values-b+in/strings_car.xml b/app/src/main/res-car/values-b+in/strings_car.xml
new file mode 100644
index 00000000000..1caea08ba75
--- /dev/null
+++ b/app/src/main/res-car/values-b+in/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Memuat...
+ Kesalahan
+ Kesalahan memuat konten
+ Favorit
+ Riwayat
+ Unduhan
+ Penyedia
+ Saat Ini
+ Menu
+ Konten Beranda
+ Tidak ada konten dari penyedia
+ Penyedia tidak ditemukan
+ Sumber
+ Sumber
+ Plot
+ Pemeran
+ Kesalahan memuat detail
+ Daftar Episode
+ Musim
+ Musim
+ Episode
+ Tidak ada episode ditemukan
+ Bukan serial TV
+ Ditambahkan ke favorit
+ Dihapus dari favorit
+ Tidak ada favorit ditemukan
+ Memulai pemutaran...
+ Memutar
+ Tautan tidak ditemukan
+ Tidak ada konten yang dapat diputar
+ Tidak dapat memuat detail
+ Kesalahan memuat tautan
+ Pas ke Layar
+ Isi Layar
+ Sumber tidak ditemukan
+ Tidak ada sumber tersedia
+ Sumber dipilih
+ Cari
+ Tidak ada hasil ditemukan
+ \'Lanjutkan Menonton\' tidak ditemukan
+ Tidak ada unduhan ditemukan
+ Berkas tidak ditemukan
+ Tidak ada episode valid
+ Pilih Penyedia
+ Dipilih
+ Pustaka
+ Penanda
+ Melanjutkan %1$s...
+
diff --git a/app/src/main/res-car/values-b+is/strings_car.xml b/app/src/main/res-car/values-b+is/strings_car.xml
new file mode 100644
index 00000000000..4bf48c74395
--- /dev/null
+++ b/app/src/main/res-car/values-b+is/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Hleður...
+ Villa
+ Villa við að hlaða efni
+ Eftirlæti
+ Saga
+ Niðurhal
+ Veita
+ Núverandi
+ Valmynd
+ Heimaefni
+ Ekkert efni frá veitu
+ Veita fannst ekki
+ Heimild
+ Heimildir
+ Söguþráður
+ Leikarar
+ Villa við að hlaða upplýsingum
+ Þáttalisti
+ Sería
+ Seríur
+ Þáttur
+ Engir þættir fundust
+ Ekki sjónvarpsþáttaröð
+ Bætt við eftirlæti
+ Fjarlægt úr eftirlæti
+ Engin eftirlæti fundust
+ Hefur spilun...
+ Spilar
+ Enginn tengill fannst
+ Ekkert spilanlegt efni fannst
+ Gat ekki hlaðið upplýsingum
+ Villa við að hlaða tenglum
+ Passa á skjá
+ Fylla skjá
+ Engin heimild fannst
+ Engin heimild tiltæk
+ Heimild valin
+ Leita
+ Engar niðurstöður fundust
+ \'Halda áfram að horfa\' fannst ekki
+ Ekkert niðurhal fannst
+ Skrá fannst ekki
+ Enginn gildur þáttur fannst
+ Veldu veitu
+ Valið
+ Bókasafn
+ Bókamerki
+ Heldur áfram %1$s...
+
diff --git a/app/src/main/res-car/values-b+iw/strings_car.xml b/app/src/main/res-car/values-b+iw/strings_car.xml
new file mode 100644
index 00000000000..100c986137b
--- /dev/null
+++ b/app/src/main/res-car/values-b+iw/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ טוען...
+ שגיאה
+ שגיאה בטעינת תוכן
+ מועדפים
+ היסטוריה
+ הורדות
+ ספק
+ נוכחי
+ תפריט
+ תוכן דף הבית
+ אין תוכן מהספק
+ ספק לא נמצא
+ מקור
+ מקורות
+ עלילה
+ שחקנים
+ שגיאה בטעינת פרטים
+ רשימת פרקים
+ עונה
+ עונות
+ פרק
+ לא נמצאו פרקים
+ לא סדרת טלוויזיה
+ נוסף למועדפים
+ הוסר מהמועדפים
+ לא נמצאו מועדפים
+ מתחיל ניגון...
+ מנגן
+ לא נמצא קישור
+ לא נמצא תוכן לניגון
+ לא ניתן לטעון פרטים
+ שגיאה בטעינת קישורים
+ התאם למסך
+ מלא מסך
+ מקור לא נמצא
+ אין מקור זמין
+ מקור נבחר
+ חיפוש
+ לא נמצאו תוצאות
+ \'המשך צפייה\' לא נמצא
+ לא נמצאו הורדות
+ קובץ לא נמצא
+ לא נמצא פרק תקין
+ בחר ספק
+ נבחר
+ ספרייה
+ סימניות
+ ממשיך %1$s...
+
diff --git a/app/src/main/res-car/values-b+ja/strings_car.xml b/app/src/main/res-car/values-b+ja/strings_car.xml
new file mode 100644
index 00000000000..940e87c68a5
--- /dev/null
+++ b/app/src/main/res-car/values-b+ja/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ 読み込み中...
+ エラー
+ コンテンツの読み込みエラー
+ お気に入り
+ 履歴
+ ダウンロード
+ プロバイダー
+ 現在
+ メニュー
+ ホームコンテンツ
+ プロバイダーからのコンテンツなし
+ プロバイダーが見つかりません
+ ソース
+ ソース
+ あらすじ
+ キャスト
+ 詳細の読み込みエラー
+ エピソードリスト
+ シーズン
+ シーズン
+ エピソード
+ エピソードが見つかりません
+ TV番組ではありません
+ お気に入りに追加しました
+ お気に入りから削除しました
+ お気に入りが見つかりません
+ 再生を開始しています...
+ 再生中
+ リンクが見つかりません
+ 再生可能なコンテンツが見つかりません
+ 詳細を読み込めません
+ リンクの読み込みエラー
+ 画面に合わせる
+ 画面を埋める
+ ソースが見つかりません
+ 利用可能なソースがありません
+ ソースを選択しました
+ 検索
+ 結果が見つかりません
+ 続きを見るコンテンツがありません
+ ダウンロードが見つかりません
+ ファイルが見つかりません
+ 有効なエピソードが見つかりません
+ プロバイダーを選択
+ 選択済み
+ ライブラリ
+ ブックマーク
+ %1$s を再開しています...
+
diff --git a/app/src/main/res-car/values-b+ka/strings_car.xml b/app/src/main/res-car/values-b+ka/strings_car.xml
new file mode 100644
index 00000000000..d1b995dc81e
--- /dev/null
+++ b/app/src/main/res-car/values-b+ka/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ ჩატვირთვა...
+ შეცდომა
+ შინაარსის ჩატვირთვის შეცდომა
+ რჩეულები
+ ისტორია
+ ჩამოტვირთვები
+ მომწოდებელი
+ მიმდინარე
+ მენიუ
+ მთავარი შინაარსი
+ შინაარსი მომწოდებლისგან არ არის
+ მომწოდებელი ვერ მოიძებნა
+ წყარო
+ წყაროები
+ სიუჟეტი
+ მსახიობები
+ დეტალების ჩატვირთვის შეცდომა
+ ეპიზოდების სია
+ სეზონი
+ სეზონები
+ ეპიზოდი
+ ეპიზოდები ვერ მოიძებნა
+ არ არის სატელევიზიო სერიალი
+ დაემატა რჩეულებში
+ ამოღებულია რჩეულებიდან
+ რჩეულები ვერ მოიძებნა
+ დაკვრის დაწყება...
+ დაკვრა
+ ბმული ვერ მოიძებნა
+ დასაკრავი შინაარსი ვერ მოიძებნა
+ დეტალების ჩატვირთვა ვერ მოხერხდა
+ ბმულების ჩატვირთვის შეცდომა
+ ეკრანზე მორგება
+ ეკრანის შევსება
+ წყარო ვერ მოიძებნა
+ წყარო არ არის ხელმისაწვდომი
+ წყარო არჩეულია
+ ძიება
+ შედეგები ვერ მოიძებნა
+ \'ყურების გაგრძელება\' ვერ მოიძებნა
+ ჩამოტვირთვები ვერ მოიძებნა
+ ფაილი ვერ მოიძებნა
+ ვალიდური ეპიზოდი ვერ მოიძებნა
+ აირჩიეთ მომწოდებელი
+ არჩეულია
+ ბიბლიოთეკა
+ სანიშნეები
+ გრძელდება %1$s...
+
diff --git a/app/src/main/res-car/values-b+kk/strings_car.xml b/app/src/main/res-car/values-b+kk/strings_car.xml
new file mode 100644
index 00000000000..e1cffdd409d
--- /dev/null
+++ b/app/src/main/res-car/values-b+kk/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Жүктелуде...
+ Қате
+ Мазмұнды жүктеу қатесі
+ Таңдаулылар
+ Тарих
+ Жүктеулер
+ Провайдер
+ Ағымдағы
+ Мәзір
+ Басты бет мазмұны
+ Провайдерден мазмұн жоқ
+ Провайдер табылмады
+ Дереккөз
+ Дереккөздер
+ Сюжет
+ Актерлер
+ Мәліметтерді жүктеу қатесі
+ Эпизодтар тізімі
+ Маусым
+ Маусымдар
+ Эпизод
+ Эпизодтар табылмады
+ ТВ сериалы емес
+ Таңдаулыларға қосылды
+ Таңдаулылардан жойылды
+ Таңдаулылар табылмады
+ Ойнату басталуда...
+ Ойнатылуда
+ Сілтеме табылмады
+ Ойнатылатын мазмұн табылмады
+ Мәліметтерді жүктеу мүмкін емес
+ Сілтемелерді жүктеу қатесі
+ Экранға сыйғызу
+ Экранды толтыру
+ Дереккөз табылмады
+ Қолжетімді дереккөз жоқ
+ Дереккөз таңдалды
+ Іздеу
+ Нәтижелер табылмады
+ \'Көруді жалғастыру\' табылмады
+ Жүктеулер табылмады
+ Файл табылмады
+ Жарамды эпизод табылмады
+ Провайдерді таңдаңыз
+ Таңдалды
+ Кітапхана
+ Бетбелгілер
+ Жалғастырылуда %1$s...
+
diff --git a/app/src/main/res-car/values-b+km/strings_car.xml b/app/src/main/res-car/values-b+km/strings_car.xml
new file mode 100644
index 00000000000..0a6743d3ba1
--- /dev/null
+++ b/app/src/main/res-car/values-b+km/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ កំពុងផ្ទុក...
+ កំហុស
+ កំហុសក្នុងការផ្ទុកមាតិកា
+ ដែលចូលចិត្ត
+ ប្រវត្តិ
+ ការទាញយក
+ អ្នកផ្តល់សេវា
+ បច្ចុប្បន្ន
+ ម៉ឺនុយ
+ មាតិកាដើម
+ គ្មានមាតិកាពីអ្នកផ្តល់សេវា
+ រកមិនឃើញអ្នកផ្តល់សេវា
+ ប្រភព
+ ប្រភព
+ សាច់រឿង
+ តួសម្តែង
+ កំហុសក្នុងការផ្ទុកព័ត៌មានលម្អិត
+ បញ្ជីភាគ
+ រដូវកាល
+ រដូវកាល
+ ភាគ
+ រកមិនឃើញភាគ
+ មិនមែនជាស៊េរីទូរទស្សន៍
+ បានបន្ថែមទៅការចូលចិត្ត
+ បានលុបចេញពីការចូលចិត្ត
+ រកមិនឃើញការចូលចិត្ត
+ កំពុងចាប់ផ្តើមការចាក់សារថ្មី...
+ កំពុងចាក់
+ រកមិនឃើញតំណ
+ រកមិនឃើញមាតិកាដែលអាចចាក់បាន
+ មិនអាចផ្ទុកព័ត៌មានលម្អិត
+ កំហុសក្នុងការផ្ទុកតំណ
+ សមនឹងអេក្រង់
+ ពេញអេក្រង់
+ រកមិនឃើញប្រភព
+ គ្មានប្រភពដែលអាចប្រើបាន
+ បានជ្រើសរើសប្រភព
+ ស្វែងរក
+ រកមិនឃើញលទ្ធផល
+ រកមិនឃើញ \'បន្តមើល\'
+ រកមិនឃើញការទាញយក
+ រកមិនឃើញឯកសារ
+ រកមិនឃើញភាគដែលមានសុពលភាព
+ ជ្រើសរើសអ្នកផ្តល់សេវា
+ បានជ្រើសរើស
+ បណ្ណាល័យ
+ ចំណាំ
+ កំពុងបន្ត %1$s...
+
diff --git a/app/src/main/res-car/values-b+kn/strings_car.xml b/app/src/main/res-car/values-b+kn/strings_car.xml
new file mode 100644
index 00000000000..7a20b0d2a20
--- /dev/null
+++ b/app/src/main/res-car/values-b+kn/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ ಲೋಡ್ ಆಗುತ್ತಿದೆ...
+ ದೋಷ
+ ವಿಷಯವನ್ನು ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ದೋಷ
+ ಮೆಚ್ಚಿನವುಗಳು
+ ಇತಿಹಾಸ
+ ಡೌನ್ಲೋಡ್ಗಳು
+ ಪೂರೈಕೆದಾರ
+ ಪ್ರಸ್ತುತ
+ ಮೆನು
+ ಮುಖಪುಟ ವಿಷಯ
+ ಪೂರೈಕೆದಾರರಿಂದ ಯಾವುದೇ ವಿಷಯವಿಲ್ಲ
+ ಪೂರೈಕೆದಾರ ಕಂಡುಬಂದಿಲ್ಲ
+ ಮೂಲ
+ ಮೂಲಗಳು
+ ಕಥಾವಸ್ತು
+ ಪಾತ್ರವರ್ಗ
+ ವಿವರಗಳನ್ನು ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ದೋಷ
+ ಸಂಚಿಕೆ ಪಟ್ಟಿ
+ ಋತು
+ ಋತುಗಳು
+ ಸಂಚಿಕೆ
+ ಯಾವುದೇ ಸಂಚಿಕೆಗಳು ಕಂಡುಬಂದಿಲ್ಲ
+ ಟಿವಿ ಸರಣಿಯಲ್ಲ
+ ಮೆಚ್ಚಿನವುಗಳಿಗೆ ಸೇರಿಸಲಾಗಿದೆ
+ ಮೆಚ್ಚಿನವುಗಳಿಂದ ತೆಗೆದುಹಾಕಲಾಗಿದೆ
+ ಯಾವುದೇ ಮೆಚ್ಚಿನವುಗಳು ಕಂಡುಬಂದಿಲ್ಲ
+ ಪ್ಲೇಬ್ಯಾಕ್ ಪ್ರಾರಂಭವಾಗುತ್ತಿದೆ...
+ ಪ್ಲೇ ಆಗುತ್ತಿದೆ
+ ಯಾವುದೇ ಲಿಂಕ್ ಕಂಡುಬಂದಿಲ್ಲ
+ ಯಾವುದೇ ಪ್ಲೇ ಮಾಡಬಹುದಾದ ವಿಷಯ ಕಂಡುಬಂದಿಲ್ಲ
+ ವಿವರಗಳನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ
+ ಲಿಂಕ್ಗಳನ್ನು ಲೋಡ್ ಮಾಡುವಲ್ಲಿ ದೋಷ
+ ಪರದೆಗೆ ಹೊಂದಿಸಿ
+ ಪರದೆ ತುಂಬಿಸಿ
+ ಯಾವುದೇ ಮೂಲ ಕಂಡುಬಂದಿಲ್ಲ
+ ಯಾವುದೇ ಮೂಲ ಲಭ್ಯವಿಲ್ಲ
+ ಮೂಲ ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ
+ ಹುಡುಕಿ
+ ಯಾವುದೇ ಫಲಿತಾಂಶಗಳು ಕಂಡುಬಂದಿಲ್ಲ
+ \'ವೀಕ್ಷಣೆ ಮುಂದುವರಿಸಿ\' ಕಂಡುಬಂದಿಲ್ಲ
+ ಯಾವುದೇ ಡೌನ್ಲೋಡ್ಗಳು ಕಂಡುಬಂದಿಲ್ಲ
+ ಫೈಲ್ ಕಂಡುಬಂದಿಲ್ಲ
+ ಯಾವುದೇ ಮಾನ್ಯ ಸಂಚಿಕೆ ಕಂಡುಬಂದಿಲ್ಲ
+ ಪೂರೈಕೆದಾರರನ್ನು ಆಯ್ಕೆಮಾಡಿ
+ ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ
+ ಗ್ರಂಥಾಲಯ
+ ಬುಕ್ಮಾರ್ಕ್ಗಳು
+ %1$s ಪುನರಾರಂಭವಾಗುತ್ತಿದೆ...
+
diff --git a/app/src/main/res-car/values-b+ko/strings_car.xml b/app/src/main/res-car/values-b+ko/strings_car.xml
new file mode 100644
index 00000000000..0c6f7bf81fd
--- /dev/null
+++ b/app/src/main/res-car/values-b+ko/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ 로드 중...
+ 오류
+ 콘텐츠 로드 오류
+ 즐겨찾기
+ 기록
+ 다운로드
+ 제공자
+ 현재
+ 메뉴
+ 홈 콘텐츠
+ 제공자의 콘텐츠 없음
+ 제공자를 찾을 수 없음
+ 소스
+ 소스
+ 줄거리
+ 출연진
+ 세부 정보 로드 오류
+ 에피소드 목록
+ 시즌
+ 시즌
+ 에피소드
+ 에피소드 없음
+ TV 시리즈 아님
+ 즐겨찾기에 추가됨
+ 즐겨찾기에서 제거됨
+ 즐겨찾기 없음
+ 재생 시작 중...
+ 재생 중
+ 링크 없음
+ 재생 가능한 콘텐츠 없음
+ 세부 정보를 로드할 수 없음
+ 링크 로드 오류
+ 화면에 맞춤
+ 화면 채우기
+ 소스 없음
+ 사용 가능한 소스 없음
+ 소스 선택됨
+ 검색
+ 결과 없음
+ 이어보기 없음
+ 다운로드 없음
+ 파일 없음
+ 유효한 에피소드 없음
+ 제공자 선택
+ 선택됨
+ 라이브러리
+ 북마크
+ %1$s 이어보는 중...
+
diff --git a/app/src/main/res-car/values-b+ky/strings_car.xml b/app/src/main/res-car/values-b+ky/strings_car.xml
new file mode 100644
index 00000000000..4f5a4790a09
--- /dev/null
+++ b/app/src/main/res-car/values-b+ky/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Жүктөө...
+ Ката
+ Мазмунду жүктөө катасы
+ Сүйүктүүлөр
+ Тарых
+ Жүктөөлөр
+ Провайдер
+ Учурдагы
+ Меню
+ Башкы мазмун
+ Провайдерден мазмун жок
+ Провайдер табылган жок
+ Булак
+ Булактар
+ Сюжет
+ Актерлор
+ Маалыматтарды жүктөө катасы
+ Эпизоддор тизмеси
+ Сезон
+ Сезондор
+ Эпизод
+ Эпизоддор табылган жок
+ ТВ сериалы эмес
+ Сүйүктүүлөргө кошулду
+ Сүйүктүүлөрдөн алынды
+ Сүйүктүүлөр табылган жок
+ Ойнотуу башталууда...
+ Ойнотулууда
+ Шилтеме табылган жок
+ Ойнотула турган мазмун табылган жок
+ Маалыматтарды жүктөө мүмкүн эмес
+ Шилтемелерди жүктөө катасы
+ Экранга тууралоо
+ Экранды толтуруу
+ Булак табылган жок
+ Жеткиликтүү булак жок
+ Булак тандалды
+ Издөө
+ Жыйынтык табылган жок
+ \'Көрүүнү улантуу\' табылган жок
+ Жүктөөлөр табылган жок
+ Файл табылган жок
+ Жарактуу эпизод табылган жок
+ Провайдерди тандоо
+ Тандалды
+ Китепкана
+ Кыстармалар
+ Улантылууда %1$s...
+
diff --git a/app/src/main/res-car/values-b+lo/strings_car.xml b/app/src/main/res-car/values-b+lo/strings_car.xml
new file mode 100644
index 00000000000..6241b14e84c
--- /dev/null
+++ b/app/src/main/res-car/values-b+lo/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ ກຳລັງໂຫຼດ...
+ ຂໍ້ຜິດພາດ
+ ເກີດຂໍ້ຜິດພາດໃນການໂຫຼດເນື້ອຫາ
+ ລາຍການທີ່ມັກ
+ ປະຫວັດການເຂົ້າຊົມ
+ ການດາວໂຫຼດ
+ ຜູ້ໃຫ້ບໍລິການ
+ ປັດຈຸບັນ
+ ເມນູ
+ ເນື້ອຫາໜ້າຫຼັກ
+ ບໍ່ມີເນື້ອຫາຈາກຜູ້ໃຫ້ບໍລິການ
+ ບໍ່ພົບຜູ້ໃຫ້ບໍລິການ
+ ແຫຼ່ງທີ່ມາ
+ ແຫຼ່ງທີ່ມາ
+ ເນື້ອເລື່ອງ
+ ນັກສະແດງ
+ ເກີດຂໍ້ຜິດພາດໃນການໂຫຼດລາຍລະອຽດ
+ ລາຍການຕອນ
+ ຊີຊັນ
+ ຊີຊັນ
+ ຕອນ
+ ບໍ່ພົບຕອນ
+ ບໍ່ແມ່ນຊີຣີໂທລະທັດ
+ ເພີ່ມເຂົ້າໃນລາຍການທີ່ມັກແລ້ວ
+ ລົບອອກຈາກລາຍການທີ່ມັກແລ້ວ
+ ບໍ່ພົບລາຍການທີ່ມັກ
+ ກຳລັງເລີ່ມການຫຼິ້ນ...
+ ກຳລັງຫຼິ້ນ
+ ບໍ່ພົບລິ້ງ
+ ບໍ່ພົບເນື້ອຫາທີ່ສາມາດຫຼິ້ນໄດ້
+ ບໍ່ສາມາດໂຫຼດລາຍລະອຽດໄດ້
+ ເກີດຂໍ້ຜິດພາດໃນການໂຫຼດລິ້ງ
+ ປັບໃຫ້ພໍດີກັບໜ້າຈໍ
+ ຂະຫຍາຍເຕັ້ນໜ້າຈໍ
+ ບໍ່ພົບແຫຼ່ງທີ່ມາ
+ ບໍ່ມີແຫຼ່ງທີ່ມາທີ່ໃຊ້ໄດ້
+ ເລືອກແຫຼ່ງທີ່ມາແລ້ວ
+ ຄົ້ນຫາ
+ ບໍ່ພົບຜົນການຄົ້ນຫາ
+ ບໍ່ພົບ \'ເບິ່ງຕໍ່\'
+ ບໍ່ພົບການດາວໂຫຼດ
+ ບໍ່ພົບໄຟລ໌
+ ບໍ່ພົບຕອນທີ່ຖືກຕ້ອງ
+ ເລືອກຜູ້ໃຫ້ບໍລິການ
+ ທີ່ເລືອກ
+ ຫ້ອງສະໝຸດ
+ ບຸກມາກ
+ ກຳລັງເບິ່ງຕໍ່ %1$s...
+
diff --git a/app/src/main/res-car/values-b+lt/strings_car.xml b/app/src/main/res-car/values-b+lt/strings_car.xml
new file mode 100644
index 00000000000..2812345f660
--- /dev/null
+++ b/app/src/main/res-car/values-b+lt/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Įkeliama...
+ Klaida
+ Klaida įkeliant turinį
+ Mėgstamiausi
+ Istorija
+ Atsisiuntimai
+ Tiekėjas
+ Dabartinis
+ Meniu
+ Pradžios turinys
+ Nėra turinio iš tiekėjo
+ Tiekėjas nerastas
+ Šaltinis
+ Šaltiniai
+ Siužetas
+ Aktoriai
+ Klaida įkeliant informaciją
+ Epizodų sąrašas
+ Sezonas
+ Sezonai
+ Epizodas
+ Epizodų nerasta
+ Ne TV serialas
+ Pridėta prie mėgstamiausių
+ Pašalinta iš mėgstamiausių
+ Mėgstamiausių nerasta
+ Pradedamas atkūrimas...
+ Atkuriama
+ Nuoroda nerasta
+ Atkuriamo turinio nerasta
+ Nepavyko įkelti informacijos
+ Klaida įkeliant nuorodas
+ Pritaikyti ekranui
+ Užpildyti ekraną
+ Šaltinis nerastas
+ Nėra galimų šaltinių
+ Šaltinis pasirinktas
+ Paieška
+ Rezultatų nerasta
+ \'Tęsti žiūrėjimą\' nerasta
+ Atsisiuntimų nerasta
+ Failas nerastas
+ Nerastas tinkamas epizodas
+ Pasirinkite tiekėją
+ Pasirinkta
+ Biblioteka
+ Žymos
+ Tęsiama %1$s...
+
diff --git a/app/src/main/res-car/values-b+lv/strings_car.xml b/app/src/main/res-car/values-b+lv/strings_car.xml
new file mode 100644
index 00000000000..386bf2b92fa
--- /dev/null
+++ b/app/src/main/res-car/values-b+lv/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Ielādē...
+ Kļūda
+ Satura ielādes kļūda
+ Izlase
+ Vēsture
+ Lejupielādes
+ Piegādātājs
+ Pašreizējais
+ Izvēlne
+ Sākuma saturs
+ Nav satura no piegādātāja
+ Piegādātājs nav atrasts
+ Avots
+ Avoti
+ Sižets
+ Lomas
+ Kļūda ielādējot informāciju
+ Epizožu saraksts
+ Sezona
+ Sezonas
+ Epizode
+ Epizodes nav atrastas
+ Nav TV seriāls
+ Pievienots izlasei
+ Noņemts no izlases
+ Izlase nav atrasta
+ Sāk atskaņošanu...
+ Atskaņo
+ Saite nav atrasta
+ Nav atrasts atskaņojams saturs
+ Nevar ielādēt informāciju
+ Kļūda ielādējot saites
+ Pielāgot ekrānam
+ Aizpildīt ekrānu
+ Avots nav atrasts
+ Nav pieejamu avotu
+ Avots izvēlēts
+ Meklēt
+ Rezultāti nav atrasti
+ \'Turpināt skatīties\' nav atrasts
+ Lejupielādes nav atrastas
+ Fails nav atrasts
+ Nav atrasta derīga epizode
+ Izvēlēties piegādātāju
+ Izvēlēts
+ Bibliotēka
+ Grāmatzīmes
+ Atsāk %1$s...
+
diff --git a/app/src/main/res-car/values-b+mk/strings_car.xml b/app/src/main/res-car/values-b+mk/strings_car.xml
new file mode 100644
index 00000000000..bdc47d33110
--- /dev/null
+++ b/app/src/main/res-car/values-b+mk/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Вчитување...
+ Грешка
+ Грешка при вчитување содржина
+ Омилени
+ Историја
+ Преземања
+ Добавувач
+ Тековно
+ Мени
+ Почетна содржина
+ Нема содржина од добавувачот
+ Добавувачот не е пронајден
+ Извор
+ Извори
+ Дејство
+ Улоги
+ Грешка при вчитување детали
+ Листа на епизоди
+ Сезона
+ Сезони
+ Епизода
+ Не се пронајдени епизоди
+ Не е ТВ серија
+ Додадено во омилени
+ Отстрането од омилени
+ Не се пронајдени омилени
+ Започнување репродукција...
+ Репродукција
+ Врската не е пронајдена
+ Не е пронајдена содржина за репродукција
+ Не може да се вчитаат детали
+ Грешка при вчитување врски
+ Вклопи во екран
+ Пополни екран
+ Изворот не е пронајден
+ Нема достапен извор
+ Изворот е избран
+ Пребарување
+ Не се пронајдени резултати
+ \'Продолжи со гледање\' не е пронајдено
+ Не се пронајдени преземања
+ Датотеката не е пронајдена
+ Не е пронајдена валидна епизода
+ Избери добавувач
+ Избрано
+ Библиотека
+ Обележувачи
+ Продолжување %1$s...
+
diff --git a/app/src/main/res-car/values-b+ml/strings_car.xml b/app/src/main/res-car/values-b+ml/strings_car.xml
new file mode 100644
index 00000000000..d1af8f61ff2
--- /dev/null
+++ b/app/src/main/res-car/values-b+ml/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ ലോഡ് ചെയ്യുന്നു...
+ പിശക്
+ ഉള്ളടക്കം ലോഡ് ചെയ്യുന്നതിൽ പിശക്
+ പ്രിയപ്പെട്ടവ
+ ചരിത്രം
+ ഡൗൺലോഡുകൾ
+ ദാതാവ്
+ നിലവിലുള്ള
+ മെനു
+ ഹോം ഉള്ളടക്കം
+ ദാതാവിൽ നിന്ന് ഉള്ളടക്കമില്ല
+ ദാതാവിനെ കണ്ടെത്തിയില്ല
+ ഉറവിടം
+ ഉറവിടങ്ങൾ
+ ഇതിവൃത്തം
+ അഭിനേതാക്കൾ
+ വിശദാംശങ്ങൾ ലോഡ് ചെയ്യുന്നതിൽ പിശക്
+ എപ്പിസോഡ് ലിസ്റ്റ്
+ സീസൺ
+ സീസണുകൾ
+ എപ്പിസോഡ്
+ എപ്പിസോഡുകളൊന്നും കണ്ടെത്തിയില്ല
+ ടിവി സീരീസ് അല്ല
+ പ്രിയപ്പെട്ടവയിലേക്ക് ചേർത്തു
+ പ്രിയപ്പെട്ടവയിൽ നിന്ന് നീക്കം ചെയ്തു
+ പ്രിയപ്പെട്ടവയൊന്നും കണ്ടെത്തിയില്ല
+ പ്ലേബാക്ക് ആരംഭിക്കുന്നു...
+ പ്ലേ ചെയ്യുന്നു
+ ലിങ്ക് കണ്ടെത്തിയില്ല
+ പ്ലേ ചെയ്യാവുന്ന ഉള്ളടക്കമൊന്നും കണ്ടെത്തിയില്ല
+ വിശദാംശങ്ങൾ ലോഡ് ചെയ്യാനായില്ല
+ ലിങ്കുകൾ ലോഡ് ചെയ്യുന്നതിൽ പിശക്
+ സ്ക്രീനിലേക്ക് യോജിപ്പിക്കുക
+ സ്ക്രീൻ നിറയ്ക്കുക
+ ഉറവിടം കണ്ടെത്തിയില്ല
+ ഉറവിടമൊന്നും ലഭ്യമല്ല
+ ഉറവിടം തിരഞ്ഞെടുത്തു
+ തിരയുക
+ ഫലങ്ങളൊന്നും കണ്ടെത്തിയില്ല
+ \'കാണുന്നത് തുടരുക\' കണ്ടെത്തിയില്ല
+ ഡൗൺലോഡുകളൊന്നും കണ്ടെത്തിയില്ല
+ ഫയൽ കണ്ടെത്തിയില്ല
+ സാധുവായ എപ്പിസോഡ് കണ്ടെത്തിയില്ല
+ ദാതാവിനെ തിരഞ്ഞെടുക്കുക
+ തിരഞ്ഞെടുത്തു
+ ലൈബ്രറി
+ ബുക്ക്മാർക്കുകൾ
+ %1$s പുനരാരംഭിക്കുന്നു...
+
diff --git a/app/src/main/res-car/values-b+mn/strings_car.xml b/app/src/main/res-car/values-b+mn/strings_car.xml
new file mode 100644
index 00000000000..69bb275def9
--- /dev/null
+++ b/app/src/main/res-car/values-b+mn/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Ачаалж байна...
+ Алдаа
+ Контент ачаалахад алдаа гарлаа
+ Таалагдсан
+ Түүх
+ Татаж авсан
+ Нийлүүлэгч
+ Одоогийн
+ Цэс
+ Нүүр хуудасны контент
+ Нийлүүлэгчээс контент алга
+ Нийлүүлэгч олдсонгүй
+ Эх сурвалж
+ Эх сурвалжууд
+ Үйл явдал
+ Дүрүүд
+ Дэлгэрэнгүйг ачаалахад алдаа гарлаа
+ Ангийн жагсаалт
+ Бүлэг
+ Бүлгүүд
+ Анги
+ Анги олдсонгүй
+ ТВ цуврал биш
+ Таалагдсанд нэмлээ
+ Таалагдсанаас хаслаа
+ Таалагдсан контент олдсонгүй
+ Тоглуулж эхэлж байна...
+ Тоглуулж байна
+ Холбоос олдсонгүй
+ Тоглуулах контент олдсонгүй
+ Дэлгэрэнгүйг ачаалах боломжгүй
+ Холбоос ачаалахад алдаа гарлаа
+ Дэлгэцэнд тааруулах
+ Дэлгэц дүүргэх
+ Эх сурвалж олдсонгүй
+ Боломжит эх сурвалж алга
+ Эх сурвалж сонгогдсон
+ Хайх
+ Үр дүн олдсонгүй
+ \'Үргэлжлүүлж үзэх\' олдсонгүй
+ Таталт олдсонгүй
+ Файл олдсонгүй
+ Хүчинтэй анги олдсонгүй
+ Нийлүүлэгч сонгох
+ Сонгогдсон
+ Сан
+ Хавчуурга
+ %1$s үргэлжлүүлж байна...
+
diff --git a/app/src/main/res-car/values-b+mr/strings_car.xml b/app/src/main/res-car/values-b+mr/strings_car.xml
new file mode 100644
index 00000000000..656591ef267
--- /dev/null
+++ b/app/src/main/res-car/values-b+mr/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ लोड होत आहे...
+ त्रुटी
+ सामग्री लोड करताना त्रुटी
+ आवडते
+ इतिहास
+ डाउनलोड
+ पुरवठादार
+ वर्तमान
+ मेनू
+ होम सामग्री
+ पुरवठादाराकडून कोणतीही सामग्री नाही
+ पुरवठादार सापडला नाही
+ स्त्रोत
+ स्त्रोत
+ कथानक
+ कलाकार
+ तपशील लोड करताना त्रुटी
+ एपिसोड यादी
+ सीझन
+ सीझन
+ एपिसोड
+ कोणतेही एपिसोड सापडले नाहीत
+ टीव्ही मालिका नाही
+ आवडत्यांमध्ये जोडले
+ आवडत्यांमधून काढले
+ कोणतेही आवडते सापडले नाहीत
+ प्लेबॅक सुरू होत आहे...
+ प्ले होत आहे
+ कोणतीही लिंक सापडली नाही
+ कोणतीही प्ले करण्यायोग्य सामग्री सापडली नाही
+ तपशील लोड करण्यास अक्षम
+ लिंक लोड करताना त्रुटी
+ स्क्रीनवर बसवा
+ स्क्रीन भरा
+ कोणताही स्त्रोत सापडला नाही
+ कोणताही स्त्रोत उपलब्ध नाही
+ स्त्रोत निवडला
+ शोधा
+ कोणतेही परिणाम सापडले नाहीत
+ \'पाहणे सुरू ठेवा\' सापडले नाही
+ कोणतेही डाउनलोड सापडले नाहीत
+ फाइल सापडली नाही
+ कोणताही वैध एपिसोड सापडला नाही
+ पुरवठादार निवडा
+ निवडलेले
+ ग्रंथालय
+ बुकमार्क
+ %1$s पुन्हा सुरू करत आहे...
+
diff --git a/app/src/main/res-car/values-b+ms/strings_car.xml b/app/src/main/res-car/values-b+ms/strings_car.xml
new file mode 100644
index 00000000000..3735de6abcc
--- /dev/null
+++ b/app/src/main/res-car/values-b+ms/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Memuatkan...
+ Ralat
+ Ralat memuatkan kandungan
+ Kegemaran
+ Sejarah
+ Muat Turun
+ Penyedia
+ Semasa
+ Menu
+ Kandungan Laman Utama
+ Tiada kandungan dari penyedia
+ Penyedia tidak ditemui
+ Sumber
+ Sumber
+ Plot
+ Pelakon
+ Ralat memuatkan butiran
+ Senarai Episod
+ Musim
+ Musim
+ Episod
+ Tiada episod ditemui
+ Bukan siri TV
+ Ditambah ke kegemaran
+ Dibuang dari kegemaran
+ Tiada kegemaran ditemui
+ Memulakan main balik...
+ Memainkan
+ Pautan tidak ditemui
+ Tiada kandungan boleh dimainkan ditemui
+ Tidak dapat memuatkan butiran
+ Ralat memuatkan pautan
+ Muat ke Skrin
+ Penuhi Skrin
+ Tiada sumber ditemui
+ Tiada sumber tersedia
+ Sumber dipilih
+ Cari
+ Tiada hasil ditemui
+ \'Teruskan Menonton\' tidak ditemui
+ Tiada muat turun ditemui
+ Fail tidak ditemui
+ Tiada episod sah ditemui
+ Pilih Penyedia
+ Dipilih
+ Perpustakaan
+ Penanda Buku
+ Menyambung semula %1$s...
+
diff --git a/app/src/main/res-car/values-b+mt/strings_car.xml b/app/src/main/res-car/values-b+mt/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+mt/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+my/strings_car.xml b/app/src/main/res-car/values-b+my/strings_car.xml
new file mode 100644
index 00000000000..67f29ecd327
--- /dev/null
+++ b/app/src/main/res-car/values-b+my/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Loading...
+ အမှား
+ အကြောင်းအရာကို ဆွဲယူရာတွင် အမှားဖြစ်နေသည်
+ အကြိုက်ဆုံးများ
+ မှတ်တမ်း
+ ဒေါင်းလုဒ်များ
+ ပံ့ပိုးသူ
+ လက်ရှိ
+ မီနူး
+ ပင်မစာမျက်နှာ
+ ပံ့ပိုးသူထံမှ အကြောင်းအရာ မရှိပါ
+ ပံ့ပိုးသူကို မတွေ့ပါ
+ အရင်းအမြစ်
+ အရင်းအမြစ်များ
+ ဇာတ်လမ်းအကျဉ်း
+ သရုပ်ဆောင်များ
+ အသေးစိတ်အချက်အလက်များကို ဆွဲယူရာတွင် အမှားဖြစ်နေသည်
+ အပိုင်းများ
+ ရာသီ
+ ရာသီများ
+ အပိုင်း
+ အပိုင်းများ မတွေ့ပါ
+ တီဗီစီးရီး မဟုတ်ပါ
+ အကြိုက်ဆုံးများသို့ ထည့်ပြီးပါပြီ
+ အကြိုက်ဆုံးများမှ ဖယ်ရှားလိုက်ပါပြီ
+ အကြိုက်ဆုံးများ မတွေ့ပါ
+ ဖွင့်နေသည်...
+ ဖွင့်နေသည်
+ လင့်ခ်မတွေ့ပါ
+ ဖွင့်နိုင်သော အကြောင်းအရာ မတွေ့ပါ
+ အသေးစိတ်အချက်အလက်များကို မဆွဲယူနိုင်ပါ
+ လင့်ခ်များကို ဆွဲယူရာတွင် အမှားဖြစ်နေသည်
+ မျက်နှာပြင်နှင့် အံကိုက်
+ မျက်နှာပြင်အပြည့်
+ အရင်းအမြစ် မတွေ့ပါ
+ ရရှိနိုင်သော အရင်းအမြစ် မရှိပါ
+ အရင်းအမြစ်ကို ရွေးချယ်လိုက်သည်
+ ရှာဖွေရန်
+ ရလဒ်မတွေ့ပါ
+ \'ဆက်လက်ကြည့်ရှုရန်\' မတွေ့ပါ
+ ဒေါင်းလုဒ်များ မတွေ့ပါ
+ ဖိုင်မတွေ့ပါ
+ မှန်ကန်သော အပိုင်း မတွေ့ပါ
+ ပံ့ပိုးသူကို ရွေးချယ်ပါ
+ ရွေးချယ်ပြီး
+ စာကြည့်တိုက်
+ မှတ်သားမှုများ
+ %1$s ကို ဆက်လက်ကြည့်ရှုနေသည်...
+
diff --git a/app/src/main/res-car/values-b+ne/strings_car.xml b/app/src/main/res-car/values-b+ne/strings_car.xml
new file mode 100644
index 00000000000..ec6ce51b767
--- /dev/null
+++ b/app/src/main/res-car/values-b+ne/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ लोड हुँदैछ...
+ त्रुटि
+ सामग्री लोड गर्दा त्रुटि
+ मनपर्नेहरू
+ इतिहास
+ डाउनलोडहरू
+ प्रदायक
+ हालको
+ मेनु
+ गृह सामग्री
+ प्रदायकबाट कुनै सामग्री छैन
+ प्रदायक फेला परेन
+ स्रोत
+ स्रोतहरू
+ कथा
+ कलाकारहरू
+ विवरण लोड गर्दा त्रुटि
+ एपिसोड सूची
+ सिजन
+ सिजनहरू
+ एपिसोड
+ कुनै एपिसोड फेला परेन
+ टिभी शृङ्खला होइन
+ मनपर्नेमा थपियो
+ मनपर्नेबाट हटाइयो
+ कुनै मनपर्ने फेला परेन
+ प्लेब्याक सुरु हुँदैछ...
+ बजाउँदै
+ कुनै लिङ्क फेला परेन
+ कुनै बजाउन योग्य सामग्री फेला परेन
+ विवरण लोड गर्न असक्षम
+ लिङ्कहरू लोड गर्दा त्रुटि
+ स्क्रिनमा मिलाउनुहोस्
+ स्क्रिन भर्नुहोस्
+ कुनै स्रोत फेला परेन
+ कुनै स्रोत उपलब्ध छैन
+ स्रोत चयन गरियो
+ खोज्नुहोस्
+ कुनै नतिजा फेला परेन
+ \'हेर्न जारी राख्नुहोस्\' फेला परेन
+ कुनै डाउनलोड फेला परेन
+ फाइल फेला परेन
+ कुनै मान्य एपिसोड फेला परेन
+ प्रदायक चयन गर्नुहोस्
+ चयन गरिएको
+ पुस्तकालय
+ बुकमार्कहरू
+ %1$s सुचारु हुँदैछ...
+
diff --git a/app/src/main/res-car/values-b+nl/strings_car.xml b/app/src/main/res-car/values-b+nl/strings_car.xml
new file mode 100644
index 00000000000..891c01a4b40
--- /dev/null
+++ b/app/src/main/res-car/values-b+nl/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Laden...
+ Fout
+ Fout bij laden inhoud
+ Favorieten
+ Geschiedenis
+ Downloads
+ Aanbieder
+ Huidig
+ Menu
+ De inhoud van het huis
+ Geen inhoud van aanbieder
+ Aanbieder niet gevonden
+ Bron
+ Bronnen
+ Verhaal
+ Cast
+ Fout bij laden details
+ Afleveringenlijst
+ Seizoen
+ Seizoenen
+ Aflevering
+ Geen afleveringen gevonden
+ Geen TV-serie
+ Toegevoegd aan favorieten
+ Verwijderd uit favorieten
+ Geen favorieten gevonden
+ Afspelen starten...
+ Afspelen
+ Geen link gevonden
+ Geen afspeelbare inhoud gevonden
+ Kan details niet laden
+ Fout bij laden links
+ Passend maken
+ Scherm vullen
+ Geen bron gevonden
+ Geen bron beschikbaar
+ Bron geselecteerd
+ Zoeken
+ Geen resultaten gevonden
+ Geen \'Verder kijken\' gevonden
+ Geen downloads gevonden
+ Bestand niet gevonden
+ Geen geldige aflevering gevonden
+ Selecteer aanbieder
+ Geselecteerd
+ Bibliotheek
+ Bladwijzers
+ Hervatten %1$s...
+
diff --git a/app/src/main/res-car/values-b+nn/strings_car.xml b/app/src/main/res-car/values-b+nn/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+nn/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+no/strings_car.xml b/app/src/main/res-car/values-b+no/strings_car.xml
new file mode 100644
index 00000000000..1b884c6e828
--- /dev/null
+++ b/app/src/main/res-car/values-b+no/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Laster inn...
+ Feil
+ Feil ved lasting av innhold
+ Favoritter
+ Historikk
+ Nedlastinger
+ Leverandør
+ Nåværende
+ Meny
+ Hjem-innhold
+ Ingen innhold fra leverandør
+ Leverandør ikke funnet
+ Kilde
+ Kilder
+ Handling
+ Skuespillere
+ Feil ved lasting av detaljer
+ Episodeliste
+ Sesong
+ Sesonger
+ Episode
+ Ingen episoder funnet
+ Ikke en TV-serie
+ Lagt til i favoritter
+ Fjernet fra favoritter
+ Ingen favoritter funnet
+ Starter avspilling...
+ Spiller av
+ Ingen lenke funnet
+ Ingen spillbart innhold funnet
+ Kan ikke laste detaljer
+ Feil ved lasting av lenker
+ Tilpass til skjerm
+ Fyll skjerm
+ Ingen kilde funnet
+ Ingen kilde tilgjengelig
+ Kilde valgt
+ Søk
+ Ingen resultater funnet
+ \'Fortsett å se\' ikke funnet
+ Ingen nedlastinger funnet
+ Fil ikke funnet
+ Ingen gyldig episode funnet
+ Velg leverandør
+ Valgt
+ Bibliotek
+ Bokmerker
+ Gjenopptar %1$s...
+
diff --git a/app/src/main/res-car/values-b+or/strings_car.xml b/app/src/main/res-car/values-b+or/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+or/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+pa/strings_car.xml b/app/src/main/res-car/values-b+pa/strings_car.xml
new file mode 100644
index 00000000000..6b1e7ca0dc0
--- /dev/null
+++ b/app/src/main/res-car/values-b+pa/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ...
+ ਗਲਤੀ
+ ਸਮੱਗਰੀ ਲੋਡ ਕਰਨ ਵਿੱਚ ਗਲਤੀ
+ ਮਨਪਸੰਦ
+ ਇਤਿਹਾਸ
+ ਡਾਊਨਲੋਡ
+ ਪ੍ਰਦਾਤਾ
+ ਮੌਜੂਦਾ
+ ਮੀਨੂ
+ ਘਰੇਲੂ ਸਮੱਗਰੀ
+ ਪ੍ਰਦਾਤਾ ਤੋਂ ਕੋਈ ਸਮੱਗਰੀ ਨਹੀਂ
+ ਪ੍ਰਦਾਤਾ ਨਹੀਂ ਮਿਲਿਆ
+ ਸਰੋਤ
+ ਸਰੋਤ
+ ਕਹਾਣੀ
+ ਕਲਾਕਾਰ
+ ਵੇਰਵੇ ਲੋਡ ਕਰਨ ਵਿੱਚ ਗਲਤੀ
+ ਐਪੀਸੋਡ ਸੂਚੀ
+ ਸੀਜ਼ਨ
+ ਸੀਜ਼ਨ
+ ਐਪੀਸੋਡ
+ ਕੋਈ ਐਪੀਸੋਡ ਨਹੀਂ ਮਿਲਿਆ
+ ਟੀਵੀ ਲੜੀਵਾਰ ਨਹੀਂ
+ ਮਨਪਸੰਦ ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ
+ ਮਨਪਸੰਦ ਤੋਂ ਹਟਾਇਆ ਗਿਆ
+ ਕੋਈ ਮਨਪਸੰਦ ਨਹੀਂ ਮਿਲਿਆ
+ ਪਲੇਬੈਕ ਸ਼ੁਰੂ ਹੋ ਰਿਹਾ ਹੈ...
+ ਖੇਡ ਰਿਹਾ ਹੈ
+ ਕੋਈ ਲਿੰਕ ਨਹੀਂ ਮਿਲਿਆ
+ ਕੋਈ ਖੇਡਣ ਯੋਗ ਸਮੱਗਰੀ ਨਹੀਂ ਮਿਲੀ
+ ਵੇਰਵੇ ਲੋਡ ਕਰਨ ਵਿੱਚ ਅਸਮਰੱਥ
+ ਲਿੰਕ ਲੋਡ ਕਰਨ ਵਿੱਚ ਗਲਤੀ
+ ਸਕ੍ਰੀਨ \'ਤੇ ਫਿੱਟ ਕਰੋ
+ ਸਕ੍ਰੀਨ ਭਰੋ
+ ਕੋਈ ਸਰੋਤ ਨਹੀਂ ਮਿਲਿਆ
+ ਕੋਈ ਸਰੋਤ ਉਪਲਬਧ ਨਹੀਂ
+ ਸਰੋਤ ਚੁਣਿਆ ਗਿਆ
+ ਖੋਜ
+ ਕੋਈ ਨਤੀਜਾ ਨਹੀਂ ਮਿਲਿਆ
+ \'ਦੇਖਣਾ ਜਾਰੀ ਰੱਖੋ\' ਨਹੀਂ ਮਿਲਿਆ
+ ਕੋਈ ਡਾਊਨਲੋਡ ਨਹੀਂ ਮਿਲਿਆ
+ ਫਾਈਲ ਨਹੀਂ ਮਿਲੀ
+ ਕੋਈ ਵੈਧ ਐਪੀਸੋਡ ਨਹੀਂ ਮਿਲਿਆ
+ ਪ੍ਰਦਾਤਾ ਚੁਣੋ
+ ਚੁਣਿਆ ਗਿਆ
+ ਲਾਇਬ੍ਰੇਰੀ
+ ਬੁੱਕਮਾਰਕ
+ %1$s ਮੁੜ ਸ਼ੁਰੂ ਹੋ ਰਿਹਾ ਹੈ...
+
diff --git a/app/src/main/res-car/values-b+pl/strings_car.xml b/app/src/main/res-car/values-b+pl/strings_car.xml
new file mode 100644
index 00000000000..99f3d4095b1
--- /dev/null
+++ b/app/src/main/res-car/values-b+pl/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Ładowanie...
+ Błąd
+ Błąd ładowania treści
+ Ulubione
+ Historia
+ Pobrane
+ Dostawca
+ Obecny
+ Menu
+ Treść główna
+ Brak treści od dostawcy
+ Nie znaleziono dostawcy
+ Źródło
+ Źródła
+ Fabuła
+ Obsada
+ Błąd ładowania szczegółów
+ Lista odcinków
+ Sezon
+ Sezony
+ Odcinek
+ Nie znaleziono odcinków
+ To nie jest serial TV
+ Dodano do ulubionych
+ Usunięto z ulubionych
+ Nie znaleziono ulubionych
+ Rozpoczynanie odtwarzania...
+ Odtwarzanie
+ Nie znaleziono łącza
+ Nie znaleziono treści do odtworzenia
+ Nie można załadować szczegółów
+ Błąd ładowania łączy
+ Dopasuj do ekranu
+ Wypełnij ekran
+ Nie znaleziono źródła
+ Brak dostępnych źródeł
+ Wybrano źródło
+ Szukaj
+ Brak wyników
+ Nie znaleziono „Oglądaj dalej”
+ Brak pobranych plików
+ Plik nie znaleziony
+ Brak poprawnego odcinka
+ Wybierz dostawcę
+ Wybrano
+ Biblioteka
+ Zakładki
+ Wznawianie %1$s...
+
diff --git a/app/src/main/res-car/values-b+pt+BR/strings_car.xml b/app/src/main/res-car/values-b+pt+BR/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+pt+BR/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+pt/strings_car.xml b/app/src/main/res-car/values-b+pt/strings_car.xml
new file mode 100644
index 00000000000..0195a196e51
--- /dev/null
+++ b/app/src/main/res-car/values-b+pt/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Carregando...
+ Erro
+ Erro ao carregar conteúdo
+ Favoritos
+ Histórico
+ Downloads
+ Provedor
+ Atual
+ Menu
+ Conteúdo da página inicial
+ Nenhum conteúdo do provedor
+ Provedor não encontrado
+ Fonte
+ Fontes
+ Enredo
+ Elenco
+ Erro ao carregar detalhes
+ Lista de episódios
+ Temporada
+ Temporadas
+ Episódio
+ Nenhum episódio encontrado
+ Não é uma série de TV
+ Adicionado aos favoritos
+ Removido dos favoritos
+ Nenhum favorito encontrado
+ Iniciando reprodução...
+ Reproduzindo
+ Nenhum link encontrado
+ Nenhum conteúdo reproduzível encontrado
+ Não foi possível carregar os detalhes
+ Erro ao carregar links
+ Ajustar à tela
+ Preencher tela
+ Nenhuma fonte encontrada
+ Nenhuma fonte disponível
+ Fonte selecionada
+ Buscar
+ Nenhum resultado encontrado
+ Nenhum item \'Continuar assistindo\' encontrado
+ Nenhum download encontrado
+ Arquivo não encontrado
+ Nenhum episódio válido encontrado
+ Selecionar provedor
+ Selecionado
+ Biblioteca
+ Marcadores
+ Retomando %1$s...
+
diff --git a/app/src/main/res-car/values-b+qt/strings_car.xml b/app/src/main/res-car/values-b+qt/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+qt/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+ro/strings_car.xml b/app/src/main/res-car/values-b+ro/strings_car.xml
new file mode 100644
index 00000000000..fb7f4316bbe
--- /dev/null
+++ b/app/src/main/res-car/values-b+ro/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Se încarcă...
+ Eroare
+ Eroare la încărcarea conținutului
+ Favorite
+ Istoric
+ Descărcări
+ Furnizor
+ Curent
+ Meniu
+ Conținut acasă
+ Niciun conținut de la furnizor
+ Furnizorul nu a fost găsit
+ Sursă
+ Surse
+ Intrigă
+ Distribuție
+ Eroare la încărcarea detaliilor
+ Listă episoade
+ Sezon
+ Sezoane
+ Episod
+ Nu s-au găsit episoade
+ Nu este serial TV
+ Adăugat la favorite
+ Eliminat din favorite
+ Nu s-au găsit favorite
+ Se începe redarea...
+ Se redă
+ Nu s-a găsit link
+ Nu s-a găsit conținut care poate fi redat
+ Nu se pot încărca detaliile
+ Eroare la încărcarea linkurilor
+ Potrivire la ecran
+ Umplere ecran
+ Nu s-a găsit sursă
+ Nicio sursă disponibilă
+ Sursă selectată
+ Căutare
+ Niciun rezultat găsit
+ Nu s-a găsit \'Continuare vizionare\'
+ Nu s-au găsit descărcări
+ Fișierul nu a fost găsit
+ Nu s-a găsit episod valid
+ Selectează furnizor
+ Selectat
+ Bibliotecă
+ Marcaje
+ Se reia %1$s...
+
diff --git a/app/src/main/res-car/values-b+ru/strings_car.xml b/app/src/main/res-car/values-b+ru/strings_car.xml
new file mode 100644
index 00000000000..5d9ba1db8ac
--- /dev/null
+++ b/app/src/main/res-car/values-b+ru/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Загрузка...
+ Ошибка
+ Ошибка загрузки контента
+ Избранное
+ История
+ Загрузки
+ Провайдер
+ Текущий
+ Меню
+ Контент главной
+ Нет контента от провайдера
+ Провайдер не найден
+ Источник
+ Источники
+ Сюжет
+ Актеры
+ Ошибка загрузки деталей
+ Список эпизодов
+ Сезон
+ Сезоны
+ Эпизод
+ Эпизоды не найдены
+ Не сериал
+ Добавлено в избранное
+ Удалено из избранного
+ Избранное не найдено
+ Запуск воспроизведения...
+ Воспроизведение
+ Ссылка не найдена
+ Нет воспроизводимого контента
+ Не удалось загрузить детали
+ Ошибка загрузки ссылок
+ По размеру экрана
+ Заполнить экран
+ Источник не найден
+ Нет доступных источников
+ Источник выбран
+ Поиск
+ Результаты не найдены
+ Нет "Продолжить просмотр"
+ Загрузки не найдены
+ Файл не найден
+ Нет валидного эпизода
+ Выбрать провайдера
+ Выбрано
+ Библиотека
+ Закладки
+ Возобновление %1$s...
+
diff --git a/app/src/main/res-car/values-b+si/strings_car.xml b/app/src/main/res-car/values-b+si/strings_car.xml
new file mode 100644
index 00000000000..62482b2491c
--- /dev/null
+++ b/app/src/main/res-car/values-b+si/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ පූරණය වෙමින්...
+ දෝෂය
+ අන්තර්ගතය පූරණය කිරීමේ දෝෂය
+ ප්රියතමයන්
+ ඉතිහාසය
+ බාගැනීම්
+ සැපයුම්කරු
+ වත්මන්
+ මෙනුව
+ මුල් පිටුව අන්තර්ගතය
+ සැපයුම්කරුගෙන් අන්තර්ගතයක් නැත
+ සැපයුම්කරු හමු නොවිණි
+ මූලාශ්රය
+ මූලාශ්ර
+ කතාව
+ නළු නිළියන්
+ විස්තර පූරණය කිරීමේ දෝෂය
+ කොටස් ලැයිස්තුව
+ වාරය
+ වාර
+ කොටස
+ කොටස් හමු නොවිණි
+ රූපවාහිනී කතා මාලාවක් නොවේ
+ ප්රියතමයන් වෙත එක් කරන ලදී
+ ප්රියතමයන්ගෙන් ඉවත් කරන ලදී
+ ප්රියතමයන් හමු නොවිණි
+ ප්රතිණිර්මාණය ආරම්භ කරමින්...
+ වාදනය වෙමින්
+ සබැඳියක් හමු නොවිණි
+ වාදනය කළ හැකි අන්තර්ගතයක් හමු නොවිණි
+ විස්තර පූරණය කළ නොහැක
+ සබැඳි පූරණය කිරීමේ දෝෂය
+ තිරයට ගැලපේ
+ තිරය පුරවන්න
+ මූලාශ්රයක් හමු නොවිණි
+ මූලාශ්රයක් නොමැත
+ මූලාශ්රය තෝරා ගන්නා ලදී
+ සොයන්න
+ ප්රතිඵල හමු නොවිණි
+ \'නැරඹීම අඛණ්ඩව\' හමු නොවිණි
+ බාගැනීම් හමු නොවිණි
+ ගොනුව හමු නොවිණි
+ වලංගු කොටසක් හමු නොවිණි
+ සැපයුම්කරු තෝරන්න
+ තෝරා ගන්නා ලදී
+ පුස්තකාලය
+ පොත් යොමු
+ %1$s නැවත ආරම්භ කරමින්...
+
diff --git a/app/src/main/res-car/values-b+sk/strings_car.xml b/app/src/main/res-car/values-b+sk/strings_car.xml
new file mode 100644
index 00000000000..250aa89c43a
--- /dev/null
+++ b/app/src/main/res-car/values-b+sk/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Načítavanie...
+ Chyba
+ Chyba pri načítavaní obsahu
+ Obľúbené
+ História
+ Sťahovania
+ Poskytovateľ
+ Aktuálne
+ Menu
+ Domovský obsah
+ Žiadny obsah od poskytovateľa
+ Poskytovateľ nenájdený
+ Zdroj
+ Zdroje
+ Dej
+ Obsadenie
+ Chyba pri načítavaní podrobností
+ Zoznam epizód
+ Séria
+ Série
+ Epizóda
+ Nenašli sa žiadne epizódy
+ Nie je to TV seriál
+ Pridané do obľúbených
+ Odstránené z obľúbených
+ Žiadne obľúbené položky
+ Spúšťanie prehrávania...
+ Prehrávanie
+ Odkaz sa nenašiel
+ Žiadny prehrávateľný obsah
+ Nedá sa načítať podrobnosti
+ Chyba pri načítavaní odkazov
+ Prispôsobiť na obrazovku
+ Vyplniť obrazovku
+ Zdroj sa nenašiel
+ Žiadny zdroj k dispozícii
+ Zdroj vybraný
+ Hľadať
+ Žiadne výsledky sa nenašli
+ \'Pokračovať v sledovaní\' sa nenašlo
+ Žiadne sťahovania
+ Súbor nenájdený
+ Žiadna platná epizóda
+ Vybrať poskytovateľa
+ Vybrané
+ Knižnica
+ Záložky
+ Obnovovanie %1$s...
+
diff --git a/app/src/main/res-car/values-b+sl/strings_car.xml b/app/src/main/res-car/values-b+sl/strings_car.xml
new file mode 100644
index 00000000000..5a97685aaff
--- /dev/null
+++ b/app/src/main/res-car/values-b+sl/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Nalaganje...
+ Napaka
+ Napaka pri nalaganju vsebine
+ Priljubljene
+ Zgodovina
+ Prenosi
+ Ponudnik
+ Trenutno
+ Meni
+ Domača vsebina
+ Ni vsebine od ponudnika
+ Ponudnik ni najden
+ Vir
+ Viri
+ Zgodba
+ Igralska zasedba
+ Napaka pri nalaganju podrobnosti
+ Seznam epizod
+ Sezona
+ Sezone
+ Epizoda
+ Ni najdenih epizod
+ Ni TV serija
+ Dodano med priljubljene
+ Odstranjeno iz priljubljenih
+ Ni priljubljenih
+ Začenjam predvajanje...
+ Predvajam
+ Povezava ni najdena
+ Ni vsebine za predvajanje
+ Ni bilo mogoče naložiti podrobnosti
+ Napaka pri nalaganju povezav
+ Prilagodi zaslonu
+ Napolni zaslon
+ Vir ni najden
+ Ni razpoložljivih virov
+ Vir izbran
+ Iskanje
+ Ni rezultatov
+ \'Nadaljuj z ogledom\' ni najdeno
+ Ni prenosov
+ Datoteka ni najdena
+ Ni veljavne epizode
+ Izberi ponudnika
+ Izbrano
+ Knjižnica
+ Zaznamki
+ Nadaljujem %1$s...
+
diff --git a/app/src/main/res-car/values-b+so/strings_car.xml b/app/src/main/res-car/values-b+so/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+so/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+sq/strings_car.xml b/app/src/main/res-car/values-b+sq/strings_car.xml
new file mode 100644
index 00000000000..dcb8bc43bfd
--- /dev/null
+++ b/app/src/main/res-car/values-b+sq/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Duke ngarkuar...
+ Gabim
+ Gabim në ngarkimin e përmbajtjes
+ Të preferuarat
+ Historia
+ Shkarkimet
+ Ofruesi
+ Aktual
+ Menu
+ Përmbajtja e kreut
+ Nuk ka përmbajtje nga ofruesi
+ Ofruesi nuk u gjet
+ Burimi
+ Burimet
+ Përmbajtja
+ Aktorët
+ Gabim në ngarkimin e detajeve
+ Lista e episodeve
+ Sezoni
+ Sezonet
+ Episodi
+ Nuk u gjetën episode
+ Nuk është serial TV
+ U shtua te të preferuarat
+ U hoq nga të preferuarat
+ Nuk u gjetën të preferuara
+ Duke filluar luajtjen...
+ Duke luajtur
+ Nuk u gjet lidhje
+ Nuk u gjet përmbajtje për t\'u luajtur
+ Nuk mund të ngarkohen detajet
+ Gabim në ngarkimin e lidhjeve
+ Përshtat në ekran
+ Mbush ekranin
+ Nuk u gjet burim
+ Asnjë burim i disponueshëm
+ Burimi u zgjodh
+ Kërko
+ Nuk u gjetën rezultate
+ \'Vazhdo shikimin\' nuk u gjet
+ Nuk u gjetën shkarkime
+ Skedari nuk u gjet
+ Nuk u gjet episod i vlefshëm
+ Zgjidh ofruesin
+ E zgjedhur
+ Biblioteka
+ Faqerojtësit
+ Duke vazhduar %1$s...
+
diff --git a/app/src/main/res-car/values-b+sr/strings_car.xml b/app/src/main/res-car/values-b+sr/strings_car.xml
new file mode 100644
index 00000000000..6b81d44509b
--- /dev/null
+++ b/app/src/main/res-car/values-b+sr/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Učitavanje...
+ Greška
+ Greška pri učitavanju sadržaja
+ Favoriti
+ Istorija
+ Preuzimanja
+ Provajder
+ Trenutno
+ Meni
+ Početni sadržaj
+ Nema sadržaja od provajdera
+ Provajder nije pronađen
+ Izvor
+ Izvori
+ Radnja
+ Uloge
+ Greška pri učitavanju detalja
+ Lista epizoda
+ Sezona
+ Sezone
+ Epizoda
+ Nema pronađenih epizoda
+ Nije TV serija
+ Dodato u favorite
+ Uklonjeno iz favorita
+ Nema favorita
+ Pokretanje reprodukcije...
+ Reprodukcija
+ Link nije pronađen
+ Sadržaj za reprodukciju nije pronađen
+ Nije moguće učitati detalje
+ Greška pri učitavanju linkova
+ Prilagodi ekranu
+ Popuni ekran
+ Izvor nije pronađen
+ Izvor nije dostupan
+ Izvor izabran
+ Pretraga
+ Nema rezultata
+ \'Nastavi gledanje\' nije pronađeno
+ Nema preuzimanja
+ Datoteka nije pronađena
+ Nema važeće epizode
+ Izaberi provajdera
+ Izabrano
+ Biblioteka
+ Obeleživači
+ Nastavljanje %1$s...
+
diff --git a/app/src/main/res-car/values-b+sv/strings_car.xml b/app/src/main/res-car/values-b+sv/strings_car.xml
new file mode 100644
index 00000000000..fcbf7528bc8
--- /dev/null
+++ b/app/src/main/res-car/values-b+sv/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Laddar...
+ Fel
+ Fel vid laddning av innehåll
+ Favoriter
+ Historik
+ Nedladdningar
+ Leverantör
+ Nuvarande
+ Meny
+ Heminnehåll
+ Inget innehåll från leverantör
+ Leverantör hittades inte
+ Källa
+ Källor
+ Handling
+ Skådespelare
+ Fel vid laddning av detaljer
+ Avsnittslista
+ Säsong
+ Säsonger
+ Avsnitt
+ Inga avsnitt hittades
+ Inte en TV-serie
+ Tillagd i favoriter
+ Borttagen från favoriter
+ Inga favoriter hittades
+ Startar uppspelning...
+ Spelar
+ Ingen länk hittades
+ Inget spelbart innehåll hittades
+ Kunde inte ladda detaljer
+ Fel vid laddning av länkar
+ Anpassa till skärm
+ Fyll skärm
+ Ingen källa hittades
+ Ingen källa tillgänglig
+ Källa vald
+ Sök
+ Inga resultat hittades
+ Inget \'Fortsätt titta\' hittades
+ Inga nedladdningar hittades
+ Filen hittades inte
+ Inget giltigt avsnitt hittades
+ Välj leverantör
+ Vald
+ Bibliotek
+ Bokmärken
+ Återupptar %1$s...
+
diff --git a/app/src/main/res-car/values-b+sw/strings_car.xml b/app/src/main/res-car/values-b+sw/strings_car.xml
new file mode 100644
index 00000000000..97997a98256
--- /dev/null
+++ b/app/src/main/res-car/values-b+sw/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Inapakia...
+ Hitilafu
+ Hitilafu katika kupakia maudhui
+ Vipendwa
+ Historia
+ Vipakuliwa
+ Mtoaji
+ Sasa
+ Menyu
+ Maudhui ya Nyumbani
+ Hakuna maudhui kutoka kwa mtoaji
+ Mtoaji hajapatikana
+ Chanzo
+ Vyanzo
+ Hadithi
+ Waigizaji
+ Hitilafu katika kupakia maelezo
+ Orodha ya Vipindi
+ Msimu
+ Misimu
+ Kipindi
+ Hakuna vipindi vilivyopatikana
+ Si mfululizo wa TV
+ Imeongezwa kwenye vipendwa
+ Imeondolewa kwenye vipendwa
+ Hakuna vipendwa vilivyopatikana
+ Inaanza kucheza...
+ Inacheza
+ Hakuna kiungo kilichopatikana
+ Hakuna maudhui ya kucheza yaliyopatikana
+ Imeshindwa kupakia maelezo
+ Hitilafu katika kupakia viungo
+ Toshea kwenye Skrini
+ Jaza Skrini
+ Hakuna chanzo kilichopatikana
+ Hakuna chanzo kinachopatikana
+ Chanzo kimechaguliwa
+ Tafuta
+ Hakuna matokeo yaliyopatikana
+ \'Endelea Kutazama\' haijapatikana
+ Hakuna vipakuliwa vilivyopatikana
+ Faili haijapatikana
+ Hakuna kipindi halali kilichopatikana
+ Chagua Mtoaji
+ Imechaguliwa
+ Maktaba
+ Alamisho
+ Inaendelea %1$s...
+
diff --git a/app/src/main/res-car/values-b+ta/strings_car.xml b/app/src/main/res-car/values-b+ta/strings_car.xml
new file mode 100644
index 00000000000..b7960e0b796
--- /dev/null
+++ b/app/src/main/res-car/values-b+ta/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ ஏற்றுகிறது...
+ பிழை
+ உள்ளடக்கத்தை ஏற்றுவதில் பிழை
+ விருப்பங்கள்
+ வரலாறு
+ பதிவிறக்கங்கள்
+ வழங்குநர்
+ தற்போதைய
+ மெனு
+ முகப்பு உள்ளடக்கம்
+ வழங்குநரிடமிருந்து உள்ளடக்கம் இல்லை
+ வழங்குநரைக் காணவில்லை
+ மூலம்
+ மூலங்கள்
+ கதைக்களம்
+ நடிப்பு
+ விவரங்களை ஏற்றுவதில் பிழை
+ அத்தியாயப் பட்டியல்
+ பருவம்
+ பருவங்கள்
+ அத்தியாயம்
+ அத்தியாயங்கள் எதுவும் காணப்படவில்லை
+ தொலைக்காட்சித் தொடர் அல்ல
+ விருப்பங்களில் சேர்க்கப்பட்டது
+ விருப்பங்களிலிருந்து நீக்கப்பட்டது
+ விருப்பங்கள் எதுவும் இல்லை
+ இயக்கத்தைத் தொடங்குகிறது...
+ இயங்குகிறது
+ இணைப்பு எதுவும் காணப்படவில்லை
+ இயக்கக்கூடிய உள்ளடக்கம் எதுவும் இல்லை
+ விவரங்களை ஏற்ற முடியவில்லை
+ இணைப்புகளை ஏற்றுவதில் பிழை
+ திரைக்குப் பொருத்து
+ திரையை நிரப்பு
+ மூலம் எதுவும் காணப்படவில்லை
+ மூலம் எதுவும் கிடைக்கவில்லை
+ மூலம் தேர்ந்தெடுக்கப்பட்டது
+ தேடு
+ முடிவுகள் எதுவும் இல்லை
+ \'தொடர்ந்து பார்க்க\' எதுவும் இல்லை
+ பதிவிறக்கங்கள் எதுவும் இல்லை
+ கோப்பைக் காணவில்லை
+ செல்லுபடியாகும் அத்தியாயம் எதுவும் இல்லை
+ வழங்குநரைத் தேர்ந்தெடு
+ தேர்ந்தெடுக்கப்பட்டது
+ நூலகம்
+ புத்தகக்குறிகள்
+ %1$s தொடர்கிறது...
+
diff --git a/app/src/main/res-car/values-b+te/strings_car.xml b/app/src/main/res-car/values-b+te/strings_car.xml
new file mode 100644
index 00000000000..d2d9ace81ac
--- /dev/null
+++ b/app/src/main/res-car/values-b+te/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ లోడ్ అవుతోంది...
+ లోపం
+ కంటెంట్ లోడ్ చేయడంలో లోపం
+ ఇష్టమైనవి
+ చరిత్ర
+ డౌన్లోడ్లు
+ ప్రొవైడర్
+ ప్రస్తుత
+ మెనూ
+ హోమ్ కంటెంట్
+ ప్రొవైడర్ నుండి కంటెంట్ లేదు
+ ప్రొవైడర్ కనుగొనబడలేదు
+ మూలం
+ మూలాలు
+ కథాంశం
+ నటీనటులు
+ వివరాలు లోడ్ చేయడంలో లోపం
+ ఎపిసోడ్ జాబితా
+ సీజన్
+ సీజన్లు
+ ఎపిసోడ్
+ ఎపిసోడ్లు కనుగొనబడలేదు
+ టీవీ సిరీస్ కాదు
+ ఇష్టమైన వాటికి జోడించబడింది
+ ఇష్టమైన వాటి నుండి తీసివేయబడింది
+ ఇష్టమైనవి కనుగొనబడలేదు
+ ప్లేబ్యాక్ ప్రారంభమవుతోంది...
+ ప్లే అవుతోంది
+ లింక్ కనుగొనబడలేదు
+ ప్లే చేయగల కంటెంట్ కనుగొనబడలేదు
+ వివరాలు లోడ్ చేయడం సాధ్యం కాలేదు
+ లింక్లు లోడ్ చేయడంలో లోపం
+ స్క్రీన్కు సరిపోల్చండి
+ స్క్రీన్ను నింపండి
+ మూలం కనుగొనబడలేదు
+ మూలం అందుబాటులో లేదు
+ మూలం ఎంపిక చేయబడింది
+ శోధించు
+ ఫలితాలు కనుగొనబడలేదు
+ \'చూడటం కొనసాగించు\' కనుగొనబడలేదు
+ డౌన్లోడ్లు కనుగొనబడలేదు
+ ఫైల్ కనుగొనబడలేదు
+ చెల్లుబాటు అయ్యే ఎపిసోడ్ కనుగొనబడలేదు
+ ప్రొవైడర్ను ఎంచుకోండి
+ ఎంపిక చేయబడింది
+ లైబ్రరీ
+ బుక్మార్క్లు
+ %1$s పునఃప్రారంభించబడుతోంది...
+
diff --git a/app/src/main/res-car/values-b+tg/strings_car.xml b/app/src/main/res-car/values-b+tg/strings_car.xml
new file mode 100644
index 00000000000..f29105798bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+tg/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Боргирӣ...
+ Хатогӣ
+ Хатогӣ дар боргирии муҳтаво
+ Дӯстдоштаҳо
+ Таърих
+ Боргириҳо
+ Провайдер
+ Ҷорӣ
+ Меню
+ Муҳтавои хона
+ Ҳеҷ муҳтаво аз провайдер нест
+ Провайдер ёфт нашуд
+ Манбаъ
+ Манбаъҳо
+ Сюжет
+ Ҳунармандон
+ Хатогӣ дар боргирии тафсилот
+ Рӯйхати қисмҳо
+ Мавсим
+ Мавсимҳо
+ Қисм
+ Ҳеҷ қисм ёфт нашуд
+ Силсилафилм нест
+ Ба дӯстдоштаҳо илова шуд
+ Аз дӯстдоштаҳо хориҷ шуд
+ Ҳеҷ дӯстдошта ёфт нашуд
+ Оғози пахш...
+ Дар ҳоли пахш
+ Ҳеҷ пайванд ёфт нашуд
+ Ҳеҷ муҳтавои қобили пахш ёфт нашуд
+ Тафсилот боргирӣ нашуд
+ Хатогӣ дар боргирии пайвандҳо
+ Ба экран мувофиқ кардан
+ Пур кардани экран
+ Ҳеҷ манбаъ ёфт нашуд
+ Ҳеҷ манбаъ дастрас нест
+ Манбаъ интихоб шуд
+ Ҷустуҷӯ
+ Ҳеҷ натиҷа ёфт нашуд
+ \'Идомаи тамошо\' ёфт нашуд
+ Ҳеҷ боргирӣ ёфт нашуд
+ Файл ёфт нашуд
+ Ҳеҷ қисми дуруст ёфт нашуд
+ Провайдерро интихоб кунед
+ Интихобшуда
+ Китобхона
+ Хабовҳо
+ Идомаи %1$s...
+
diff --git a/app/src/main/res-car/values-b+th/strings_car.xml b/app/src/main/res-car/values-b+th/strings_car.xml
new file mode 100644
index 00000000000..374658cc309
--- /dev/null
+++ b/app/src/main/res-car/values-b+th/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ กำลังโหลด...
+ ข้อผิดพลาด
+ ข้อผิดพลาดในการโหลดเนื้อหา
+ รายการโปรด
+ ประวัติ
+ ดาวน์โหลด
+ ผู้ให้บริการ
+ ปัจจุบัน
+ เมนู
+ เนื้อหาหน้าแรก
+ ไม่มีเนื้อหาจากผู้ให้บริการ
+ ไม่พบผู้ให้บริการ
+ แหล่งที่มา
+ แหล่งที่มา
+ เนื้อเรื่อง
+ นักแสดง
+ ข้อผิดพลาดในการโหลดรายละเอียด
+ รายการตอน
+ ซีซั่น
+ ซีซั่น
+ ตอน
+ ไม่พบตอน
+ ไม่ใช่ทีวีซีรีส์
+ เพิ่มในรายการโปรดแล้ว
+ ลบออกจากรายการโปรดแล้ว
+ ไม่พบรายการโปรด
+ กำลังเริ่มเล่น...
+ กำลังเล่น
+ ไม่พบลิงก์
+ ไม่พบเนื้อหาที่เล่นได้
+ ไม่สามารถโหลดรายละเอียดได้
+ ข้อผิดพลาดในการโหลดลิงก์
+ พอดีหน้าจอ
+ เต็มหน้าจอ
+ ไม่พบแหล่งที่มา
+ ไม่มีแหล่งที่มาที่ใช้ได้
+ เลือกแหล่งที่มาแล้ว
+ ค้นหา
+ ไม่พบผลลัพธ์
+ ไม่พบ \'ดูต่อ\'
+ ไม่พบการดาวน์โหลด
+ ไม่พบไฟล์
+ ไม่พบตอนที่ถูกต้อง
+ เลือกผู้ให้บริการ
+ ที่เลือก
+ ห้องสมุด
+ บุ๊กมาร์ก
+ กำลังดูต่อ %1$s...
+
diff --git a/app/src/main/res-car/values-b+ti/strings_car.xml b/app/src/main/res-car/values-b+ti/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+ti/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+tl/strings_car.xml b/app/src/main/res-car/values-b+tl/strings_car.xml
new file mode 100644
index 00000000000..a99f6e086a9
--- /dev/null
+++ b/app/src/main/res-car/values-b+tl/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Naglo-load...
+ Error
+ Error sa pag-load ng nilalaman
+ Mga Paborito
+ Kasaysayan
+ Mga Download
+ Tagapagbigay
+ Kasalukuyan
+ Menu
+ Nilalaman ng tahanan
+ Walang nilalaman mula sa tagapagbigay
+ Hindi natagpuan ang tagapagbigay
+ Pinagmulan
+ Mga Pinagmulan
+ Kuwento
+ Tauhan
+ Error sa pag-load ng mga detalye
+ Listahan ng Episodyo
+ Season
+ Mga Season
+ Episodyo
+ Walang natagpuang episodyo
+ Hindi serye sa TV
+ Idinagdag sa mga paborito
+ Inalis sa mga paborito
+ Walang natagpuang paborito
+ Sinisimulan ang pag-playback...
+ Gumagana
+ Walang natagpuang link
+ Walang natagpuang puwedeng i-play na nilalaman
+ Hindi ma-load ang mga detalye
+ Error sa pag-load ng mga link
+ Pagkasyahin sa Screen
+ Punuin ang Screen
+ Walang napiling pinagmulan
+ Walang magagamit na pinagmulan
+ Napiling pinagmulan
+ Maghanap
+ Walang natagpuang resulta
+ Hindi natagpuan ang \'Ituloy ang Panonood\'
+ Walang natagpuang download
+ Hindi natagpuan ang file
+ Walang wastong episodyo na natagpuan
+ Piliin ang Tagapagbigay
+ Napili
+ Aklatan
+ Mga Bookmark
+ Ipinagpapatuloy ang %1$s...
+
diff --git a/app/src/main/res-car/values-b+tr/strings_car.xml b/app/src/main/res-car/values-b+tr/strings_car.xml
new file mode 100644
index 00000000000..17b162f542f
--- /dev/null
+++ b/app/src/main/res-car/values-b+tr/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Yükleniyor...
+ Hata
+ İçerik yüklenirken hata
+ Favoriler
+ Geçmiş
+ İndirilenler
+ Sağlayıcı
+ Mevcut
+ Menü
+ Ana Sayfa İçeriği
+ Sağlayıcıdan içerik yok
+ Sağlayıcı bulunamadı
+ Kaynak
+ Kaynaklar
+ Konu
+ Oyuncular
+ Detaylar yüklenirken hata
+ Bölüm Listesi
+ Sezon
+ Sezonlar
+ Bölüm
+ Bölüm bulunamadı
+ TV dizisi değil
+ Favorilere eklendi
+ Favorilerden çıkarıldı
+ Favori bulunamadı
+ Oynatma başlatılıyor...
+ Oynatılıyor
+ Bağlantı bulunamadı
+ Oynatılabilir içerik bulunamadı
+ Detaylar yüklenemedi
+ Bağlantılar yüklenirken hata
+ Ekrana Sığdır
+ Ekranı Doldur
+ Kaynak bulunamadı
+ Mevcut kaynak yok
+ Kaynak seçildi
+ Ara
+ Sonuç bulunamadı
+ \'İzlemeye Devam Et\' bulunamadı
+ İndirme bulunamadı
+ Dosya bulunamadı
+ Geçerli bölüm bulunamadı
+ Sağlayıcı Seç
+ Seçildi
+ Kütüphane
+ Yer İmleri
+ %1$s devam ettiriliyor...
+
diff --git a/app/src/main/res-car/values-b+uk/strings_car.xml b/app/src/main/res-car/values-b+uk/strings_car.xml
new file mode 100644
index 00000000000..5cd25097ff6
--- /dev/null
+++ b/app/src/main/res-car/values-b+uk/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Завантаження...
+ Помилка
+ Помилка завантаження вмісту
+ Обране
+ Історія
+ Завантаження
+ Провайдер
+ Поточний
+ Меню
+ Домашній вміст
+ Немає вмісту від провайдера
+ Провайдера не знайдено
+ Джерело
+ Джерела
+ Сюжет
+ Актори
+ Помилка завантаження деталей
+ Список епізодів
+ Сезон
+ Сезони
+ Епізод
+ Епізодів не знайдено
+ Не серіал
+ Додано до обраного
+ Видалено з обраного
+ Немає обраного
+ Початок відтворення...
+ Відтворення
+ Посилання не знайдено
+ Вміст для відтворення не знайдено
+ Не вдалося завантажити деталі
+ Помилка завантаження посилань
+ Припасувати до екрану
+ Заповнити екран
+ Джерело не знайдено
+ Джерела недоступні
+ Джерело вибрано
+ Пошук
+ Результатів не знайдено
+ \'Продовжити перегляд\' не знайдено
+ Завантажень не знайдено
+ Файл не знайдено
+ Дійсний епізод не знайдено
+ Вибрати провайдера
+ Вибрано
+ Бібліотека
+ Закладки
+ Відновлення %1$s...
+
diff --git a/app/src/main/res-car/values-b+ur/strings_car.xml b/app/src/main/res-car/values-b+ur/strings_car.xml
new file mode 100644
index 00000000000..43b74a6a62e
--- /dev/null
+++ b/app/src/main/res-car/values-b+ur/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ لوڈ ہو رہا ہے...
+ خرابی
+ مواد لوڈ کرنے میں خرابی
+ پسندیدہ
+ تاریخچہ
+ ڈاؤن لوڈز
+ فراہم کنندہ
+ موجودہ
+ مینو
+ ہوم مواد
+ فراہم کنندہ سے کوئی مواد نہیں
+ فراہم کنندہ نہیں ملا
+ ماخذ
+ ماخذات
+ پلاٹ
+ کاسٹ
+ تفصیلات لوڈ کرنے میں خرابی
+ اقساط کی فہرست
+ سیزن
+ سیزنز
+ قسط
+ کوئی قسط نہیں ملی
+ ٹی وی سیریز نہیں
+ پسندیدہ میں شامل کر دیا گیا
+ پسندیدہ سے ہٹا دیا گیا
+ کوئی پسندیدہ نہیں ملا
+ پلے بیک شروع ہو رہا ہے...
+ پلے ہو رہا ہے
+ کوئی لنک نہیں ملا
+ کوئی قابل پلے مواد نہیں ملا
+ تفصیلات لوڈ نہیں ہو سکیں
+ لنکس لوڈ کرنے میں خرابی
+ اسکرین پر فٹ کریں
+ اسکرین بھریں
+ کوئی ماخذ نہیں ملا
+ کوئی ماخذ دستیاب نہیں
+ ماخذ منتخب ہو گیا
+ تلاش
+ کوئی نتیجہ نہیں ملا
+ \'دیکھنا جاری رکھیں\' نہیں ملا
+ کوئی ڈاؤن لوڈ نہیں ملا
+ فائل نہیں ملی
+ کوئی درست قسط نہیں ملی
+ فراہم کنندہ منتخب کریں
+ منتخب شدہ
+ لائبریری
+ بک مارکس
+ %1$s دوبارہ شروع ہو رہا ہے...
+
diff --git a/app/src/main/res-car/values-b+uz/strings_car.xml b/app/src/main/res-car/values-b+uz/strings_car.xml
new file mode 100644
index 00000000000..30f36208f3f
--- /dev/null
+++ b/app/src/main/res-car/values-b+uz/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Yuklanmoqda...
+ Xato
+ Kontentni yuklashda xato
+ Sevimlilar
+ Tarix
+ Yuklanmalar
+ Provayder
+ Joriy
+ Menyu
+ Bosh sahifa kontenti
+ Provayderdan kontent yo\'q
+ Provayder topilmadi
+ Manba
+ Manbalar
+ Syujet
+ Rollarda
+ Tafsilotlarni yuklashda xato
+ Qismlar ro\'yxati
+ Mavsum
+ Mavsumlar
+ Qism
+ Qismlar topilmadi
+ TV serial emas
+ Sevimlilarga qo\'shildi
+ Sevimlilardan olib tashlandi
+ Sevimlilar topilmadi
+ Ijro boshlanmoqda...
+ Ijro etilmoqda
+ Havola topilmadi
+ Ijro etib bo\'ladigan kontent topilmadi
+ Tafsilotlarni yuklab bo\'lmadi
+ Havolalarni yuklashda xato
+ Ekranga moslash
+ Ekranni to\'ldirish
+ Manba topilmadi
+ Mavjud manba yo\'q
+ Manba tanlandi
+ Qidirish
+ Natijalar topilmadi
+ \'Ko\'rishni davom ettirish\' topilmadi
+ Yuklanmalar topilmadi
+ Fayl topilmadi
+ Yaroqli qism topilmadi
+ Provayderni tanlash
+ Tanlandi
+ Kutubxona
+ Xatcho\'plar
+ %1$s davom ettirilmoqda...
+
diff --git a/app/src/main/res-car/values-b+vi/strings_car.xml b/app/src/main/res-car/values-b+vi/strings_car.xml
new file mode 100644
index 00000000000..68c2393b14b
--- /dev/null
+++ b/app/src/main/res-car/values-b+vi/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Đang tải...
+ Lỗi
+ Lỗi tải nội dung
+ Yêu thích
+ Lịch sử
+ Tải xuống
+ Nguồn phát
+ Hiện tại
+ Menu
+ Nội dung trang chủ
+ Không có nội dung từ nguồn
+ Không tìm thấy nguồn
+ Nguồn
+ Nguồn
+ Cốt truyện
+ Diễn viên
+ Lỗi tải chi tiết
+ Danh sách tập
+ Mùa
+ Mùa
+ Tập
+ Không tìm thấy tập nào
+ Không phải phim bộ
+ Đã thêm vào yêu thích
+ Đã xóa khỏi yêu thích
+ Không có yêu thích
+ Đang bắt đầu phát...
+ Đang phát
+ Không tìm thấy liên kết
+ Không có nội dung phát được
+ Không thể tải chi tiết
+ Lỗi tải liên kết
+ Vừa màn hình
+ Lấp đầy màn hình
+ Không tìm thấy nguồn
+ Không có nguồn khả dụng
+ Đã chọn nguồn
+ Tìm kiếm
+ Không tìm thấy kết quả
+ Không tìm thấy \'Tiếp tục xem\'
+ Không tìm thấy bản tải xuống
+ Không tìm thấy tệp
+ Không có tập hợp lệ
+ Chọn nguồn
+ Đã chọn
+ Thư viện
+ Dấu trang
+ Đang tiếp tục %1$s...
+
diff --git a/app/src/main/res-car/values-b+zh+TW/strings_car.xml b/app/src/main/res-car/values-b+zh+TW/strings_car.xml
new file mode 100644
index 00000000000..ac0a25531bb
--- /dev/null
+++ b/app/src/main/res-car/values-b+zh+TW/strings_car.xml
@@ -0,0 +1,74 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res-car/values-b+zh/strings_car.xml b/app/src/main/res-car/values-b+zh/strings_car.xml
new file mode 100644
index 00000000000..8f950f7828b
--- /dev/null
+++ b/app/src/main/res-car/values-b+zh/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ 加载中...
+ 错误
+ 加载内容错误
+ 收藏
+ 历史
+ 下载
+ 提供商
+ 当前
+ 菜单
+ 首页内容
+ 无提供商内容
+ 未找到提供商
+ 来源
+ 来源
+ 剧情
+ 演员
+ 加载详情错误
+ 剧集列表
+ 季
+ 季
+ 集
+ 未找到剧集
+ 非电视剧
+ 已添加到收藏
+ 已从收藏移除
+ 无收藏
+ 开始播放...
+ 播放中
+ 无链接
+ 无由播放内容
+ 无法加载详情
+ 加载链接错误
+ 适应屏幕
+ 充满屏幕
+ 未找到来源
+ 无可用来源
+ 已选来源
+ 搜索
+ 无结果
+ 无继续观看
+ 无下载
+ 文件未找到
+ 无有效剧集
+ 选择提供商
+ 已选
+ 库
+ 书签
+ 恢复播放 %1$s...
+
diff --git a/app/src/main/res-car/values-b+zu/strings_car.xml b/app/src/main/res-car/values-b+zu/strings_car.xml
new file mode 100644
index 00000000000..28edfa24bb2
--- /dev/null
+++ b/app/src/main/res-car/values-b+zu/strings_car.xml
@@ -0,0 +1,51 @@
+
+
+ Iyalayisha...
+ Iphutha
+ Iphutha ekulayisheni okuqukethwe
+ Izintandokazi
+ Umlando
+ Okulandiwe
+ Umhlinzeki
+ Okwamanje
+ Imenyu
+ Okuqukethwe Kwasekhaya
+ Akukho okuqukethwe okuvela kumhlinzeki
+ Umhlinzeki akatholakalanga
+ Umthombo
+ Imithombo
+ Icebo
+ Abalingisi
+ Iphutha ekulayisheni imininingwane
+ Uhlu Lweziqephu
+ Isizini
+ Izinkathi
+ Isiqephu
+ Azikho iziqephu ezitholiwe
+ Akulona uchungechunge lwe-TV
+ Kungezwe kuzintandokazi
+ Kususiwe kuzintandokazi
+ Azikho izintandokazi ezitholiwe
+ Iqala ukudlala...
+ Iyadlala
+ Asikho isixhumanisi esitholiwe
+ Akukho okuqukethwe okudlalekayo okutholiwe
+ Ayikwazi ukulayisha imininingwane
+ Iphutha ekulayisheni izixhumanisi
+ Lingana nesikrini
+ Gcwalisa Isikrini
+ Awukho umthombo otholiwe
+ Awukho umthombo otholakalayo
+ Umthombo ukhethiwe
+ Sesha
+ Ayikho imiphumela etholiwe
+ \'Qhubeka nokubuka\' ayitholakali
+ Akukho okulandiwe okutholiwe
+ Ifayela alitholakalanga
+ Asikho isiqephu esivumelekile esitholiwe
+ Khetha Umhlinzeki
+ Kukhethiwe
+ Umtapo wolwazi
+ Amabhukhimakhi
+ Iyaqhubeka %1$s...
+
diff --git a/app/src/main/res-car/values-it/strings_car.xml b/app/src/main/res-car/values-it/strings_car.xml
new file mode 100644
index 00000000000..cb20b104b35
--- /dev/null
+++ b/app/src/main/res-car/values-it/strings_car.xml
@@ -0,0 +1,75 @@
+
+
+
+ Caricamento...
+ Errore
+ Errore caricamento contenuti
+
+
+ Preferiti
+ Cronologia
+ Download
+ Provider
+ Attuale
+ Menu
+ Contenuti Home
+ Nessun contenuto dal provider
+ Provider non trovato
+ Info su di me
+
+
+ Sorgente
+ Sorgenti
+ Trama
+ Cast
+ Errore caricamento dettagli
+
+
+ Lista Episodi
+ Stagione
+ Stagioni
+ Episodio
+ Nessun episodio trovato
+ Non è una serie TV
+
+
+ Aggiunto ai preferiti
+ Rimosso dai preferiti
+ Nessun preferito trovato
+
+
+ Avvio riproduzione...
+ In riproduzione
+ Nessun link trovato
+ Nessun contenuto riproducibile trovato
+ Impossibile caricare i dettagli
+ Errore caricamento link
+ Adatta allo schermo
+ Riempi schermo
+
+
+ Nessuna sorgente trovata
+ Nessuna sorgente disponibile
+ Sorgente selezionata
+
+
+ Cerca
+ Nessun risultato trovato
+
+
+ Nessun elemento \'Continua a guardare\' trovato
+
+
+ Nessun download completato trovato
+ File non trovato
+ Nessun episodio valido trovato
+
+
+ Seleziona Provider
+ Selezionato
+
+
+ Libreria
+ Segnalibri
+ Riprendo %1$s...
+
diff --git a/app/src/main/res-car/values/strings_car.xml b/app/src/main/res-car/values/strings_car.xml
new file mode 100644
index 00000000000..607af3ff28a
--- /dev/null
+++ b/app/src/main/res-car/values/strings_car.xml
@@ -0,0 +1,75 @@
+
+
+
+ Loading...
+ Error
+ Error loading content
+
+
+ Favorites
+ History
+ Downloads
+ Provider
+ Current
+ Menu
+ Home Content
+ No content from provider
+ Provider not found
+ About me
+
+
+ Source
+ Sources
+ Plot
+ Cast
+ Error loading details
+
+
+ Episode List
+ Season
+ Seasons
+ Episode
+ No episodes found
+ Not a TV series
+
+
+ Added to favorites
+ Removed from favorites
+ No favorites found
+
+
+ Starting playback...
+ Playing
+ No link found
+ No playable content found
+ Unable to load details
+ Error loading links
+ Fit to screen
+ Fill screen
+
+
+ No source found
+ No source available
+ Source selected
+
+
+ Search
+ No results found
+
+
+ No \'Continue watching\' items found
+
+
+ No completed downloads found
+ File not found
+ No valid episode found
+
+
+ Select Provider
+ Selected
+
+
+ Library
+ Bookmarks
+ Resuming %1$s...
+
diff --git a/app/src/main/res/drawable/go_back_30.xml b/app/src/main/res/drawable/go_back_30.xml
index 14999011662..8202d3ce42c 100644
--- a/app/src/main/res/drawable/go_back_30.xml
+++ b/app/src/main/res/drawable/go_back_30.xml
@@ -1,7 +1,7 @@
diff --git a/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml b/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml
index d93d1b64b91..c7b8b5f55fb 100644
--- a/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml
+++ b/app/src/main/res/drawable/ic_baseline_aspect_ratio_24.xml
@@ -1,4 +1,4 @@
-
diff --git a/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml b/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml
index f880379f0bb..0870be8f615 100644
--- a/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml
+++ b/app/src/main/res/drawable/ic_baseline_play_arrow_24.xml
@@ -1,4 +1,4 @@
-
diff --git a/app/src/main/res/drawable/ic_baseline_source_24.xml b/app/src/main/res/drawable/ic_baseline_source_24.xml
new file mode 100644
index 00000000000..0d7eb86d55f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_source_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_tune_24.xml b/app/src/main/res/drawable/ic_baseline_tune_24.xml
index d0c63a3d17d..0342fb06ea8 100644
--- a/app/src/main/res/drawable/ic_baseline_tune_24.xml
+++ b/app/src/main/res/drawable/ic_baseline_tune_24.xml
@@ -2,7 +2,7 @@
android:height="24dp"
android:viewportWidth="48"
android:viewportHeight="48"
- android:tint="?attr/white"
+ android:tint="#FFFFFF"
xmlns:android="http://schemas.android.com/apk/res/android">
diff --git a/app/src/main/res/raw/aboutme.mp4 b/app/src/main/res/raw/aboutme.mp4
new file mode 100644
index 00000000000..7a107a59ff8
Binary files /dev/null and b/app/src/main/res/raw/aboutme.mp4 differ
diff --git a/app/src/main/res/values-b+es/array.xml b/app/src/main/res/values-es/array.xml
similarity index 100%
rename from app/src/main/res/values-b+es/array.xml
rename to app/src/main/res/values-es/array.xml
diff --git a/app/src/main/res/values-b+es/strings.xml b/app/src/main/res/values-es/strings.xml
similarity index 100%
rename from app/src/main/res/values-b+es/strings.xml
rename to app/src/main/res/values-es/strings.xml
diff --git a/app/src/main/res/values-b+it/strings.xml b/app/src/main/res/values-it/strings.xml
similarity index 100%
rename from app/src/main/res/values-b+it/strings.xml
rename to app/src/main/res/values-it/strings.xml
diff --git a/app/src/main/res/xml/automotive_app_desc.xml b/app/src/main/res/xml/automotive_app_desc.xml
new file mode 100644
index 00000000000..c601d28ff79
--- /dev/null
+++ b/app/src/main/res/xml/automotive_app_desc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f0119613ca6..3c2f71a04c8 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -6,6 +6,7 @@ androidGradlePlugin = "8.13.2"
appcompat = "1.7.1"
biometric = "1.4.0-alpha04"
buildkonfigGradlePlugin = "0.17.1"
+carApp = "1.8.0-alpha03"
coil = "3.3.0"
colorpicker = "6b46b49bd5"
conscryptAndroid = { strictly = "2.5.2" } # 2.5.3 crashes everything
@@ -50,7 +51,7 @@ gpuv = "3a107f995b"
jvmTarget = "1.8"
jdkToolchain = "17"
-minSdk = "21"
+minSdk = "23"
compileSdk = "36"
targetSdk = "36"
@@ -58,6 +59,7 @@ targetSdk = "36"
activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" }
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
biometric = { module = "androidx.biometric:biometric", version.ref = "biometric" }
+car-app = { module = "androidx.car.app:app", version.ref = "carApp" }
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
coil-network-okhttp = { module = "io.coil-kt.coil3:coil-network-okhttp", version.ref = "coil" }
colorpicker = { module = "com.github.recloudstream:color-picker-android", version.ref = "colorpicker" }