mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-20 16:22:04 +00:00
updated remaining contents for localization
This commit is contained in:
parent
9924d26ff6
commit
bbdd4c0504
7 changed files with 215 additions and 106 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
View,
|
View,
|
||||||
Text,
|
Text,
|
||||||
|
|
@ -70,6 +71,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
onClose,
|
onClose,
|
||||||
castMember,
|
castMember,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||||
const [personDetails, setPersonDetails] = useState<PersonDetails | null>(null);
|
const [personDetails, setPersonDetails] = useState<PersonDetails | null>(null);
|
||||||
|
|
@ -82,14 +84,14 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
if (visible && castMember) {
|
if (visible && castMember) {
|
||||||
modalOpacity.value = withTiming(1, { duration: 250 });
|
modalOpacity.value = withTiming(1, { duration: 250 });
|
||||||
modalScale.value = withSpring(1, { damping: 20, stiffness: 200 });
|
modalScale.value = withSpring(1, { damping: 20, stiffness: 200 });
|
||||||
|
|
||||||
if (!hasFetched || personDetails?.id !== castMember.id) {
|
if (!hasFetched || personDetails?.id !== castMember.id) {
|
||||||
fetchPersonDetails();
|
fetchPersonDetails();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
modalOpacity.value = withTiming(0, { duration: 200 });
|
modalOpacity.value = withTiming(0, { duration: 200 });
|
||||||
modalScale.value = withTiming(0.9, { duration: 200 });
|
modalScale.value = withTiming(0.9, { duration: 200 });
|
||||||
|
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
setHasFetched(false);
|
setHasFetched(false);
|
||||||
setPersonDetails(null);
|
setPersonDetails(null);
|
||||||
|
|
@ -99,7 +101,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
|
|
||||||
const fetchPersonDetails = async () => {
|
const fetchPersonDetails = async () => {
|
||||||
if (!castMember || loading) return;
|
if (!castMember || loading) return;
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const details = await tmdbService.getPersonDetails(castMember.id);
|
const details = await tmdbService.getPersonDetails(castMember.id);
|
||||||
|
|
@ -150,11 +152,11 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
const birthDate = new Date(birthday);
|
const birthDate = new Date(birthday);
|
||||||
let age = today.getFullYear() - birthDate.getFullYear();
|
let age = today.getFullYear() - birthDate.getFullYear();
|
||||||
const monthDiff = today.getMonth() - birthDate.getMonth();
|
const monthDiff = today.getMonth() - birthDate.getMonth();
|
||||||
|
|
||||||
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||||||
age--;
|
age--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return age;
|
return age;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -196,8 +198,8 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
height: MODAL_HEIGHT,
|
height: MODAL_HEIGHT,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderRadius: isTablet ? 32 : 24,
|
borderRadius: isTablet ? 32 : 24,
|
||||||
backgroundColor: Platform.OS === 'android'
|
backgroundColor: Platform.OS === 'android'
|
||||||
? 'rgba(20, 20, 20, 0.95)'
|
? 'rgba(20, 20, 20, 0.95)'
|
||||||
: 'transparent',
|
: 'transparent',
|
||||||
},
|
},
|
||||||
modalStyle,
|
modalStyle,
|
||||||
|
|
@ -280,7 +282,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|
@ -296,7 +298,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
fontSize: isTablet ? 14 : 13,
|
fontSize: isTablet ? 14 : 13,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
}} numberOfLines={2}>
|
}} numberOfLines={2}>
|
||||||
as {castMember.character}
|
{t('cast.as_character', { character: castMember.character })}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -336,7 +338,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
}}>
|
}}>
|
||||||
Loading details...
|
{t('cast.loading_details')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -352,8 +354,8 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
borderColor: 'rgba(255, 255, 255, 0.06)',
|
borderColor: 'rgba(255, 255, 255, 0.06)',
|
||||||
}}>
|
}}>
|
||||||
{personDetails?.birthday && (
|
{personDetails?.birthday && (
|
||||||
<View style={{
|
<View style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: personDetails?.place_of_birth ? 10 : 0
|
marginBottom: personDetails?.place_of_birth ? 10 : 0
|
||||||
}}>
|
}}>
|
||||||
|
|
@ -369,7 +371,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
}}>
|
}}>
|
||||||
{calculateAge(personDetails.birthday)} years old
|
{t('cast.years_old', { age: calculateAge(personDetails.birthday) })}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
@ -389,7 +391,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
}}>
|
}}>
|
||||||
Born in {personDetails.place_of_birth}
|
{t('cast.born_in', { place: personDetails.place_of_birth })}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
@ -420,7 +422,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
letterSpacing: 0.3,
|
letterSpacing: 0.3,
|
||||||
}}>
|
}}>
|
||||||
View Filmography
|
{t('cast.view_filmography')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
|
@ -454,7 +456,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
letterSpacing: 0.5,
|
letterSpacing: 0.5,
|
||||||
}}>
|
}}>
|
||||||
Also Known As
|
{t('cast.also_known_as')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
color: 'rgba(255, 255, 255, 0.7)',
|
color: 'rgba(255, 255, 255, 0.7)',
|
||||||
|
|
@ -480,7 +482,7 @@ export const CastDetailsModal: React.FC<CastDetailsModalProps> = ({
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
}}>
|
}}>
|
||||||
No additional information available
|
{t('cast.no_info_available')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"try_different": "جرب تصنيفاً أو كتالوجاً مختلفاً",
|
"try_different": "جرب تصنيفاً أو كتالوجاً مختلفاً",
|
||||||
"select_catalog_desc": "اختر كتالوجاً للاكتشاف",
|
"select_catalog_desc": "اختر كتالوجاً للاكتشاف",
|
||||||
"tap_catalog_desc": "اضغط على الكتالوج أعلاه للبدء",
|
"tap_catalog_desc": "اضغط على الكتالوج أعلاه للبدء",
|
||||||
"search_placeholder": "ابحث عن أفلام، مسلسلات...",
|
"placeholder": "ابحث عن أفلام، مسلسلات...",
|
||||||
"keep_typing": "استمر في الكتابة...",
|
"keep_typing": "استمر في الكتابة...",
|
||||||
"type_characters": "اكتب حرفين على الأقل للبحث",
|
"type_characters": "اكتب حرفين على الأقل للبحث",
|
||||||
"no_results": "لم يتم العثور على نتائج",
|
"no_results": "لم يتم العثور على نتائج",
|
||||||
|
|
@ -279,7 +279,28 @@
|
||||||
"born_in": "وُلد في {{place}}",
|
"born_in": "وُلد في {{place}}",
|
||||||
"filmography": "قائمة الأفلام",
|
"filmography": "قائمة الأفلام",
|
||||||
"also_known_as": "يُعرف أيضاً بـ",
|
"also_known_as": "يُعرف أيضاً بـ",
|
||||||
"no_info_available": "لا توجد معلومات إضافية متاحة"
|
"no_info_available": "لا توجد معلومات إضافية متاحة",
|
||||||
|
"as_character": "as {{character}}",
|
||||||
|
"loading_details": "Loading details...",
|
||||||
|
"years_old": "{{age}} years old",
|
||||||
|
"view_filmography": "View Filmography",
|
||||||
|
"filter": "Filter",
|
||||||
|
"sort_by": "Sort By",
|
||||||
|
"sort_popular": "Popular",
|
||||||
|
"sort_latest": "Latest",
|
||||||
|
"sort_upcoming": "Upcoming",
|
||||||
|
"upcoming_badge": "UPCOMING",
|
||||||
|
"coming_soon": "Coming Soon",
|
||||||
|
"filmography_count": "Filmography • {{count}} titles",
|
||||||
|
"loading_filmography": "Loading filmography...",
|
||||||
|
"load_more_remaining": "Load More ({{count}} remaining)",
|
||||||
|
"alert_error_title": "Error",
|
||||||
|
"alert_error_message": "Unable to load \"{{title}}\". Please try again later.",
|
||||||
|
"alert_ok": "OK",
|
||||||
|
"no_upcoming": "No upcoming releases available for this actor",
|
||||||
|
"no_content": "No content available for this actor",
|
||||||
|
"no_movies": "No movies available for this actor",
|
||||||
|
"no_tv": "No TV shows available for this actor"
|
||||||
},
|
},
|
||||||
"comments": {
|
"comments": {
|
||||||
"title": "تعليقات Trakt",
|
"title": "تعليقات Trakt",
|
||||||
|
|
@ -1124,7 +1145,7 @@
|
||||||
"clear_cache_desc": "سيؤدي هذا لإزالة رابط المستودع المحفوظ ومسح كل بيانات البلاجنز المخزنة مؤقتاً. ستحتاج لإعادة إدخال رابط المستودع.",
|
"clear_cache_desc": "سيؤدي هذا لإزالة رابط المستودع المحفوظ ومسح كل بيانات البلاجنز المخزنة مؤقتاً. ستحتاج لإعادة إدخال رابط المستودع.",
|
||||||
"add_new_repo": "إضافة مستودع جديد",
|
"add_new_repo": "إضافة مستودع جديد",
|
||||||
"available_plugins": "البلاجنز المتاحة ({{count}})",
|
"available_plugins": "البلاجنز المتاحة ({{count}})",
|
||||||
"search_placeholder": "البحث في البلاجنز...",
|
"placeholder": "البحث في البلاجنز...",
|
||||||
"all": "الكل",
|
"all": "الكل",
|
||||||
"filter_all": "كل الأنواع",
|
"filter_all": "كل الأنواع",
|
||||||
"filter_movies": "أفلام",
|
"filter_movies": "أفلام",
|
||||||
|
|
@ -1171,4 +1192,4 @@
|
||||||
"cancel": "إلغاء",
|
"cancel": "إلغاء",
|
||||||
"add": "إضافة"
|
"add": "إضافة"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"try_different": "Try a different genre or catalog",
|
"try_different": "Try a different genre or catalog",
|
||||||
"select_catalog_desc": "Select a catalog to discover",
|
"select_catalog_desc": "Select a catalog to discover",
|
||||||
"tap_catalog_desc": "Tap the catalog chip above to get started",
|
"tap_catalog_desc": "Tap the catalog chip above to get started",
|
||||||
"search_placeholder": "Search movies, shows...",
|
"placeholder": "Search movies, shows...",
|
||||||
"keep_typing": "Keep typing...",
|
"keep_typing": "Keep typing...",
|
||||||
"type_characters": "Type at least 2 characters to search",
|
"type_characters": "Type at least 2 characters to search",
|
||||||
"no_results": "No results found",
|
"no_results": "No results found",
|
||||||
|
|
@ -279,7 +279,28 @@
|
||||||
"born_in": "Born in {{place}}",
|
"born_in": "Born in {{place}}",
|
||||||
"filmography": "Filmography",
|
"filmography": "Filmography",
|
||||||
"also_known_as": "Also Known As",
|
"also_known_as": "Also Known As",
|
||||||
"no_info_available": "No additional information available"
|
"no_info_available": "No additional information available",
|
||||||
|
"as_character": "as {{character}}",
|
||||||
|
"loading_details": "Loading details...",
|
||||||
|
"years_old": "{{age}} years old",
|
||||||
|
"view_filmography": "View Filmography",
|
||||||
|
"filter": "Filter",
|
||||||
|
"sort_by": "Sort By",
|
||||||
|
"sort_popular": "Popular",
|
||||||
|
"sort_latest": "Latest",
|
||||||
|
"sort_upcoming": "Upcoming",
|
||||||
|
"upcoming_badge": "UPCOMING",
|
||||||
|
"coming_soon": "Coming Soon",
|
||||||
|
"filmography_count": "Filmography • {{count}} titles",
|
||||||
|
"loading_filmography": "Loading filmography...",
|
||||||
|
"load_more_remaining": "Load More ({{count}} remaining)",
|
||||||
|
"alert_error_title": "Error",
|
||||||
|
"alert_error_message": "Unable to load \"{{title}}\". Please try again later.",
|
||||||
|
"alert_ok": "OK",
|
||||||
|
"no_upcoming": "No upcoming releases available for this actor",
|
||||||
|
"no_content": "No content available for this actor",
|
||||||
|
"no_movies": "No movies available for this actor",
|
||||||
|
"no_tv": "No TV shows available for this actor"
|
||||||
},
|
},
|
||||||
"comments": {
|
"comments": {
|
||||||
"title": "Trakt Comments",
|
"title": "Trakt Comments",
|
||||||
|
|
@ -1124,7 +1145,7 @@
|
||||||
"clear_cache_desc": "This will remove the saved repository URL and clear all cached plugin data. You will need to re-enter your repository URL.",
|
"clear_cache_desc": "This will remove the saved repository URL and clear all cached plugin data. You will need to re-enter your repository URL.",
|
||||||
"add_new_repo": "Add New Repository",
|
"add_new_repo": "Add New Repository",
|
||||||
"available_plugins": "Available Plugins ({{count}})",
|
"available_plugins": "Available Plugins ({{count}})",
|
||||||
"search_placeholder": "Search plugins...",
|
"placeholder": "Search plugins...",
|
||||||
"all": "All",
|
"all": "All",
|
||||||
"filter_all": "All Types",
|
"filter_all": "All Types",
|
||||||
"filter_movies": "Movies",
|
"filter_movies": "Movies",
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"try_different": "Prueba con un género o catálogo diferente",
|
"try_different": "Prueba con un género o catálogo diferente",
|
||||||
"select_catalog_desc": "Selecciona un catálogo para descubrir",
|
"select_catalog_desc": "Selecciona un catálogo para descubrir",
|
||||||
"tap_catalog_desc": "Toca el catálogo arriba para empezar",
|
"tap_catalog_desc": "Toca el catálogo arriba para empezar",
|
||||||
"search_placeholder": "Buscar películas, series...",
|
"placeholder": "Buscar películas, series...",
|
||||||
"keep_typing": "Sigue escribiendo...",
|
"keep_typing": "Sigue escribiendo...",
|
||||||
"type_characters": "Escribe al menos 2 caracteres para buscar",
|
"type_characters": "Escribe al menos 2 caracteres para buscar",
|
||||||
"no_results": "No se encontraron resultados",
|
"no_results": "No se encontraron resultados",
|
||||||
|
|
@ -279,7 +279,28 @@
|
||||||
"born_in": "Nacido/a en {{place}}",
|
"born_in": "Nacido/a en {{place}}",
|
||||||
"filmography": "Filmografía",
|
"filmography": "Filmografía",
|
||||||
"also_known_as": "También conocido/a como",
|
"also_known_as": "También conocido/a como",
|
||||||
"no_info_available": "No hay información adicional disponible"
|
"no_info_available": "No additional information available",
|
||||||
|
"as_character": "as {{character}}",
|
||||||
|
"loading_details": "Loading details...",
|
||||||
|
"years_old": "{{age}} years old",
|
||||||
|
"view_filmography": "View Filmography",
|
||||||
|
"filter": "Filter",
|
||||||
|
"sort_by": "Sort By",
|
||||||
|
"sort_popular": "Popular",
|
||||||
|
"sort_latest": "Latest",
|
||||||
|
"sort_upcoming": "Upcoming",
|
||||||
|
"upcoming_badge": "UPCOMING",
|
||||||
|
"coming_soon": "Coming Soon",
|
||||||
|
"filmography_count": "Filmography • {{count}} titles",
|
||||||
|
"loading_filmography": "Loading filmography...",
|
||||||
|
"load_more_remaining": "Load More ({{count}} remaining)",
|
||||||
|
"alert_error_title": "Error",
|
||||||
|
"alert_error_message": "Unable to load \"{{title}}\". Please try again later.",
|
||||||
|
"alert_ok": "OK",
|
||||||
|
"no_upcoming": "No upcoming releases available for this actor",
|
||||||
|
"no_content": "No content available for this actor",
|
||||||
|
"no_movies": "No movies available for this actor",
|
||||||
|
"no_tv": "No TV shows available for this actor"
|
||||||
},
|
},
|
||||||
"comments": {
|
"comments": {
|
||||||
"title": "Comentarios de Trakt",
|
"title": "Comentarios de Trakt",
|
||||||
|
|
@ -1124,7 +1145,7 @@
|
||||||
"clear_cache_desc": "Esto eliminará la URL guardada y los datos en caché. Tendrás que introducir de nuevo la URL del repositorio.",
|
"clear_cache_desc": "Esto eliminará la URL guardada y los datos en caché. Tendrás que introducir de nuevo la URL del repositorio.",
|
||||||
"add_new_repo": "Añadir nuevo repositorio",
|
"add_new_repo": "Añadir nuevo repositorio",
|
||||||
"available_plugins": "Plugins disponibles ({{count}})",
|
"available_plugins": "Plugins disponibles ({{count}})",
|
||||||
"search_placeholder": "Buscar plugins...",
|
"placeholder": "Buscar plugins...",
|
||||||
"all": "Todo",
|
"all": "Todo",
|
||||||
"filter_all": "Todos los tipos",
|
"filter_all": "Todos los tipos",
|
||||||
"filter_movies": "Películas",
|
"filter_movies": "Películas",
|
||||||
|
|
@ -1171,4 +1192,4 @@
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
"add": "Añadir"
|
"add": "Añadir"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"try_different": "Essayez un genre ou un catalogue différent",
|
"try_different": "Essayez un genre ou un catalogue différent",
|
||||||
"select_catalog_desc": "Sélectionnez un catalogue à découvrir",
|
"select_catalog_desc": "Sélectionnez un catalogue à découvrir",
|
||||||
"tap_catalog_desc": "Appuyez sur le jeton de catalogue ci-dessus pour commencer",
|
"tap_catalog_desc": "Appuyez sur le jeton de catalogue ci-dessus pour commencer",
|
||||||
"search_placeholder": "Rechercher des films, séries...",
|
"placeholder": "Rechercher des films, séries...",
|
||||||
"keep_typing": "Continuez à taper...",
|
"keep_typing": "Continuez à taper...",
|
||||||
"type_characters": "Tapez au moins 2 caractères pour rechercher",
|
"type_characters": "Tapez au moins 2 caractères pour rechercher",
|
||||||
"no_results": "Aucun résultat trouvé",
|
"no_results": "Aucun résultat trouvé",
|
||||||
|
|
@ -278,7 +278,28 @@
|
||||||
"personal_info": "Infos personnelles",
|
"personal_info": "Infos personnelles",
|
||||||
"born_in": "Né à {{place}}",
|
"born_in": "Né à {{place}}",
|
||||||
"filmography": "Filmographie",
|
"filmography": "Filmographie",
|
||||||
"also_known_as": "Aussi connu sous le nom de",
|
"also_known_as": "Aussi connu(e) sous le nom de",
|
||||||
|
"as_character": "as {{character}}",
|
||||||
|
"loading_details": "Loading details...",
|
||||||
|
"years_old": "{{age}} years old",
|
||||||
|
"view_filmography": "View Filmography",
|
||||||
|
"filter": "Filter",
|
||||||
|
"sort_by": "Sort By",
|
||||||
|
"sort_popular": "Popular",
|
||||||
|
"sort_latest": "Latest",
|
||||||
|
"sort_upcoming": "Upcoming",
|
||||||
|
"upcoming_badge": "UPCOMING",
|
||||||
|
"coming_soon": "Coming Soon",
|
||||||
|
"filmography_count": "Filmography • {{count}} titles",
|
||||||
|
"loading_filmography": "Loading filmography...",
|
||||||
|
"load_more_remaining": "Load More ({{count}} remaining)",
|
||||||
|
"alert_error_title": "Error",
|
||||||
|
"alert_error_message": "Unable to load \"{{title}}\". Please try again later.",
|
||||||
|
"alert_ok": "OK",
|
||||||
|
"no_upcoming": "No upcoming releases available for this actor",
|
||||||
|
"no_content": "No content available for this actor",
|
||||||
|
"no_movies": "No movies available for this actor",
|
||||||
|
"no_tv": "No TV shows available for this actor",
|
||||||
"no_info_available": "Aucune information supplémentaire disponible"
|
"no_info_available": "Aucune information supplémentaire disponible"
|
||||||
},
|
},
|
||||||
"comments": {
|
"comments": {
|
||||||
|
|
@ -1124,7 +1145,7 @@
|
||||||
"clear_cache_desc": "Cela supprimera l'URL du dépôt enregistrée et effacera toutes les données de plugin mises en cache. Vous devrez ressaisir votre URL de dépôt.",
|
"clear_cache_desc": "Cela supprimera l'URL du dépôt enregistrée et effacera toutes les données de plugin mises en cache. Vous devrez ressaisir votre URL de dépôt.",
|
||||||
"add_new_repo": "Ajouter un nouveau dépôt",
|
"add_new_repo": "Ajouter un nouveau dépôt",
|
||||||
"available_plugins": "Plugins disponibles ({{count}})",
|
"available_plugins": "Plugins disponibles ({{count}})",
|
||||||
"search_placeholder": "Rechercher des plugins...",
|
"placeholder": "Rechercher des plugins...",
|
||||||
"all": "Tout",
|
"all": "Tout",
|
||||||
"filter_all": "Tous les types",
|
"filter_all": "Tous les types",
|
||||||
"filter_movies": "Films",
|
"filter_movies": "Films",
|
||||||
|
|
@ -1171,4 +1192,4 @@
|
||||||
"cancel": "Annuler",
|
"cancel": "Annuler",
|
||||||
"add": "Ajouter"
|
"add": "Ajouter"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"try_different": "Tente um gênero ou catálogo diferente",
|
"try_different": "Tente um gênero ou catálogo diferente",
|
||||||
"select_catalog_desc": "Selecione um catálogo para descobrir",
|
"select_catalog_desc": "Selecione um catálogo para descobrir",
|
||||||
"tap_catalog_desc": "Toque no botão de catálogo acima para começar",
|
"tap_catalog_desc": "Toque no botão de catálogo acima para começar",
|
||||||
"search_placeholder": "Buscar filmes, séries...",
|
"placeholder": "Buscar filmes, séries...",
|
||||||
"keep_typing": "Continue digitando...",
|
"keep_typing": "Continue digitando...",
|
||||||
"type_characters": "Digite pelo menos 2 caracteres para buscar",
|
"type_characters": "Digite pelo menos 2 caracteres para buscar",
|
||||||
"no_results": "Nenhum resultado encontrado",
|
"no_results": "Nenhum resultado encontrado",
|
||||||
|
|
@ -278,7 +278,28 @@
|
||||||
"personal_info": "Informações Pessoais",
|
"personal_info": "Informações Pessoais",
|
||||||
"born_in": "Nascido em {{place}}",
|
"born_in": "Nascido em {{place}}",
|
||||||
"filmography": "Filmografia",
|
"filmography": "Filmografia",
|
||||||
"also_known_as": "Também Conhecido Como",
|
"also_known_as": "Também conhecido(a) como",
|
||||||
|
"as_character": "como {{character}}",
|
||||||
|
"loading_details": "Carregando detalhes...",
|
||||||
|
"years_old": "{{age}} anos",
|
||||||
|
"view_filmography": "Ver Filmografia",
|
||||||
|
"filter": "Filtrar",
|
||||||
|
"sort_by": "Ordenar Por",
|
||||||
|
"sort_popular": "Popular",
|
||||||
|
"sort_latest": "Mais Recente",
|
||||||
|
"sort_upcoming": "Próximos Lançamentos",
|
||||||
|
"upcoming_badge": "EM BREVE",
|
||||||
|
"coming_soon": "Em Breve",
|
||||||
|
"filmography_count": "Filmografia • {{count}} títulos",
|
||||||
|
"loading_filmography": "Carregando filmografia...",
|
||||||
|
"load_more_remaining": "Carregar Mais ({{count}} restantes)",
|
||||||
|
"alert_error_title": "Erro",
|
||||||
|
"alert_error_message": "Não foi possível carregar \"{{title}}\". Por favor, tente novamente mais tarde.",
|
||||||
|
"alert_ok": "OK",
|
||||||
|
"no_upcoming": "Nenhum lançamento futuro disponível para este ator",
|
||||||
|
"no_content": "Nenhum conteúdo disponível para este ator",
|
||||||
|
"no_movies": "Nenhum filme disponível para este ator",
|
||||||
|
"no_tv": "Nenhuma série disponível para este ator",
|
||||||
"no_info_available": "Nenhuma informação adicional disponível"
|
"no_info_available": "Nenhuma informação adicional disponível"
|
||||||
},
|
},
|
||||||
"comments": {
|
"comments": {
|
||||||
|
|
@ -1090,7 +1111,7 @@
|
||||||
"clear_cache_desc": "Isso removerá a URL do repositório salvo e limpará todos os dados de plugins armazenados em cache. Você precisará digitar a URL do repositório novamente.",
|
"clear_cache_desc": "Isso removerá a URL do repositório salvo e limpará todos os dados de plugins armazenados em cache. Você precisará digitar a URL do repositório novamente.",
|
||||||
"add_new_repo": "Adicionar Novo Repositório",
|
"add_new_repo": "Adicionar Novo Repositório",
|
||||||
"available_plugins": "Plugins Disponíveis ({{count}})",
|
"available_plugins": "Plugins Disponíveis ({{count}})",
|
||||||
"search_placeholder": "Pesquisar plugins...",
|
"placeholder": "Pesquisar plugins...",
|
||||||
"all": "Todos",
|
"all": "Todos",
|
||||||
"filter_all": "Todos Tipos",
|
"filter_all": "Todos Tipos",
|
||||||
"filter_movies": "Filmes",
|
"filter_movies": "Filmes",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
View,
|
View,
|
||||||
Text,
|
Text,
|
||||||
|
|
@ -59,6 +60,7 @@ type CastMoviesScreenRouteProp = RouteProp<RootStackParamList, 'CastMovies'>;
|
||||||
|
|
||||||
const CastMoviesScreen: React.FC = () => {
|
const CastMoviesScreen: React.FC = () => {
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
|
const { t } = useTranslation();
|
||||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||||
const route = useRoute<CastMoviesScreenRouteProp>();
|
const route = useRoute<CastMoviesScreenRouteProp>();
|
||||||
const { castMember } = route.params;
|
const { castMember } = route.params;
|
||||||
|
|
@ -89,27 +91,27 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
|
|
||||||
const fetchCastCredits = async () => {
|
const fetchCastCredits = async () => {
|
||||||
if (!castMember) return;
|
if (!castMember) return;
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const credits = await tmdbService.getPersonCombinedCredits(castMember.id);
|
const credits = await tmdbService.getPersonCombinedCredits(castMember.id);
|
||||||
|
|
||||||
if (credits && credits.cast) {
|
if (credits && credits.cast) {
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
|
|
||||||
// Combine cast roles with enhanced data, excluding talk shows and variety shows
|
// Combine cast roles with enhanced data, excluding talk shows and variety shows
|
||||||
const allCredits = credits.cast
|
const allCredits = credits.cast
|
||||||
.filter((item: any) => {
|
.filter((item: any) => {
|
||||||
// Filter out talk shows, variety shows, and ensure we have required data
|
// Filter out talk shows, variety shows, and ensure we have required data
|
||||||
const hasPoster = item.poster_path;
|
const hasPoster = item.poster_path;
|
||||||
const hasReleaseDate = item.release_date || item.first_air_date;
|
const hasReleaseDate = item.release_date || item.first_air_date;
|
||||||
|
|
||||||
if (!hasPoster || !hasReleaseDate) return false;
|
if (!hasPoster || !hasReleaseDate) return false;
|
||||||
|
|
||||||
// Enhanced talk show filtering
|
// Enhanced talk show filtering
|
||||||
const title = (item.title || item.name || '').toLowerCase();
|
const title = (item.title || item.name || '').toLowerCase();
|
||||||
const overview = (item.overview || '').toLowerCase();
|
const overview = (item.overview || '').toLowerCase();
|
||||||
|
|
||||||
// List of common talk show and variety show keywords
|
// List of common talk show and variety show keywords
|
||||||
const talkShowKeywords = [
|
const talkShowKeywords = [
|
||||||
'talk', 'show', 'late night', 'tonight show', 'jimmy fallon', 'snl', 'saturday night live',
|
'talk', 'show', 'late night', 'tonight show', 'jimmy fallon', 'snl', 'saturday night live',
|
||||||
|
|
@ -120,18 +122,18 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
'red carpet', 'premiere', 'after party', 'behind the scenes', 'making of', 'documentary',
|
'red carpet', 'premiere', 'after party', 'behind the scenes', 'making of', 'documentary',
|
||||||
'special', 'concert', 'live performance', 'mtv', 'vh1', 'bet', 'comedy', 'roast'
|
'special', 'concert', 'live performance', 'mtv', 'vh1', 'bet', 'comedy', 'roast'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check if any keyword matches
|
// Check if any keyword matches
|
||||||
const isTalkShow = talkShowKeywords.some(keyword =>
|
const isTalkShow = talkShowKeywords.some(keyword =>
|
||||||
title.includes(keyword) || overview.includes(keyword)
|
title.includes(keyword) || overview.includes(keyword)
|
||||||
);
|
);
|
||||||
|
|
||||||
return !isTalkShow;
|
return !isTalkShow;
|
||||||
})
|
})
|
||||||
.map((item: any) => {
|
.map((item: any) => {
|
||||||
const releaseDate = new Date(item.release_date || item.first_air_date);
|
const releaseDate = new Date(item.release_date || item.first_air_date);
|
||||||
const isUpcoming = releaseDate > currentDate;
|
const isUpcoming = releaseDate > currentDate;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
title: item.title || item.name,
|
title: item.title || item.name,
|
||||||
|
|
@ -144,7 +146,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
isUpcoming,
|
isUpcoming,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
setMovies(allCredits);
|
setMovies(allCredits);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -223,41 +225,41 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
isUpcoming: movie.isUpcoming
|
isUpcoming: movie.isUpcoming
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (__DEV__) console.log('Attempting to get Stremio ID for:', movie.media_type, movie.id.toString());
|
if (__DEV__) console.log('Attempting to get Stremio ID for:', movie.media_type, movie.id.toString());
|
||||||
|
|
||||||
// Get Stremio ID using catalogService
|
// Get Stremio ID using catalogService
|
||||||
const stremioId = await catalogService.getStremioId(movie.media_type, movie.id.toString());
|
const stremioId = await catalogService.getStremioId(movie.media_type, movie.id.toString());
|
||||||
|
|
||||||
if (__DEV__) console.log('Stremio ID result:', stremioId);
|
if (__DEV__) console.log('Stremio ID result:', stremioId);
|
||||||
|
|
||||||
if (stremioId) {
|
if (stremioId) {
|
||||||
if (__DEV__) console.log('Successfully found Stremio ID, navigating to Metadata with:', {
|
if (__DEV__) console.log('Successfully found Stremio ID, navigating to Metadata with:', {
|
||||||
id: stremioId,
|
id: stremioId,
|
||||||
type: movie.media_type
|
type: movie.media_type
|
||||||
});
|
});
|
||||||
|
|
||||||
// Convert TMDB media type to Stremio media type
|
// Convert TMDB media type to Stremio media type
|
||||||
const stremioType = movie.media_type === 'tv' ? 'series' : movie.media_type;
|
const stremioType = movie.media_type === 'tv' ? 'series' : movie.media_type;
|
||||||
|
|
||||||
if (__DEV__) console.log('Navigating with Stremio type conversion:', {
|
if (__DEV__) console.log('Navigating with Stremio type conversion:', {
|
||||||
originalType: movie.media_type,
|
originalType: movie.media_type,
|
||||||
stremioType: stremioType,
|
stremioType: stremioType,
|
||||||
id: stremioId
|
id: stremioId
|
||||||
});
|
});
|
||||||
|
|
||||||
navigation.dispatch(
|
navigation.dispatch(
|
||||||
StackActions.push('Metadata', {
|
StackActions.push('Metadata', {
|
||||||
id: stremioId,
|
id: stremioId,
|
||||||
type: stremioType
|
type: stremioType
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (__DEV__) console.warn('Stremio ID is null/undefined for movie:', movie.title);
|
if (__DEV__) console.warn('Stremio ID is null/undefined for movie:', movie.title);
|
||||||
throw new Error('Could not find Stremio ID');
|
throw new Error('Could not find Stremio ID');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.error('=== Error in handleMoviePress ===');
|
console.error('=== Error in handleMoviePress ===');
|
||||||
console.error('Movie:', movie.title);
|
console.error('Movie:', movie.title);
|
||||||
|
|
@ -265,9 +267,9 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
console.error('Error message:', error.message);
|
console.error('Error message:', error.message);
|
||||||
console.error('Error stack:', error.stack);
|
console.error('Error stack:', error.stack);
|
||||||
}
|
}
|
||||||
setAlertTitle('Error');
|
setAlertTitle(t('cast.alert_error_title'));
|
||||||
setAlertMessage(`Unable to load "${movie.title}". Please try again later.`);
|
setAlertMessage(t('cast.alert_error_message', { title: movie.title }));
|
||||||
setAlertActions([{ label: 'OK', onPress: () => {} }]);
|
setAlertActions([{ label: t('cast.alert_ok'), onPress: () => { } }]);
|
||||||
setAlertVisible(true);
|
setAlertVisible(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -278,7 +280,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
|
|
||||||
const renderFilterButton = (filter: 'all' | 'movies' | 'tv', label: string, count: number) => {
|
const renderFilterButton = (filter: 'all' | 'movies' | 'tv', label: string, count: number) => {
|
||||||
const isSelected = selectedFilter === filter;
|
const isSelected = selectedFilter === filter;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View entering={FadeIn.delay(100)}>
|
<Animated.View entering={FadeIn.delay(100)}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
|
@ -286,8 +288,8 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
paddingHorizontal: 18,
|
paddingHorizontal: 18,
|
||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
borderRadius: 25,
|
borderRadius: 25,
|
||||||
backgroundColor: isSelected
|
backgroundColor: isSelected
|
||||||
? currentTheme.colors.primary
|
? currentTheme.colors.primary
|
||||||
: 'rgba(255, 255, 255, 0.08)',
|
: 'rgba(255, 255, 255, 0.08)',
|
||||||
marginRight: 12,
|
marginRight: 12,
|
||||||
borderWidth: isSelected ? 0 : 1,
|
borderWidth: isSelected ? 0 : 1,
|
||||||
|
|
@ -311,7 +313,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
|
|
||||||
const renderSortButton = (sort: 'popularity' | 'latest' | 'upcoming', label: string, icon: string) => {
|
const renderSortButton = (sort: 'popularity' | 'latest' | 'upcoming', label: string, icon: string) => {
|
||||||
const isSelected = sortBy === sort;
|
const isSelected = sortBy === sort;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View entering={FadeIn.delay(200)}>
|
<Animated.View entering={FadeIn.delay(200)}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
|
@ -319,8 +321,8 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingVertical: 8,
|
paddingVertical: 8,
|
||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
backgroundColor: isSelected
|
backgroundColor: isSelected
|
||||||
? 'rgba(255, 255, 255, 0.15)'
|
? 'rgba(255, 255, 255, 0.15)'
|
||||||
: 'transparent',
|
: 'transparent',
|
||||||
marginRight: 12,
|
marginRight: 12,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -329,10 +331,10 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
onPress={() => setSortBy(sort)}
|
onPress={() => setSortBy(sort)}
|
||||||
activeOpacity={0.7}
|
activeOpacity={0.7}
|
||||||
>
|
>
|
||||||
<MaterialIcons
|
<MaterialIcons
|
||||||
name={icon as any}
|
name={icon as any}
|
||||||
size={16}
|
size={16}
|
||||||
color={isSelected ? currentTheme.colors.primary : 'rgba(255, 255, 255, 0.6)'}
|
color={isSelected ? currentTheme.colors.primary : 'rgba(255, 255, 255, 0.6)'}
|
||||||
style={{ marginRight: 6 }}
|
style={{ marginRight: 6 }}
|
||||||
/>
|
/>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
|
|
@ -397,7 +399,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
<MaterialIcons name="movie" size={32} color="rgba(255, 255, 255, 0.2)" />
|
<MaterialIcons name="movie" size={32} color="rgba(255, 255, 255, 0.2)" />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Upcoming indicator */}
|
{/* Upcoming indicator */}
|
||||||
{item.isUpcoming && (
|
{item.isUpcoming && (
|
||||||
<View style={{
|
<View style={{
|
||||||
|
|
@ -419,7 +421,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
marginLeft: 4,
|
marginLeft: 4,
|
||||||
letterSpacing: 0.2,
|
letterSpacing: 0.2,
|
||||||
}}>
|
}}>
|
||||||
UPCOMING
|
{t('cast.upcoming_badge')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
@ -463,7 +465,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={{ paddingHorizontal: 4, marginTop: 8 }}>
|
<View style={{ paddingHorizontal: 4, marginTop: 8 }}>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|
@ -474,7 +476,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
}} numberOfLines={2}>
|
}} numberOfLines={2}>
|
||||||
{`${item.title}`}
|
{`${item.title}`}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{item.character && (
|
{item.character && (
|
||||||
<Text style={{
|
<Text style={{
|
||||||
color: 'rgba(255, 255, 255, 0.65)',
|
color: 'rgba(255, 255, 255, 0.65)',
|
||||||
|
|
@ -482,10 +484,10 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
marginTop: 3,
|
marginTop: 3,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
}} numberOfLines={1}>
|
}} numberOfLines={1}>
|
||||||
{`as ${item.character}`}
|
{t('cast.as_character', { character: item.character })}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View style={{
|
<View style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
@ -502,7 +504,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
{`${new Date(item.release_date).getFullYear()}`}
|
{`${new Date(item.release_date).getFullYear()}`}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.isUpcoming && (
|
{item.isUpcoming && (
|
||||||
<View style={{
|
<View style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
@ -516,7 +518,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
marginLeft: 2,
|
marginLeft: 2,
|
||||||
letterSpacing: 0.2,
|
letterSpacing: 0.2,
|
||||||
}}>
|
}}>
|
||||||
Coming Soon
|
{t('cast.coming_soon')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
@ -538,7 +540,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
[1, 0.9],
|
[1, 0.9],
|
||||||
Extrapolate.CLAMP
|
Extrapolate.CLAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
opacity,
|
opacity,
|
||||||
};
|
};
|
||||||
|
|
@ -547,7 +549,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, backgroundColor: currentTheme.colors.darkBackground }}>
|
<View style={{ flex: 1, backgroundColor: currentTheme.colors.darkBackground }}>
|
||||||
{/* Minimal Header */}
|
{/* Minimal Header */}
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
paddingTop: safeAreaTop + 16,
|
paddingTop: safeAreaTop + 16,
|
||||||
|
|
@ -560,7 +562,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
headerAnimatedStyle
|
headerAnimatedStyle
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
entering={SlideInDown.delay(100)}
|
entering={SlideInDown.delay(100)}
|
||||||
style={{ flexDirection: 'row', alignItems: 'center' }}
|
style={{ flexDirection: 'row', alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
|
|
@ -579,7 +581,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
>
|
>
|
||||||
<MaterialIcons name="arrow-back" size={20} color="rgba(255, 255, 255, 0.9)" />
|
<MaterialIcons name="arrow-back" size={20} color="rgba(255, 255, 255, 0.9)" />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<View style={{
|
<View style={{
|
||||||
width: 44,
|
width: 44,
|
||||||
height: 44,
|
height: 44,
|
||||||
|
|
@ -613,7 +615,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
|
@ -630,7 +632,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
letterSpacing: 0.2,
|
letterSpacing: 0.2,
|
||||||
}}>
|
}}>
|
||||||
{`Filmography • ${movies.length} titles`}
|
{t('cast.filmography_count', { count: movies.length })}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
|
@ -652,16 +654,16 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
letterSpacing: 0.5,
|
letterSpacing: 0.5,
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
}}>
|
}}>
|
||||||
Filter
|
{t('cast.filter')}
|
||||||
</Text>
|
</Text>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
horizontal
|
horizontal
|
||||||
showsHorizontalScrollIndicator={false}
|
showsHorizontalScrollIndicator={false}
|
||||||
contentContainerStyle={{ paddingRight: 20 }}
|
contentContainerStyle={{ paddingRight: 20 }}
|
||||||
>
|
>
|
||||||
{renderFilterButton('all', 'All', movies.length)}
|
{renderFilterButton('all', t('catalog.all'), movies.length)}
|
||||||
{renderFilterButton('movies', 'Movies', movieCount)}
|
{renderFilterButton('movies', t('catalog.movies'), movieCount)}
|
||||||
{renderFilterButton('tv', 'TV Shows', tvCount)}
|
{renderFilterButton('tv', t('catalog.tv_shows'), tvCount)}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|
@ -675,16 +677,16 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
letterSpacing: 0.5,
|
letterSpacing: 0.5,
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
}}>
|
}}>
|
||||||
Sort By
|
{t('cast.sort_by')}
|
||||||
</Text>
|
</Text>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
horizontal
|
horizontal
|
||||||
showsHorizontalScrollIndicator={false}
|
showsHorizontalScrollIndicator={false}
|
||||||
contentContainerStyle={{ paddingRight: 20 }}
|
contentContainerStyle={{ paddingRight: 20 }}
|
||||||
>
|
>
|
||||||
{renderSortButton('popularity', 'Popular', 'trending-up')}
|
{renderSortButton('popularity', t('cast.sort_popular'), 'trending-up')}
|
||||||
{renderSortButton('latest', 'Latest', 'schedule')}
|
{renderSortButton('latest', t('cast.sort_latest'), 'schedule')}
|
||||||
{renderSortButton('upcoming', 'Upcoming', 'event')}
|
{renderSortButton('upcoming', t('cast.sort_upcoming'), 'event')}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -703,7 +705,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
marginTop: 12,
|
marginTop: 12,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
}}>
|
}}>
|
||||||
Loading filmography...
|
{t('cast.loading_filmography')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -755,7 +757,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
}}>
|
}}>
|
||||||
{`Load More (${filteredAndSortedMovies.length - displayLimit} remaining)`}
|
{t('cast.load_more_remaining', { count: filteredAndSortedMovies.length - displayLimit })}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
@ -763,7 +765,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
ListEmptyComponent={
|
ListEmptyComponent={
|
||||||
<Animated.View
|
<Animated.View
|
||||||
entering={FadeIn.delay(400)}
|
entering={FadeIn.delay(400)}
|
||||||
style={{
|
style={{
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
@ -790,7 +792,7 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
}}>
|
}}>
|
||||||
No Content Found
|
{t('catalog.no_content_found')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={{
|
<Text style={{
|
||||||
color: 'rgba(255, 255, 255, 0.5)',
|
color: 'rgba(255, 255, 255, 0.5)',
|
||||||
|
|
@ -799,13 +801,13 @@ const CastMoviesScreen: React.FC = () => {
|
||||||
lineHeight: 20,
|
lineHeight: 20,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
}}>
|
}}>
|
||||||
{sortBy === 'upcoming'
|
{sortBy === 'upcoming'
|
||||||
? 'No upcoming releases available for this actor'
|
? t('cast.no_upcoming')
|
||||||
: selectedFilter === 'all'
|
: selectedFilter === 'all'
|
||||||
? 'No content available for this actor'
|
? t('cast.no_content')
|
||||||
: selectedFilter === 'movies'
|
: selectedFilter === 'movies'
|
||||||
? 'No movies available for this actor'
|
? t('cast.no_movies')
|
||||||
: 'No TV shows available for this actor'
|
: t('cast.no_tv')
|
||||||
}
|
}
|
||||||
</Text>
|
</Text>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue