Revert "translation fixes and modern view focus meta fix"
This commit is contained in:
parent
acf59fb3a1
commit
31992b884c
23 changed files with 98 additions and 1514 deletions
|
|
@ -10,7 +10,7 @@ import com.nuvio.tv.domain.model.MetaLink
|
|||
import com.nuvio.tv.domain.model.PosterShape
|
||||
import com.nuvio.tv.domain.model.Video
|
||||
|
||||
fun MetaDto.toDomain(episodeLabel: String = "Episode"): Meta {
|
||||
fun MetaDto.toDomain(): Meta {
|
||||
return Meta(
|
||||
id = id,
|
||||
type = ContentType.fromString(type),
|
||||
|
|
@ -39,7 +39,7 @@ fun MetaDto.toDomain(episodeLabel: String = "Episode"): Meta {
|
|||
photo = castMember.photo?.takeIf { it.isNotBlank() }
|
||||
)
|
||||
},
|
||||
videos = videos?.map { it.toDomain(episodeLabel) } ?: emptyList(),
|
||||
videos = videos?.map { it.toDomain() } ?: emptyList(),
|
||||
productionCompanies = emptyList(),
|
||||
networks = emptyList(),
|
||||
ageRating = null,
|
||||
|
|
@ -64,10 +64,10 @@ private fun coerceStringList(value: Any?): List<String> {
|
|||
}
|
||||
}
|
||||
|
||||
fun VideoDto.toDomain(episodeLabel: String = "Episode"): Video {
|
||||
fun VideoDto.toDomain(): Video {
|
||||
return Video(
|
||||
id = id,
|
||||
title = name ?: title ?: "$episodeLabel ${episode ?: number ?: 0}",
|
||||
title = name ?: title ?: "Episode ${episode ?: number ?: 0}",
|
||||
released = released,
|
||||
thumbnail = thumbnail,
|
||||
streams = streams?.map { it.toDomain(addonName = "Embedded Streams", addonLogo = null) } ?: emptyList(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.nuvio.tv.data.repository
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.nuvio.tv.core.network.NetworkResult
|
||||
import com.nuvio.tv.core.network.safeApiCall
|
||||
|
|
@ -11,8 +10,6 @@ import com.nuvio.tv.domain.model.Meta
|
|||
import com.nuvio.tv.domain.model.AddonResource
|
||||
import com.nuvio.tv.domain.repository.AddonRepository
|
||||
import com.nuvio.tv.domain.repository.MetaRepository
|
||||
import com.nuvio.tv.R
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
|
@ -23,7 +20,6 @@ import javax.inject.Singleton
|
|||
|
||||
@Singleton
|
||||
class MetaRepositoryImpl @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val api: AddonApi,
|
||||
private val addonRepository: AddonRepository
|
||||
) : MetaRepository {
|
||||
|
|
@ -55,8 +51,7 @@ class MetaRepositoryImpl @Inject constructor(
|
|||
is NetworkResult.Success -> {
|
||||
val metaDto = result.data.meta
|
||||
if (metaDto != null) {
|
||||
val episodeLabel = context.getString(R.string.episodes_episode)
|
||||
val meta = metaDto.toDomain(episodeLabel)
|
||||
val meta = metaDto.toDomain()
|
||||
metaCache[cacheKey] = meta
|
||||
emit(NetworkResult.Success(meta))
|
||||
} else {
|
||||
|
|
@ -126,8 +121,7 @@ class MetaRepositoryImpl @Inject constructor(
|
|||
is NetworkResult.Success -> {
|
||||
val metaDto = result.data.meta
|
||||
if (metaDto != null) {
|
||||
val episodeLabel = context.getString(R.string.episodes_episode)
|
||||
val meta = metaDto.toDomain(episodeLabel)
|
||||
val meta = metaDto.toDomain()
|
||||
addonMetaCache[cacheKey] = meta
|
||||
metaCache[cacheKey] = meta
|
||||
emit(NetworkResult.Success(meta))
|
||||
|
|
@ -153,8 +147,7 @@ class MetaRepositoryImpl @Inject constructor(
|
|||
is NetworkResult.Success -> {
|
||||
val metaDto = result.data.meta
|
||||
if (metaDto != null) {
|
||||
val episodeLabel = context.getString(R.string.episodes_episode)
|
||||
val meta = metaDto.toDomain(episodeLabel)
|
||||
val meta = metaDto.toDomain()
|
||||
addonMetaCache[cacheKey] = meta
|
||||
metaCache[cacheKey] = meta
|
||||
Log.d(
|
||||
|
|
|
|||
|
|
@ -118,15 +118,10 @@ fun CatalogRowSection(
|
|||
Modifier
|
||||
}
|
||||
|
||||
val strTypeMovie = stringResource(R.string.type_movie)
|
||||
val strTypeSeries = stringResource(R.string.type_series)
|
||||
val typeLabel = remember(catalogRow.rawType, catalogRow.apiType, strTypeMovie, strTypeSeries) {
|
||||
val raw = catalogRow.rawType.takeIf { it.isNotBlank() } ?: catalogRow.apiType
|
||||
when (raw.lowercase()) {
|
||||
"movie" -> strTypeMovie
|
||||
"series" -> strTypeSeries
|
||||
else -> formatAddonTypeLabel(raw)
|
||||
}
|
||||
val typeLabel = remember(catalogRow.rawType, catalogRow.apiType) {
|
||||
formatAddonTypeLabel(
|
||||
catalogRow.rawType.takeIf { it.isNotBlank() } ?: catalogRow.apiType
|
||||
)
|
||||
}
|
||||
val catalogTitle = remember(catalogRow.catalogName, typeLabel, showCatalogTypeSuffix) {
|
||||
val formattedName = catalogRow.catalogName.replaceFirstChar { it.uppercase() }
|
||||
|
|
|
|||
|
|
@ -219,9 +219,6 @@ fun ContinueWatchingCard(
|
|||
val strUpcoming = stringResource(R.string.cw_upcoming)
|
||||
val strNextUp = stringResource(R.string.cw_next_up)
|
||||
val strResume = stringResource(R.string.cw_resume)
|
||||
val strHoursMinLeft = stringResource(R.string.cw_hours_min_left)
|
||||
val strMinLeft = stringResource(R.string.cw_min_left)
|
||||
val strAlmostDone = stringResource(R.string.cw_almost_done)
|
||||
val nextUpBadgeText = nextUp?.let { info ->
|
||||
if (!info.hasAired) {
|
||||
info.airDateLabel?.let { strAirsDate } ?: strUpcoming
|
||||
|
|
@ -232,7 +229,7 @@ fun ContinueWatchingCard(
|
|||
val remainingText = progress?.let {
|
||||
remember(it.position, it.duration, it.progressPercent) {
|
||||
when {
|
||||
it.duration > 0L -> formatRemainingTime(it.remainingTime, strHoursMinLeft, strMinLeft, strAlmostDone)
|
||||
it.duration > 0L -> formatRemainingTime(it.remainingTime)
|
||||
it.progressPercent != null -> "${it.progressPercent.toInt().coerceIn(0, 100)}% watched"
|
||||
else -> strResume
|
||||
}
|
||||
|
|
@ -501,19 +498,14 @@ private fun firstNonBlank(vararg candidates: String?): String? {
|
|||
return candidates.firstOrNull { !it.isNullOrBlank() }?.trim()
|
||||
}
|
||||
|
||||
internal fun formatRemainingTime(
|
||||
remainingMs: Long,
|
||||
strHoursMinLeft: String,
|
||||
strMinLeft: String,
|
||||
strAlmostDone: String
|
||||
): String {
|
||||
internal fun formatRemainingTime(remainingMs: Long): String {
|
||||
val totalMinutes = TimeUnit.MILLISECONDS.toMinutes(remainingMs)
|
||||
val hours = totalMinutes / 60
|
||||
val minutes = totalMinutes % 60
|
||||
|
||||
return when {
|
||||
hours > 0 -> strHoursMinLeft.format(hours, minutes)
|
||||
minutes > 0 -> strMinLeft.format(minutes)
|
||||
else -> strAlmostDone
|
||||
hours > 0 -> "${hours}h ${minutes}m left"
|
||||
minutes > 0 -> "${minutes}m left"
|
||||
else -> "Almost done"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,11 +142,11 @@ private fun SyncOverviewCard(overview: SyncOverview) {
|
|||
modifier = Modifier.weight(1f),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
ProfileStatValue(overview.totalAddons, stringResource(R.string.account_stat_addons))
|
||||
ProfileStatValue(overview.totalPlugins, stringResource(R.string.account_stat_plugins))
|
||||
ProfileStatValue(overview.totalLibrary, stringResource(R.string.account_stat_library))
|
||||
ProfileStatValue(overview.totalWatchProgress, stringResource(R.string.account_stat_progress))
|
||||
ProfileStatValue(overview.totalWatchedItems, stringResource(R.string.account_stat_watched))
|
||||
ProfileStatValue(overview.totalAddons, "addons")
|
||||
ProfileStatValue(overview.totalPlugins, "plugins")
|
||||
ProfileStatValue(overview.totalLibrary, "library")
|
||||
ProfileStatValue(overview.totalWatchProgress, "progress")
|
||||
ProfileStatValue(overview.totalWatchedItems, "watched")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,11 +221,11 @@ private fun ProfileSyncRow(profile: ProfileSyncStats) {
|
|||
modifier = Modifier.weight(1f),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
ProfileStatValue(profile.addons, stringResource(R.string.account_stat_addons))
|
||||
ProfileStatValue(profile.plugins, stringResource(R.string.account_stat_plugins))
|
||||
ProfileStatValue(profile.library, stringResource(R.string.account_stat_library))
|
||||
ProfileStatValue(profile.watchProgress, stringResource(R.string.account_stat_progress))
|
||||
ProfileStatValue(profile.watchedItems, stringResource(R.string.account_stat_watched))
|
||||
ProfileStatValue(profile.addons, "addons")
|
||||
ProfileStatValue(profile.plugins, "plugins")
|
||||
ProfileStatValue(profile.library, "library")
|
||||
ProfileStatValue(profile.watchProgress, "progress")
|
||||
ProfileStatValue(profile.watchedItems, "watched")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
package com.nuvio.tv.ui.screens.account
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.nuvio.tv.R
|
||||
import com.nuvio.tv.BuildConfig
|
||||
import com.nuvio.tv.core.auth.AuthManager
|
||||
import com.nuvio.tv.core.plugin.PluginManager
|
||||
|
|
@ -61,8 +59,7 @@ class AccountViewModel @Inject constructor(
|
|||
private val watchedItemsPreferences: WatchedItemsPreferences,
|
||||
private val traktAuthDataStore: TraktAuthDataStore,
|
||||
private val postgrest: Postgrest,
|
||||
private val profileManager: ProfileManager,
|
||||
@dagger.hilt.android.qualifiers.ApplicationContext private val context: Context
|
||||
private val profileManager: ProfileManager
|
||||
) : ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(AccountUiState())
|
||||
|
|
@ -543,9 +540,9 @@ class AccountViewModel @Inject constructor(
|
|||
_uiState.update {
|
||||
it.copy(
|
||||
qrLoginStatus = when (normalizedStatus) {
|
||||
"approved" -> context.getString(R.string.qr_login_approved)
|
||||
"pending" -> context.getString(R.string.qr_login_pending)
|
||||
"expired" -> context.getString(R.string.qr_login_expired)
|
||||
"approved" -> "Login approved. Finishing sign in..."
|
||||
"pending" -> "Waiting for approval on your phone..."
|
||||
"expired" -> "QR login expired. Generate a new code."
|
||||
else -> "Status: ${result.status}"
|
||||
},
|
||||
qrLoginExpiresAtMillis = expiresAtMillis ?: it.qrLoginExpiresAtMillis,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.nuvio.tv.ui.screens.detail
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.nuvio.tv.R
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
|
@ -293,15 +291,9 @@ private fun CastMemberItem(
|
|||
|
||||
val character = member.character
|
||||
if (!character.isNullOrBlank()) {
|
||||
val displayCharacter = when {
|
||||
character.equals("Creator", ignoreCase = true) -> stringResource(R.string.cast_role_creator)
|
||||
character.equals("Director", ignoreCase = true) -> stringResource(R.string.cast_role_director)
|
||||
character.equals("Writer", ignoreCase = true) -> stringResource(R.string.cast_role_writer)
|
||||
else -> character
|
||||
}
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
text = displayCharacter,
|
||||
text = character,
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = NuvioColors.TextTertiary,
|
||||
maxLines = 1,
|
||||
|
|
|
|||
|
|
@ -5,18 +5,17 @@ import java.util.Locale
|
|||
import java.util.TimeZone
|
||||
|
||||
fun formatReleaseDate(isoDate: String): String {
|
||||
val locale = Locale.getDefault()
|
||||
return try {
|
||||
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US).apply {
|
||||
timeZone = TimeZone.getTimeZone("UTC")
|
||||
}
|
||||
val outputFormat = SimpleDateFormat("MMMM d, yyyy", locale)
|
||||
val outputFormat = SimpleDateFormat("MMMM d, yyyy", Locale.US)
|
||||
val date = inputFormat.parse(isoDate)
|
||||
date?.let { outputFormat.format(it) } ?: ""
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
val inputFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
val outputFormat = SimpleDateFormat("MMMM d, yyyy", locale)
|
||||
val outputFormat = SimpleDateFormat("MMMM d, yyyy", Locale.US)
|
||||
val date = inputFormat.parse(isoDate)
|
||||
date?.let { outputFormat.format(it) } ?: ""
|
||||
} catch (e: Exception) {
|
||||
|
|
|
|||
|
|
@ -39,16 +39,12 @@ import kotlinx.coroutines.flow.distinctUntilChanged
|
|||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import android.content.Context
|
||||
import com.nuvio.tv.R
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val TAG = "MetaDetailsViewModel"
|
||||
|
||||
@HiltViewModel
|
||||
class MetaDetailsViewModel @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val metaRepository: MetaRepository,
|
||||
private val tmdbSettingsDataStore: TmdbSettingsDataStore,
|
||||
private val tmdbService: TmdbService,
|
||||
|
|
@ -747,7 +743,7 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextVideoId = meta.id,
|
||||
nextSeason = null,
|
||||
nextEpisode = null,
|
||||
displayText = context.getString(R.string.detail_btn_resume)
|
||||
displayText = "Resume"
|
||||
)
|
||||
} else {
|
||||
NextToWatch(
|
||||
|
|
@ -756,7 +752,7 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextVideoId = meta.id,
|
||||
nextSeason = null,
|
||||
nextEpisode = null,
|
||||
displayText = context.getString(R.string.detail_btn_play)
|
||||
displayText = "Play"
|
||||
)
|
||||
}
|
||||
updateNextToWatch(nextToWatch)
|
||||
|
|
@ -775,7 +771,7 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextVideoId = meta.id,
|
||||
nextSeason = null,
|
||||
nextEpisode = null,
|
||||
displayText = context.getString(R.string.detail_btn_play)
|
||||
displayText = "Play"
|
||||
)
|
||||
)
|
||||
return@launch
|
||||
|
|
@ -809,7 +805,7 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextVideoId = metaId,
|
||||
nextSeason = null,
|
||||
nextEpisode = null,
|
||||
displayText = context.getString(R.string.detail_btn_play)
|
||||
displayText = "Play"
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -826,7 +822,7 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextVideoId = matchedEpisode?.id ?: latestProgress.videoId,
|
||||
nextSeason = season,
|
||||
nextEpisode = episode,
|
||||
displayText = context.getString(R.string.detail_btn_resume_episode, season, episode)
|
||||
displayText = "Resume S${season}E${episode}"
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -839,7 +835,7 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextVideoId = next.id,
|
||||
nextSeason = next.season,
|
||||
nextEpisode = next.episode,
|
||||
displayText = context.getString(R.string.detail_btn_next_episode, next.season, next.episode)
|
||||
displayText = "Next S${next.season}E${next.episode}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -880,24 +876,19 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextVideoId = resumeEpisode.id,
|
||||
nextSeason = resumeEpisode.season,
|
||||
nextEpisode = resumeEpisode.episode,
|
||||
displayText = context.getString(R.string.detail_btn_resume_episode, resumeEpisode.season, resumeEpisode.episode)
|
||||
displayText = "Resume S${resumeEpisode.season}E${resumeEpisode.episode}"
|
||||
)
|
||||
}
|
||||
nextUnwatchedEpisode != null -> {
|
||||
val hasWatchedSomething = fallbackProgressMap.isNotEmpty()
|
||||
val s = nextUnwatchedEpisode.season
|
||||
val e = nextUnwatchedEpisode.episode
|
||||
val displayPrefix = if (hasWatchedSomething) "Next" else "Play"
|
||||
NextToWatch(
|
||||
watchProgress = null,
|
||||
isResume = false,
|
||||
nextVideoId = nextUnwatchedEpisode.id,
|
||||
nextSeason = s,
|
||||
nextEpisode = e,
|
||||
displayText = if (hasWatchedSomething) {
|
||||
context.getString(R.string.detail_btn_next_episode, s, e)
|
||||
} else {
|
||||
context.getString(R.string.detail_btn_play_episode, s, e)
|
||||
}
|
||||
nextSeason = nextUnwatchedEpisode.season,
|
||||
nextEpisode = nextUnwatchedEpisode.episode,
|
||||
displayText = "$displayPrefix S${nextUnwatchedEpisode.season}E${nextUnwatchedEpisode.episode}"
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
|
|
@ -909,9 +900,9 @@ class MetaDetailsViewModel @Inject constructor(
|
|||
nextSeason = firstEpisode?.season,
|
||||
nextEpisode = firstEpisode?.episode,
|
||||
displayText = if (firstEpisode != null) {
|
||||
context.getString(R.string.detail_btn_play_episode, firstEpisode.season, firstEpisode.episode)
|
||||
"Play S${firstEpisode.season}E${firstEpisode.episode}"
|
||||
} else {
|
||||
context.getString(R.string.detail_btn_play)
|
||||
"Play"
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -219,7 +219,6 @@ internal fun ModernRowSection(
|
|||
onContinueWatchingOptions: (ContinueWatchingItem) -> Unit,
|
||||
isCatalogItemWatched: (MetaPreview) -> Boolean,
|
||||
onCatalogItemLongPress: (MetaPreview, String) -> Unit,
|
||||
onItemFocus: (MetaPreview) -> Unit,
|
||||
onCatalogSelectionFocused: (FocusedCatalogSelection) -> Unit,
|
||||
onNavigateToDetail: (String, String, String) -> Unit,
|
||||
onLoadMoreCatalog: (String, String, String) -> Unit,
|
||||
|
|
@ -391,7 +390,6 @@ internal fun ModernRowSection(
|
|||
val isContinueWatchingRow = row.key == "continue_watching"
|
||||
val onFocused = {
|
||||
onRowItemFocused(row.key, index, isContinueWatchingRow)
|
||||
item.metaPreview?.let { onItemFocus(it) }
|
||||
}
|
||||
|
||||
when (val payload = item.payload) {
|
||||
|
|
|
|||
|
|
@ -76,10 +76,8 @@ import androidx.compose.ui.res.stringResource
|
|||
import com.nuvio.tv.R
|
||||
|
||||
@Composable
|
||||
private fun localizedTypeLabel(key: String): String = when (key.lowercase()) {
|
||||
private fun localizedTypeLabel(key: String): String = when (key) {
|
||||
LibraryTypeTab.ALL_KEY -> stringResource(R.string.library_type_all)
|
||||
"movie" -> stringResource(R.string.type_movie)
|
||||
"series" -> stringResource(R.string.type_series)
|
||||
else -> formatAddonTypeLabel(key)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ internal fun EpisodesSidePanel(
|
|||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = if (uiState.showEpisodeStreams) stringResource(R.string.episodes_panel_streams_title) else stringResource(R.string.episodes_panel_title),
|
||||
text = if (uiState.showEpisodeStreams) "Streams" else "Episodes",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
color = NuvioColors.TextPrimary
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import android.content.Context
|
||||
package com.nuvio.tv.ui.screens.player
|
||||
|
||||
import androidx.media3.ui.AspectRatioFrameLayout
|
||||
import com.nuvio.tv.R
|
||||
|
||||
internal object PlayerDisplayModeUtils {
|
||||
fun nextResizeMode(currentMode: Int): Int {
|
||||
|
|
@ -14,14 +14,14 @@ internal object PlayerDisplayModeUtils {
|
|||
}
|
||||
}
|
||||
|
||||
fun resizeModeLabel(mode: Int, context: Context): String {
|
||||
fun resizeModeLabel(mode: Int): String {
|
||||
return when (mode) {
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIT -> context.getString(R.string.player_aspect_fit)
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FILL -> context.getString(R.string.player_aspect_stretch)
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH -> context.getString(R.string.player_aspect_fit_width)
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT -> context.getString(R.string.player_aspect_fit_height)
|
||||
AspectRatioFrameLayout.RESIZE_MODE_ZOOM -> context.getString(R.string.player_aspect_crop)
|
||||
else -> context.getString(R.string.player_aspect_fit)
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIT -> "Fit (Original)"
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FILL -> "Stretch"
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH -> "Fit Width"
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT -> "Fit Height"
|
||||
AspectRatioFrameLayout.RESIZE_MODE_ZOOM -> "Crop"
|
||||
else -> "Fit (Original)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -711,7 +711,7 @@ fun PlayerRuntimeController.onEvent(event: PlayerEvent) {
|
|||
PlayerEvent.OnToggleAspectRatio -> {
|
||||
val currentMode = _uiState.value.resizeMode
|
||||
val newMode = PlayerDisplayModeUtils.nextResizeMode(currentMode)
|
||||
val modeText = PlayerDisplayModeUtils.resizeModeLabel(newMode, context)
|
||||
val modeText = PlayerDisplayModeUtils.resizeModeLabel(newMode)
|
||||
Log.d("PlayerViewModel", "Aspect ratio toggled: $currentMode -> $newMode")
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
|
|
|
|||
|
|
@ -1770,7 +1770,7 @@ private fun SpeedItem(
|
|||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = if (speed == 1f) stringResource(R.string.player_speed_normal) else "${speed}x",
|
||||
text = if (speed == 1f) "Normal" else "${speed}x",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = if (isSelected) NuvioColors.Primary else NuvioColors.TextPrimary
|
||||
)
|
||||
|
|
|
|||
|
|
@ -103,19 +103,12 @@ internal fun SubtitleSelectionDialog(
|
|||
.distinct()
|
||||
.size
|
||||
}
|
||||
val strAddons = stringResource(R.string.subtitle_tab_addons)
|
||||
val strLanguages = stringResource(R.string.subtitle_tab_languages)
|
||||
val addonsTabTitle = when (subtitleOrganizationMode) {
|
||||
SubtitleOrganizationMode.BY_LANGUAGE -> strLanguages
|
||||
SubtitleOrganizationMode.BY_LANGUAGE -> "Languages"
|
||||
SubtitleOrganizationMode.NONE,
|
||||
SubtitleOrganizationMode.BY_ADDON -> strAddons
|
||||
SubtitleOrganizationMode.BY_ADDON -> "Addons"
|
||||
}
|
||||
val tabs = listOf(
|
||||
stringResource(R.string.subtitle_tab_builtin),
|
||||
addonsTabTitle,
|
||||
stringResource(R.string.subtitle_tab_style),
|
||||
stringResource(R.string.subtitle_tab_delay)
|
||||
)
|
||||
val tabs = listOf("Built-in", addonsTabTitle, "Style", "Delay")
|
||||
val tabFocusRequesters = remember { tabs.map { FocusRequester() } }
|
||||
|
||||
Dialog(onDismissRequest = onDismiss) {
|
||||
|
|
@ -275,7 +268,7 @@ private fun InternalSubtitlesContent(
|
|||
) {
|
||||
item {
|
||||
TrackItem(
|
||||
track = TrackInfo(index = -1, name = stringResource(R.string.subtitle_none), language = null),
|
||||
track = TrackInfo(index = -1, name = "None", language = null),
|
||||
isSelected = selectedIndex == -1 && selectedAddonSubtitle == null,
|
||||
onClick = onDisableSubtitles
|
||||
)
|
||||
|
|
@ -317,17 +310,11 @@ private fun AddonSubtitlesContent(
|
|||
isLoading: Boolean,
|
||||
onSubtitleSelected: (Subtitle) -> Unit
|
||||
) {
|
||||
val strAll = stringResource(R.string.subtitle_all)
|
||||
val strLanguages = stringResource(R.string.subtitle_tab_languages)
|
||||
val strAddons = stringResource(R.string.subtitle_tab_addons)
|
||||
val viewData = remember(subtitles, preferredLanguage, subtitleOrganizationMode, strAll, strLanguages, strAddons) {
|
||||
val viewData = remember(subtitles, preferredLanguage, subtitleOrganizationMode) {
|
||||
buildAddonSubtitleViewData(
|
||||
subtitles = subtitles,
|
||||
preferredLanguage = preferredLanguage,
|
||||
mode = subtitleOrganizationMode,
|
||||
strAll = strAll,
|
||||
strLanguages = strLanguages,
|
||||
strAddons = strAddons
|
||||
mode = subtitleOrganizationMode
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -491,10 +478,7 @@ private data class AddonSubtitleViewData(
|
|||
private fun buildAddonSubtitleViewData(
|
||||
subtitles: List<Subtitle>,
|
||||
preferredLanguage: String,
|
||||
mode: SubtitleOrganizationMode,
|
||||
strAll: String,
|
||||
strLanguages: String,
|
||||
strAddons: String
|
||||
mode: SubtitleOrganizationMode
|
||||
): AddonSubtitleViewData {
|
||||
val preferredFirst = sortByPreferredLanguage(subtitles, preferredLanguage) { it.lang }
|
||||
|
||||
|
|
@ -505,7 +489,7 @@ private fun buildAddonSubtitleViewData(
|
|||
filters = listOf(
|
||||
SubtitleFilter(
|
||||
key = "all",
|
||||
label = strAll,
|
||||
label = "All",
|
||||
items = preferredFirst
|
||||
)
|
||||
)
|
||||
|
|
@ -514,7 +498,7 @@ private fun buildAddonSubtitleViewData(
|
|||
|
||||
SubtitleOrganizationMode.BY_LANGUAGE -> {
|
||||
AddonSubtitleViewData(
|
||||
filterTitle = strLanguages,
|
||||
filterTitle = "Languages",
|
||||
filters = preferredFirst
|
||||
.groupBy { subtitleLanguageGroupKey(it.lang) }
|
||||
.map { (languageKey, items) ->
|
||||
|
|
@ -530,7 +514,7 @@ private fun buildAddonSubtitleViewData(
|
|||
|
||||
SubtitleOrganizationMode.BY_ADDON -> {
|
||||
AddonSubtitleViewData(
|
||||
filterTitle = strAddons,
|
||||
filterTitle = "Addons",
|
||||
filters = preferredFirst
|
||||
.groupBy { it.addonName }
|
||||
.map { (addon, items) ->
|
||||
|
|
@ -695,11 +679,11 @@ private fun SubtitleStyleContent(
|
|||
// Core section
|
||||
item {
|
||||
StyleSection(
|
||||
title = stringResource(R.string.subtitle_section_core),
|
||||
title = "Core",
|
||||
icon = Icons.Default.FormatSize
|
||||
) {
|
||||
// Font Size
|
||||
StyleSettingRow(label = stringResource(R.string.subtitle_font_size)) {
|
||||
StyleSettingRow(label = "Font Size") {
|
||||
StyleStepperButton(
|
||||
icon = Icons.Default.Remove,
|
||||
onClick = { onEvent(PlayerEvent.OnSetSubtitleSize(subtitleStyle.size - 10)) }
|
||||
|
|
@ -714,7 +698,7 @@ private fun SubtitleStyleContent(
|
|||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
// Bold
|
||||
StyleSettingRow(label = stringResource(R.string.subtitle_bold)) {
|
||||
StyleSettingRow(label = "Bold") {
|
||||
StyleToggleButton(
|
||||
isEnabled = subtitleStyle.bold,
|
||||
onClick = { onEvent(PlayerEvent.OnSetSubtitleBold(!subtitleStyle.bold)) }
|
||||
|
|
@ -726,7 +710,7 @@ private fun SubtitleStyleContent(
|
|||
// Advanced section
|
||||
item {
|
||||
StyleSection(
|
||||
title = stringResource(R.string.subtitle_section_advanced),
|
||||
title = "Advanced",
|
||||
icon = Icons.Default.Tune
|
||||
) {
|
||||
// Text Color
|
||||
|
|
@ -751,7 +735,7 @@ private fun SubtitleStyleContent(
|
|||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
// Outline
|
||||
StyleSettingRow(label = stringResource(R.string.subtitle_outline)) {
|
||||
StyleSettingRow(label = "Outline") {
|
||||
StyleToggleButton(
|
||||
isEnabled = subtitleStyle.outlineEnabled,
|
||||
onClick = { onEvent(PlayerEvent.OnSetSubtitleOutlineEnabled(!subtitleStyle.outlineEnabled)) }
|
||||
|
|
@ -784,7 +768,7 @@ private fun SubtitleStyleContent(
|
|||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
// Bottom Offset
|
||||
StyleSettingRow(label = stringResource(R.string.subtitle_bottom_offset)) {
|
||||
StyleSettingRow(label = "Bottom Offset") {
|
||||
StyleStepperButton(
|
||||
icon = Icons.Default.Remove,
|
||||
onClick = { onEvent(PlayerEvent.OnSetSubtitleVerticalOffset(subtitleStyle.verticalOffset - 5)) }
|
||||
|
|
@ -968,7 +952,7 @@ private fun StyleToggleButton(
|
|||
shape = CardDefaults.shape(RoundedCornerShape(10.dp))
|
||||
) {
|
||||
Text(
|
||||
text = if (isEnabled) stringResource(R.string.subtitle_on) else stringResource(R.string.subtitle_off),
|
||||
text = if (isEnabled) "On" else "Off",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = if (isEnabled) Color.White else Color.White.copy(alpha = 0.5f),
|
||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
|
|
|
|||
|
|
@ -85,18 +85,10 @@ internal fun DiscoverSection(
|
|||
val genres = selectedCatalog?.genres.orEmpty()
|
||||
var expandedPicker by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
val strTypeMovie = stringResource(R.string.type_movie)
|
||||
val strTypeSeries = stringResource(R.string.type_series)
|
||||
fun localizedTypeLabel(type: String): String = when (type.lowercase()) {
|
||||
"movie" -> strTypeMovie
|
||||
"series" -> strTypeSeries
|
||||
else -> formatAddonTypeLabel(type)
|
||||
}
|
||||
|
||||
val availableTypes = remember(uiState.discoverCatalogs) {
|
||||
uiState.discoverCatalogs.map { it.type }.distinct()
|
||||
}
|
||||
val selectedTypeLabel = localizedTypeLabel(uiState.selectedDiscoverType)
|
||||
val selectedTypeLabel = formatAddonTypeLabel(uiState.selectedDiscoverType)
|
||||
val selectedCatalogLabel = selectedCatalog?.catalogName ?: stringResource(R.string.discover_select_catalog)
|
||||
val selectedGenreLabel = uiState.selectedDiscoverGenre ?: stringResource(R.string.discover_genre_default)
|
||||
|
||||
|
|
@ -122,7 +114,7 @@ internal fun DiscoverSection(
|
|||
value = selectedTypeLabel,
|
||||
expanded = expandedPicker == "type",
|
||||
options = availableTypes.map { type ->
|
||||
val label = localizedTypeLabel(type)
|
||||
val label = formatAddonTypeLabel(type)
|
||||
DiscoverOption(label, type)
|
||||
},
|
||||
onExpandedChange = { shouldExpand ->
|
||||
|
|
@ -172,7 +164,7 @@ internal fun DiscoverSection(
|
|||
val metadataSegments = buildList {
|
||||
add(catalog.addonName)
|
||||
if (uiState.catalogTypeSuffixEnabled) {
|
||||
localizedTypeLabel(catalog.type)
|
||||
formatAddonTypeLabel(catalog.type)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.let(::add)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -328,8 +328,8 @@ fun SearchScreen(
|
|||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
EmptyScreenState(
|
||||
title = stringResource(R.string.search_start_title),
|
||||
subtitle = stringResource(R.string.search_start_subtitle),
|
||||
title = "Start Searching",
|
||||
subtitle = "Enter at least 2 characters",
|
||||
icon = Icons.Default.Search
|
||||
)
|
||||
}
|
||||
|
|
@ -396,11 +396,11 @@ fun SearchScreen(
|
|||
trimmedSubmittedQuery.length < 2 && !hasPendingUnsubmittedQuery -> {
|
||||
item {
|
||||
EmptyScreenState(
|
||||
title = stringResource(R.string.search_start_title),
|
||||
title = "Start Searching",
|
||||
subtitle = if (uiState.discoverEnabled) {
|
||||
stringResource(R.string.search_start_subtitle)
|
||||
"Enter at least 2 characters"
|
||||
} else {
|
||||
stringResource(R.string.search_start_subtitle_no_discover)
|
||||
"Discover is disabled. Enter at least 2 characters"
|
||||
},
|
||||
icon = Icons.Default.Search
|
||||
)
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ internal fun PlaybackSettingsSections(
|
|||
item(key = "general_osd_clock") {
|
||||
ToggleSettingsItem(
|
||||
icon = Icons.Default.Timer,
|
||||
title = stringResource(R.string.playback_osd_clock),
|
||||
title = "OSD Clock",
|
||||
subtitle = stringResource(R.string.playback_show_clock_sub),
|
||||
isChecked = playerSettings.osdClockEnabled,
|
||||
onCheckedChange = onSetOsdClockEnabled,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package com.nuvio.tv.ui.screens.settings
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.nuvio.tv.R
|
||||
import com.nuvio.tv.data.local.TraktAuthDataStore
|
||||
import com.nuvio.tv.data.local.TraktAuthState
|
||||
import com.nuvio.tv.data.local.TraktSettingsDataStore
|
||||
|
|
@ -52,8 +50,7 @@ class TraktViewModel @Inject constructor(
|
|||
private val traktAuthService: TraktAuthService,
|
||||
private val traktAuthDataStore: TraktAuthDataStore,
|
||||
private val traktProgressService: TraktProgressService,
|
||||
private val traktSettingsDataStore: TraktSettingsDataStore,
|
||||
@dagger.hilt.android.qualifiers.ApplicationContext private val context: Context
|
||||
private val traktSettingsDataStore: TraktSettingsDataStore
|
||||
) : ViewModel() {
|
||||
private val _uiState = MutableStateFlow(TraktUiState())
|
||||
val uiState: StateFlow<TraktUiState> = _uiState.asStateFlow()
|
||||
|
|
@ -314,7 +311,7 @@ class TraktViewModel @Inject constructor(
|
|||
_uiState.update {
|
||||
it.copy(
|
||||
isPolling = true,
|
||||
statusMessage = context.getString(R.string.trakt_waiting_approval)
|
||||
statusMessage = "Waiting for approval..."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@
|
|||
<string name="cw_upcoming">Nadchodzące</string>
|
||||
<string name="cw_next_up">Następny odcinek</string>
|
||||
<string name="cw_resume">Wznów</string>
|
||||
<string name="cw_hours_min_left">Zostało %1$dg %2$dm</string>
|
||||
<string name="cw_min_left">Zostało %1$dm</string>
|
||||
<string name="cw_almost_done">Prawie koniec</string>
|
||||
<string name="cw_airs_date">Emisja %1$s</string>
|
||||
<string name="cw_action_go_to_details">Przejdź do szczegółów</string>
|
||||
<string name="cw_action_remove">Usuń</string>
|
||||
|
|
@ -56,15 +53,7 @@
|
|||
<string name="episodes_season_actions">Akcje sezonu</string>
|
||||
|
||||
<!-- MetaDetailsScreen -->
|
||||
<string name="detail_btn_play">Odtwórz</string>
|
||||
<string name="detail_btn_resume">Wznów</string>
|
||||
<string name="detail_btn_play_episode">Odtwórz S%1$dE%2$d</string>
|
||||
<string name="detail_btn_resume_episode">Wznów S%1$dE%2$d</string>
|
||||
<string name="detail_btn_next_episode">Następny S%1$dE%2$d</string>
|
||||
<string name="detail_tab_cast">Twórcy i obsada</string>
|
||||
<string name="cast_role_creator">Twórca</string>
|
||||
<string name="cast_role_director">Reżyser</string>
|
||||
<string name="cast_role_writer">Scenarzysta</string>
|
||||
<string name="detail_tab_ratings">Oceny</string>
|
||||
<string name="detail_tab_more_like_this">Podobne</string>
|
||||
<string name="detail_section_network">Stacja</string>
|
||||
|
|
@ -114,11 +103,6 @@
|
|||
<string name="settings_debug_subtitle">Narzędzia deweloperskie i flagi funkcji.</string>
|
||||
<string name="settings_plugins_section_subtitle">Zarządzaj repozytoriami, dostawcami i stanami wtyczek.</string>
|
||||
<string name="settings_account_section_subtitle">Status konta i synchronizacji.</string>
|
||||
<string name="account_stat_addons">dodatki</string>
|
||||
<string name="account_stat_plugins">wtyczki</string>
|
||||
<string name="account_stat_library">biblioteka</string>
|
||||
<string name="account_stat_progress">postęp</string>
|
||||
<string name="account_stat_watched">obejrzane</string>
|
||||
<string name="settings_integrations_section">Integracje</string>
|
||||
<string name="settings_integrations_section_subtitle">Wybierz ustawienia TMDB lub MDBList</string>
|
||||
<string name="settings_tmdb_subtitle">Kontrolki wzbogacania metadanych</string>
|
||||
|
|
@ -135,14 +119,13 @@
|
|||
<!-- PlaybackSettingsSections -->
|
||||
<string name="playback_section_general">Ogólne</string>
|
||||
<string name="playback_section_general_desc">Podstawowe zachowanie odtwarzacza.</string>
|
||||
<string name="playback_loading_overlay">Ekan ładowania</string>
|
||||
<string name="playback_loading_overlay">Nakładka ładowania</string>
|
||||
<string name="playback_loading_overlay_sub">Pokaż ekran ładowania do pojawienia się pierwszej klatki.</string>
|
||||
<string name="playback_pause_overlay">Ekran pauzy</string>
|
||||
<string name="playback_pause_overlay_sub">Pokaż ekran ze szczegółami po 5 sekundach pauzy.</string>
|
||||
<string name="playback_pause_overlay">Nakładka pauzy</string>
|
||||
<string name="playback_pause_overlay_sub">Pokaż nakładkę ze szczegółami po 5 sekundach pauzy.</string>
|
||||
<string name="playback_show_clock_sub">Pokaż aktualny czas i czas zakończenia podczas wyświetlania kontrolek.</string>
|
||||
<string name="playback_osd_clock">Zegar OSD</string>
|
||||
<string name="playback_skip_intro">Pomiń intro</string>
|
||||
<string name="playback_skip_intro_sub">Używaj introdb.app do wykrywania intro i podsumowań.</string>
|
||||
<string name="playback_skip_intro_sub">Używaj introdb.app do wykrywania intro i recap.</string>
|
||||
<string name="playback_auto_frame_rate">Auto częstotliwość odświeżania</string>
|
||||
<string name="playback_section_player">Odtwarzacz i wybór źródła</string>
|
||||
<string name="playback_section_player_desc">Preferencje odtwarzacza, auto-play i filtrowanie źródeł.</string>
|
||||
|
|
@ -237,7 +220,7 @@
|
|||
<string name="autoplay_next_episode_sub">Automatycznie rozpocznij następny odcinek gdy pojawi się monit.</string>
|
||||
<string name="autoplay_threshold_pct">Procent</string>
|
||||
<string name="autoplay_threshold_min">Minut przed końcem</string>
|
||||
<string name="autoplay_threshold_mode">Określanie progu następnego odcinka</string>
|
||||
<string name="autoplay_threshold_mode">Tryb progu następnego odcinka</string>
|
||||
<string name="autoplay_threshold_pct_title">Próg procentowy</string>
|
||||
<string name="autoplay_threshold_pct_sub">Zapasowy gdy brak znacznika outro.</string>
|
||||
<string name="autoplay_threshold_min_title">Próg minutowy</string>
|
||||
|
|
@ -308,15 +291,15 @@
|
|||
<string name="layout_trailer_button_sub">Pokaż przycisk zwiastuna na stronie szczegółów (tylko gdy zwiastun jest dostępny).</string>
|
||||
<string name="layout_prefer_external_meta">Preferuj metadane z zewnętrznego dodatku</string>
|
||||
<string name="layout_prefer_external_meta_sub">Używaj metadanych z zewnętrznego dodatku zamiast dodatku katalogowego.</string>
|
||||
<string name="layout_section_focused">Zaznaczony plakat</string>
|
||||
<string name="layout_section_focused_desc">Zaawansowane zachowanie zaznaczonych kart plakatów.</string>
|
||||
<string name="layout_expand_poster">Rozwiń zaznaczony plakat do tła</string>
|
||||
<string name="layout_expand_poster_sub">Rozwiń zaznaczony plakat po opóźnieniu bezczynności.</string>
|
||||
<string name="layout_section_focused">Skupiony plakat</string>
|
||||
<string name="layout_section_focused_desc">Zaawansowane zachowanie skupionych kart plakatów.</string>
|
||||
<string name="layout_expand_poster">Rozwiń skupiony plakat do tła</string>
|
||||
<string name="layout_expand_poster_sub">Rozwiń skupiony plakat po opóźnieniu bezczynności.</string>
|
||||
<string name="layout_expand_delay">Opóźnienie rozwinięcia tła</string>
|
||||
<string name="layout_expand_delay_sub">Jak długo czekać przed rozwinięciem zaznaczonych kart.</string>
|
||||
<string name="layout_expand_delay_sub">Jak długo czekać przed rozwinięciem skupionych kart.</string>
|
||||
<string name="layout_autoplay_trailer">Auto-odtwarzanie zwiastuna</string>
|
||||
<string name="layout_autoplay_trailer_expanded">Auto-odtwarzanie zwiastuna w rozszerzonej karcie</string>
|
||||
<string name="layout_autoplay_trailer_sub">Odtwarzaj podgląd zwiastuna dla zaznaczonej treści gdy dostępny.</string>
|
||||
<string name="layout_autoplay_trailer_sub">Odtwarzaj podgląd zwiastuna dla skupionej treści gdy dostępny.</string>
|
||||
<string name="layout_autoplay_trailer_expanded_sub">Odtwarzaj zwiastun w rozszerzonym tle gdy dostępny.</string>
|
||||
<string name="layout_trailer_muted">Odtwarzaj zwiastun bez dźwięku</string>
|
||||
<string name="layout_trailer_muted_sub_preview">Wycisz audio zwiastuna podczas podglądu auto-play.</string>
|
||||
|
|
@ -403,10 +386,6 @@
|
|||
<string name="trakt_connected_as">Połączono jako %1$s</string>
|
||||
<string name="trakt_account_login">Logowanie do konta</string>
|
||||
<string name="trakt_awaiting_instruction">Przejdź na trakt.tv/activate i wprowadź ten kod:</string>
|
||||
<string name="trakt_waiting_approval">Oczekiwanie na zatwierdzenie…</string>
|
||||
<string name="qr_login_approved">Logowanie zatwierdzone. Trwa kończenie…</string>
|
||||
<string name="qr_login_pending">Oczekiwanie na zatwierdzenie na telefonie…</string>
|
||||
<string name="qr_login_expired">Kod QR wygasł. Wygeneruj nowy.</string>
|
||||
<string name="trakt_code_expires">Kod wygasa za %1$s</string>
|
||||
<string name="trakt_token_refreshes">Token dostępu Trakt odświeży się za %1$s</string>
|
||||
<string name="trakt_login_instruction">Naciśnij Zaloguj, aby rozpocząć uwierzytelnianie urządzenia Trakt. Tutaj pojawi się kod QR.</string>
|
||||
|
|
@ -552,14 +531,6 @@
|
|||
<string name="episodes_panel_reload">Odśwież</string>
|
||||
<string name="episodes_panel_no_streams">Nie znaleziono źródeł</string>
|
||||
<string name="episodes_panel_no_episodes">Brak dostępnych odcinków</string>
|
||||
<string name="episodes_panel_title">Odcinki</string>
|
||||
<string name="episodes_panel_streams_title">Strumienie</string>
|
||||
<string name="player_speed_normal">Normalna</string>
|
||||
<string name="player_aspect_fit">Dopasuj (oryginalny)</string>
|
||||
<string name="player_aspect_stretch">Rozciągnij</string>
|
||||
<string name="player_aspect_fit_width">Dopasuj szerokość</string>
|
||||
<string name="player_aspect_fit_height">Dopasuj wysokość</string>
|
||||
<string name="player_aspect_crop">Przytnij</string>
|
||||
|
||||
<!-- AudioDialog -->
|
||||
<string name="audio_dialog_title">Dźwięk</string>
|
||||
|
|
@ -572,21 +543,6 @@
|
|||
<string name="subtitle_text_color">Kolor tekstu</string>
|
||||
<string name="subtitle_outline_color">Kolor obrysu</string>
|
||||
<string name="subtitle_reset_defaults">Przywróć domyślne</string>
|
||||
<string name="subtitle_tab_builtin">Wbudowane</string>
|
||||
<string name="subtitle_tab_addons">Dodatki</string>
|
||||
<string name="subtitle_tab_languages">Języki</string>
|
||||
<string name="subtitle_tab_style">Styl</string>
|
||||
<string name="subtitle_tab_delay">Opóźnienie</string>
|
||||
<string name="subtitle_none">Brak</string>
|
||||
<string name="subtitle_all">Wszystkie</string>
|
||||
<string name="subtitle_section_core">Podstawowe</string>
|
||||
<string name="subtitle_section_advanced">Zaawansowane</string>
|
||||
<string name="subtitle_font_size">Rozmiar czcionki</string>
|
||||
<string name="subtitle_bold">Pogrubienie</string>
|
||||
<string name="subtitle_outline">Obramowanie</string>
|
||||
<string name="subtitle_bottom_offset">Przesunięcie od dołu</string>
|
||||
<string name="subtitle_on">Wł.</string>
|
||||
<string name="subtitle_off">Wył.</string>
|
||||
<string name="subtitle_style_title">Styl napisów</string>
|
||||
<string name="subtitle_style_color">Kolor</string>
|
||||
<string name="subtitle_style_reset">Resetuj</string>
|
||||
|
|
@ -604,9 +560,6 @@
|
|||
<!-- SearchScreen -->
|
||||
<string name="search_keyboard_hint">Naciśnij Gotowe na klawiaturze, aby wyszukać</string>
|
||||
<string name="search_placeholder">Szukaj filmów i seriali</string>
|
||||
<string name="search_start_title">Zacznij szukać</string>
|
||||
<string name="search_start_subtitle">Wpisz co najmniej 2 znaki</string>
|
||||
<string name="search_start_subtitle_no_discover">Odkrywanie jest wyłączone. Wpisz co najmniej 2 znaki</string>
|
||||
|
||||
<!-- LibraryScreen -->
|
||||
<string name="library_syncing">Synchronizowanie biblioteki Trakt\u2026</string>
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@
|
|||
<string name="cw_upcoming">Upcoming</string>
|
||||
<string name="cw_next_up">Next Up</string>
|
||||
<string name="cw_resume">Resume</string>
|
||||
<string name="cw_hours_min_left">%1$dh %2$dm left</string>
|
||||
<string name="cw_min_left">%1$dm left</string>
|
||||
<string name="cw_almost_done">Almost done</string>
|
||||
<string name="cw_airs_date">Airs %1$s</string>
|
||||
<string name="cw_action_go_to_details">Go to details</string>
|
||||
<string name="cw_action_remove">Remove</string>
|
||||
|
|
@ -58,15 +55,7 @@
|
|||
<string name="episodes_season_actions">Season actions</string>
|
||||
|
||||
<!-- MetaDetailsScreen -->
|
||||
<string name="detail_btn_play">Play</string>
|
||||
<string name="detail_btn_resume">Resume</string>
|
||||
<string name="detail_btn_play_episode">Play S%1$dE%2$d</string>
|
||||
<string name="detail_btn_resume_episode">Resume S%1$dE%2$d</string>
|
||||
<string name="detail_btn_next_episode">Next S%1$dE%2$d</string>
|
||||
<string name="detail_tab_cast">Creator and Cast</string>
|
||||
<string name="cast_role_creator">Creator</string>
|
||||
<string name="cast_role_director">Director</string>
|
||||
<string name="cast_role_writer">Writer</string>
|
||||
<string name="detail_tab_ratings">Ratings</string>
|
||||
<string name="detail_tab_more_like_this">More like this</string>
|
||||
<string name="detail_section_network">Network</string>
|
||||
|
|
@ -116,11 +105,6 @@
|
|||
<string name="settings_debug_subtitle">Developer tools and feature flags.</string>
|
||||
<string name="settings_plugins_section_subtitle">Manage repositories, providers, and plugin states.</string>
|
||||
<string name="settings_account_section_subtitle">Account and sync status.</string>
|
||||
<string name="account_stat_addons">addons</string>
|
||||
<string name="account_stat_plugins">plugins</string>
|
||||
<string name="account_stat_library">library</string>
|
||||
<string name="account_stat_progress">progress</string>
|
||||
<string name="account_stat_watched">watched</string>
|
||||
<string name="settings_integrations_section">Integrations</string>
|
||||
<string name="settings_integrations_section_subtitle">Choose TMDB or MDBList settings</string>
|
||||
<string name="settings_tmdb_subtitle">Metadata enrichment controls</string>
|
||||
|
|
@ -142,7 +126,6 @@
|
|||
<string name="playback_pause_overlay">Pause Overlay</string>
|
||||
<string name="playback_pause_overlay_sub">Show details overlay after 5 seconds while paused.</string>
|
||||
<string name="playback_show_clock_sub">Show current time and end time while controls are visible.</string>
|
||||
<string name="playback_osd_clock">OSD Clock</string>
|
||||
<string name="playback_skip_intro">Skip Intro</string>
|
||||
<string name="playback_skip_intro_sub">Use introdb.app to detect intros and recaps.</string>
|
||||
<string name="playback_auto_frame_rate">Auto Frame Rate</string>
|
||||
|
|
@ -405,10 +388,6 @@
|
|||
<string name="trakt_connected_as">Connected as %1$s</string>
|
||||
<string name="trakt_account_login">Account Login</string>
|
||||
<string name="trakt_awaiting_instruction">Go to trakt.tv/activate and enter this code:</string>
|
||||
<string name="trakt_waiting_approval">Waiting for approval…</string>
|
||||
<string name="qr_login_approved">Login approved. Finishing sign in…</string>
|
||||
<string name="qr_login_pending">Waiting for approval on your phone…</string>
|
||||
<string name="qr_login_expired">QR login expired. Generate a new code.</string>
|
||||
<string name="trakt_code_expires">Code expires in %1$s</string>
|
||||
<string name="trakt_token_refreshes">Trakt access token refreshes in %1$s</string>
|
||||
<string name="trakt_login_instruction">Press Login to start Trakt device authentication. A QR code will appear here.</string>
|
||||
|
|
@ -555,14 +534,6 @@
|
|||
<string name="episodes_panel_reload">Reload</string>
|
||||
<string name="episodes_panel_no_streams">No streams found</string>
|
||||
<string name="episodes_panel_no_episodes">No episodes available</string>
|
||||
<string name="episodes_panel_title">Episodes</string>
|
||||
<string name="episodes_panel_streams_title">Streams</string>
|
||||
<string name="player_speed_normal">Normal</string>
|
||||
<string name="player_aspect_fit">Fit (Original)</string>
|
||||
<string name="player_aspect_stretch">Stretch</string>
|
||||
<string name="player_aspect_fit_width">Fit Width</string>
|
||||
<string name="player_aspect_fit_height">Fit Height</string>
|
||||
<string name="player_aspect_crop">Crop</string>
|
||||
|
||||
<!-- AudioDialog -->
|
||||
<string name="audio_dialog_title">Audio</string>
|
||||
|
|
@ -575,21 +546,6 @@
|
|||
<string name="subtitle_text_color">Text Color</string>
|
||||
<string name="subtitle_outline_color">Outline Color</string>
|
||||
<string name="subtitle_reset_defaults">Reset Defaults</string>
|
||||
<string name="subtitle_tab_builtin">Built-in</string>
|
||||
<string name="subtitle_tab_addons">Addons</string>
|
||||
<string name="subtitle_tab_languages">Languages</string>
|
||||
<string name="subtitle_tab_style">Style</string>
|
||||
<string name="subtitle_tab_delay">Delay</string>
|
||||
<string name="subtitle_none">None</string>
|
||||
<string name="subtitle_all">All</string>
|
||||
<string name="subtitle_section_core">Core</string>
|
||||
<string name="subtitle_section_advanced">Advanced</string>
|
||||
<string name="subtitle_font_size">Font Size</string>
|
||||
<string name="subtitle_bold">Bold</string>
|
||||
<string name="subtitle_outline">Outline</string>
|
||||
<string name="subtitle_bottom_offset">Bottom Offset</string>
|
||||
<string name="subtitle_on">On</string>
|
||||
<string name="subtitle_off">Off</string>
|
||||
<string name="subtitle_style_title">Subtitle Style</string>
|
||||
<string name="subtitle_style_color">Color</string>
|
||||
<string name="subtitle_style_reset">Reset</string>
|
||||
|
|
@ -607,9 +563,6 @@
|
|||
<!-- SearchScreen -->
|
||||
<string name="search_keyboard_hint">Press Done on the keyboard to search</string>
|
||||
<string name="search_placeholder">Search movies & series</string>
|
||||
<string name="search_start_title">Start Searching</string>
|
||||
<string name="search_start_subtitle">Enter at least 2 characters</string>
|
||||
<string name="search_start_subtitle_no_discover">Discover is disabled. Enter at least 2 characters</string>
|
||||
|
||||
<!-- LibraryScreen -->
|
||||
<string name="library_syncing">Syncing Trakt library\u2026</string>
|
||||
|
|
|
|||
Loading…
Reference in a new issue