mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-16 23:12:12 +00:00
Merge branch 'cmp-rewrite' of https://github.com/NuvioMedia/NuvioMobile into cmp-rewrite
This commit is contained in:
commit
37203d1fc1
6 changed files with 1333 additions and 22 deletions
|
|
@ -1,13 +1,14 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<locale android:name="cs"/>
|
||||||
<locale android:name="en"/>
|
<locale android:name="en"/>
|
||||||
<locale android:name="fr"/>
|
<locale android:name="fr"/>
|
||||||
<locale android:name="es"/>
|
|
||||||
<locale android:name="pt"/>
|
|
||||||
<locale android:name="tr"/>
|
|
||||||
<locale android:name="it"/>
|
|
||||||
<locale android:name="el"/>
|
|
||||||
<locale android:name="pl"/>
|
|
||||||
<locale android:name="de"/>
|
<locale android:name="de"/>
|
||||||
<locale android:name="cs"/>
|
<locale android:name="el"/>
|
||||||
|
<locale android:name="id"/>
|
||||||
|
<locale android:name="it"/>
|
||||||
|
<locale android:name="pl"/>
|
||||||
|
<locale android:name="pt"/>
|
||||||
|
<locale android:name="es"/>
|
||||||
|
<locale android:name="tr"/>
|
||||||
</locale-config>
|
</locale-config>
|
||||||
|
|
|
||||||
|
|
@ -720,7 +720,7 @@
|
||||||
<string name="settings_playback_threshold_mode_percentage">Pourcentage</string>
|
<string name="settings_playback_threshold_mode_percentage">Pourcentage</string>
|
||||||
<string name="settings_playback_threshold_percentage">Pourcentage de seuil</string>
|
<string name="settings_playback_threshold_percentage">Pourcentage de seuil</string>
|
||||||
<string name="settings_playback_threshold_percentage_description">Afficher la carte de l'épisode suivant lorsque la lecture atteint ce pourcentage.</string>
|
<string name="settings_playback_threshold_percentage_description">Afficher la carte de l'épisode suivant lorsque la lecture atteint ce pourcentage.</string>
|
||||||
<string name="settings_playback_threshold_percentage_value">%1$s%</string>
|
<string name="settings_playback_threshold_percentage_value">%1$s %</string>
|
||||||
<string name="settings_playback_timeout_instant">Instantané</string>
|
<string name="settings_playback_timeout_instant">Instantané</string>
|
||||||
<string name="settings_playback_timeout_seconds">%1$ss</string>
|
<string name="settings_playback_timeout_seconds">%1$ss</string>
|
||||||
<string name="settings_playback_timeout_unlimited">Illimité</string>
|
<string name="settings_playback_timeout_unlimited">Illimité</string>
|
||||||
|
|
@ -1017,7 +1017,7 @@
|
||||||
<string name="streams_no_direct_link">Aucun lien direct du stream disponible</string>
|
<string name="streams_no_direct_link">Aucun lien direct du stream disponible</string>
|
||||||
<string name="streams_no_metadata">Aucune métadonnée disponible</string>
|
<string name="streams_no_metadata">Aucune métadonnée disponible</string>
|
||||||
<string name="streams_refresh">Actualiser les streams</string>
|
<string name="streams_refresh">Actualiser les streams</string>
|
||||||
<string name="streams_resume_from_percent">Reprendre depuis %1$d%</string>
|
<string name="streams_resume_from_percent">Reprendre depuis %1$d %</string>
|
||||||
<string name="streams_resume_from_time">Reprendre depuis %1$s</string>
|
<string name="streams_resume_from_time">Reprendre depuis %1$s</string>
|
||||||
<string name="streams_size">TAILLE %1$s</string>
|
<string name="streams_size">TAILLE %1$s</string>
|
||||||
<string name="trailer_close">Fermer la bande-annonce</string>
|
<string name="trailer_close">Fermer la bande-annonce</string>
|
||||||
|
|
@ -1027,7 +1027,7 @@
|
||||||
<string name="updates_asset_line">%1$s • %2$s</string>
|
<string name="updates_asset_line">%1$s • %2$s</string>
|
||||||
<string name="updates_check_failed">Échec de la vérification des mises à jour</string>
|
<string name="updates_check_failed">Échec de la vérification des mises à jour</string>
|
||||||
<string name="updates_download_failed">Échec du téléchargement</string>
|
<string name="updates_download_failed">Échec du téléchargement</string>
|
||||||
<string name="updates_downloading_progress">Téléchargement %1$d%%</string>
|
<string name="updates_downloading_progress">Téléchargement %1$d %</string>
|
||||||
<string name="updates_install_failed">Impossible de démarrer l'installation</string>
|
<string name="updates_install_failed">Impossible de démarrer l'installation</string>
|
||||||
<string name="updates_latest_version">Vous utilisez la version la plus récente.</string>
|
<string name="updates_latest_version">Vous utilisez la version la plus récente.</string>
|
||||||
<string name="updates_message_allow_installs">Activez l'installation d'applications pour Nuvio puis revenez pour continuer.</string>
|
<string name="updates_message_allow_installs">Activez l'installation d'applications pour Nuvio puis revenez pour continuer.</string>
|
||||||
|
|
|
||||||
1277
composeApp/src/commonMain/composeResources/values-id/strings.xml
Normal file
1277
composeApp/src/commonMain/composeResources/values-id/strings.xml
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -531,6 +531,7 @@ private fun MainAppContent(
|
||||||
val hapticFeedback = LocalHapticFeedback.current
|
val hapticFeedback = LocalHapticFeedback.current
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
var selectedTab by rememberSaveable { mutableStateOf(AppScreenTab.Home) }
|
var selectedTab by rememberSaveable { mutableStateOf(AppScreenTab.Home) }
|
||||||
|
var searchFocusRequestCount by remember { mutableStateOf(0) }
|
||||||
val currentBackStackEntry by navController.currentBackStackEntryAsState()
|
val currentBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
val nativeRequestedTab by remember { NativeTabBridge.requestedTab }.collectAsStateWithLifecycle()
|
val nativeRequestedTab by remember { NativeTabBridge.requestedTab }.collectAsStateWithLifecycle()
|
||||||
val liquidGlassNativeTabBarEnabled by remember {
|
val liquidGlassNativeTabBarEnabled by remember {
|
||||||
|
|
@ -597,6 +598,9 @@ private fun MainAppContent(
|
||||||
|
|
||||||
LaunchedEffect(selectedTab) {
|
LaunchedEffect(selectedTab) {
|
||||||
NativeTabBridge.publishSelectedTab(selectedTab.toNativeNavigationTab())
|
NativeTabBridge.publishSelectedTab(selectedTab.toNativeNavigationTab())
|
||||||
|
if (selectedTab != AppScreenTab.Search) {
|
||||||
|
searchFocusRequestCount = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DisposableEffect(
|
DisposableEffect(
|
||||||
|
|
@ -1049,7 +1053,13 @@ private fun MainAppContent(
|
||||||
)
|
)
|
||||||
NavItem(
|
NavItem(
|
||||||
selected = selectedTab == AppScreenTab.Search,
|
selected = selectedTab == AppScreenTab.Search,
|
||||||
onClick = { selectedTab = AppScreenTab.Search },
|
onClick = {
|
||||||
|
if (selectedTab == AppScreenTab.Search) {
|
||||||
|
searchFocusRequestCount++
|
||||||
|
} else {
|
||||||
|
selectedTab = AppScreenTab.Search
|
||||||
|
}
|
||||||
|
},
|
||||||
icon = Res.drawable.sidebar_search,
|
icon = Res.drawable.sidebar_search,
|
||||||
contentDescription = stringResource(Res.string.compose_nav_search),
|
contentDescription = stringResource(Res.string.compose_nav_search),
|
||||||
)
|
)
|
||||||
|
|
@ -1083,6 +1093,7 @@ private fun MainAppContent(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(innerPadding),
|
.padding(innerPadding),
|
||||||
selectedTab = selectedTab,
|
selectedTab = selectedTab,
|
||||||
|
searchFocusRequestCount = searchFocusRequestCount,
|
||||||
animateHomeCollectionGifs = tabsRouteActive,
|
animateHomeCollectionGifs = tabsRouteActive,
|
||||||
onCatalogClick = onCatalogClick,
|
onCatalogClick = onCatalogClick,
|
||||||
onPosterClick = { meta ->
|
onPosterClick = { meta ->
|
||||||
|
|
@ -1137,7 +1148,13 @@ private fun MainAppContent(
|
||||||
if (isTabletLayout && !useNativeBottomTabs) {
|
if (isTabletLayout && !useNativeBottomTabs) {
|
||||||
TabletFloatingTopBar(
|
TabletFloatingTopBar(
|
||||||
selectedTab = selectedTab,
|
selectedTab = selectedTab,
|
||||||
onTabSelected = { selectedTab = it },
|
onTabSelected = { tab ->
|
||||||
|
if (tab == AppScreenTab.Search && selectedTab == AppScreenTab.Search) {
|
||||||
|
searchFocusRequestCount++
|
||||||
|
} else {
|
||||||
|
selectedTab = tab
|
||||||
|
}
|
||||||
|
},
|
||||||
onProfileSelected = onProfileSelected,
|
onProfileSelected = onProfileSelected,
|
||||||
onAddProfileRequested = onSwitchProfile,
|
onAddProfileRequested = onSwitchProfile,
|
||||||
)
|
)
|
||||||
|
|
@ -2085,6 +2102,7 @@ private fun rememberGuardedPopBackStack(
|
||||||
private fun AppTabHost(
|
private fun AppTabHost(
|
||||||
selectedTab: AppScreenTab,
|
selectedTab: AppScreenTab,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
searchFocusRequestCount: Int = 0,
|
||||||
animateHomeCollectionGifs: Boolean = true,
|
animateHomeCollectionGifs: Boolean = true,
|
||||||
onCatalogClick: ((HomeCatalogSection) -> Unit)? = null,
|
onCatalogClick: ((HomeCatalogSection) -> Unit)? = null,
|
||||||
onPosterClick: ((MetaPreview) -> Unit)? = null,
|
onPosterClick: ((MetaPreview) -> Unit)? = null,
|
||||||
|
|
@ -2132,6 +2150,7 @@ private fun AppTabHost(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
onPosterClick = onPosterClick,
|
onPosterClick = onPosterClick,
|
||||||
onPosterLongClick = onPosterLongClick,
|
onPosterLongClick = onPosterLongClick,
|
||||||
|
searchFocusRequestCount = searchFocusRequestCount,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
|
@ -80,7 +82,16 @@ fun SearchScreen(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onPosterClick: ((MetaPreview) -> Unit)? = null,
|
onPosterClick: ((MetaPreview) -> Unit)? = null,
|
||||||
onPosterLongClick: ((MetaPreview) -> Unit)? = null,
|
onPosterLongClick: ((MetaPreview) -> Unit)? = null,
|
||||||
|
searchFocusRequestCount: Int = 0,
|
||||||
) {
|
) {
|
||||||
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
|
LaunchedEffect(searchFocusRequestCount) {
|
||||||
|
if (searchFocusRequestCount > 0) {
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
AddonRepository.initialize()
|
AddonRepository.initialize()
|
||||||
WatchedRepository.ensureLoaded()
|
WatchedRepository.ensureLoaded()
|
||||||
|
|
@ -240,6 +251,7 @@ fun SearchScreen(
|
||||||
value = query,
|
value = query,
|
||||||
onValueChange = { query = it },
|
onValueChange = { query = it },
|
||||||
placeholder = stringResource(Res.string.compose_search_placeholder),
|
placeholder = stringResource(Res.string.compose_search_placeholder),
|
||||||
|
modifier = Modifier.focusRequester(focusRequester),
|
||||||
trailingContent = if (query.isNotBlank()) {
|
trailingContent = if (query.isNotBlank()) {
|
||||||
{
|
{
|
||||||
IconButton(onClick = { query = "" }) {
|
IconButton(onClick = { query = "" }) {
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,34 @@
|
||||||
package com.nuvio.app.features.settings
|
package com.nuvio.app.features.settings
|
||||||
|
|
||||||
import nuvio.composeapp.generated.resources.Res
|
import nuvio.composeapp.generated.resources.Res
|
||||||
|
import nuvio.composeapp.generated.resources.lang_czech
|
||||||
import nuvio.composeapp.generated.resources.lang_english
|
import nuvio.composeapp.generated.resources.lang_english
|
||||||
import nuvio.composeapp.generated.resources.lang_french
|
import nuvio.composeapp.generated.resources.lang_french
|
||||||
import nuvio.composeapp.generated.resources.lang_german
|
import nuvio.composeapp.generated.resources.lang_german
|
||||||
import nuvio.composeapp.generated.resources.lang_spanish
|
|
||||||
import nuvio.composeapp.generated.resources.lang_portuguese_portugal
|
|
||||||
import nuvio.composeapp.generated.resources.lang_turkish
|
|
||||||
import nuvio.composeapp.generated.resources.lang_italian
|
|
||||||
import nuvio.composeapp.generated.resources.lang_greek
|
import nuvio.composeapp.generated.resources.lang_greek
|
||||||
|
import nuvio.composeapp.generated.resources.lang_indonesian
|
||||||
|
import nuvio.composeapp.generated.resources.lang_italian
|
||||||
import nuvio.composeapp.generated.resources.lang_polish
|
import nuvio.composeapp.generated.resources.lang_polish
|
||||||
import nuvio.composeapp.generated.resources.lang_czech
|
import nuvio.composeapp.generated.resources.lang_portuguese_portugal
|
||||||
|
import nuvio.composeapp.generated.resources.lang_spanish
|
||||||
|
import nuvio.composeapp.generated.resources.lang_turkish
|
||||||
import org.jetbrains.compose.resources.StringResource
|
import org.jetbrains.compose.resources.StringResource
|
||||||
|
|
||||||
enum class AppLanguage(
|
enum class AppLanguage(
|
||||||
val code: String,
|
val code: String,
|
||||||
val labelRes: StringResource,
|
val labelRes: StringResource,
|
||||||
) {
|
) {
|
||||||
|
CZECH("cs", Res.string.lang_czech),
|
||||||
ENGLISH("en", Res.string.lang_english),
|
ENGLISH("en", Res.string.lang_english),
|
||||||
FRENCH("fr", Res.string.lang_french),
|
FRENCH("fr", Res.string.lang_french),
|
||||||
GERMAN("de", Res.string.lang_german),
|
GERMAN("de", Res.string.lang_german),
|
||||||
SPANISH("es", Res.string.lang_spanish),
|
|
||||||
PORTUGUESE("pt", Res.string.lang_portuguese_portugal),
|
|
||||||
TURKISH("tr", Res.string.lang_turkish),
|
|
||||||
ITALIAN("it", Res.string.lang_italian),
|
|
||||||
GREEK("el", Res.string.lang_greek),
|
GREEK("el", Res.string.lang_greek),
|
||||||
|
INDONESIAN("id", Res.string.lang_indonesian),
|
||||||
|
ITALIAN("it", Res.string.lang_italian),
|
||||||
POLISH("pl", Res.string.lang_polish),
|
POLISH("pl", Res.string.lang_polish),
|
||||||
CZECH("cs", Res.string.lang_czech),
|
PORTUGUESE("pt", Res.string.lang_portuguese_portugal),
|
||||||
|
SPANISH("es", Res.string.lang_spanish),
|
||||||
|
TURKISH("tr", Res.string.lang_turkish),
|
||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue