mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
updated settinsgcreen and it's sub-pages to support localization
This commit is contained in:
parent
9c37ad8b94
commit
afddf4bf2d
9 changed files with 360 additions and 132 deletions
|
|
@ -37,6 +37,108 @@
|
|||
"language": "Language",
|
||||
"select_language": "Select Language",
|
||||
"english": "English",
|
||||
"portuguese": "Portuguese"
|
||||
"portuguese": "Portuguese",
|
||||
"account": "Account",
|
||||
"content_discovery": "Content & Discovery",
|
||||
"appearance": "Appearance",
|
||||
"integrations": "Integrations",
|
||||
"playback": "Playback",
|
||||
"backup_restore": "Backup & Restore",
|
||||
"updates": "Updates",
|
||||
"about": "About",
|
||||
"developer": "Developer",
|
||||
"cache": "Cache",
|
||||
"settings_title": "Settings",
|
||||
"sign_in_sync": "Sign in to sync",
|
||||
"add_catalogs_sources": "Addons, catalogs, and sources",
|
||||
"player_trailers_downloads": "Player, trailers, downloads",
|
||||
"mdblist_tmdb_ai": "MDBList, TMDB, AI",
|
||||
"check_updates": "Check for updates",
|
||||
"developer_tools": "Testing and debug options",
|
||||
"clear_mdblist_cache": "Clear MDBList Cache",
|
||||
"cache_management": "CACHE MANAGEMENT",
|
||||
"downloads_counter": "downloads and counting",
|
||||
"made_with_love": "Made with ❤️ by Tapframe and friends",
|
||||
"sections": {
|
||||
"information": "INFORMATION",
|
||||
"theme": "THEME",
|
||||
"layout": "LAYOUT",
|
||||
"sources": "SOURCES",
|
||||
"catalogs": "CATALOGS",
|
||||
"discovery": "DISCOVERY",
|
||||
"metadata": "METADATA",
|
||||
"ai_assistant": "AI ASSISTANT",
|
||||
"video_player": "VIDEO PLAYER",
|
||||
"audio_subtitles": "AUDIO & SUBTITLES",
|
||||
"media": "MEDIA",
|
||||
"notifications": "NOTIFICATIONS",
|
||||
"testing": "TESTING",
|
||||
"danger_zone": "DANGER ZONE"
|
||||
},
|
||||
"items": {
|
||||
"privacy_policy": "Privacy Policy",
|
||||
"report_issue": "Report Issue",
|
||||
"version": "Version",
|
||||
"contributors": "Contributors",
|
||||
"view_contributors": "View all contributors",
|
||||
"theme": "Theme",
|
||||
"episode_layout": "Episode Layout",
|
||||
"streams_backdrop": "Streams Backdrop",
|
||||
"streams_backdrop_desc": "Show blurred backdrop on mobile streams",
|
||||
"addons": "Addons",
|
||||
"installed": "installed",
|
||||
"debrid_integration": "Debrid Integration",
|
||||
"debrid_desc": "Connect Torbox for premium streams",
|
||||
"plugins": "Plugins",
|
||||
"plugins_desc": "Manage plugins and repositories",
|
||||
"catalogs": "Catalogs",
|
||||
"active": "active",
|
||||
"home_screen": "Home Screen",
|
||||
"home_screen_desc": "Layout and content",
|
||||
"continue_watching": "Continue Watching",
|
||||
"continue_watching_desc": "Cache and playback behavior",
|
||||
"show_discover": "Show Discover Section",
|
||||
"show_discover_desc": "Display discover content in Search",
|
||||
"mdblist": "MDBList",
|
||||
"mdblist_connected": "Connected",
|
||||
"mdblist_desc": "Enable to add ratings & reviews",
|
||||
"tmdb": "TMDB",
|
||||
"tmdb_desc": "Metadata & logo source provider",
|
||||
"openrouter": "OpenRouter API",
|
||||
"openrouter_connected": "Connected",
|
||||
"openrouter_desc": "Add your API key to enable AI chat",
|
||||
"video_player": "Video Player",
|
||||
"built_in": "Built-in",
|
||||
"external": "External",
|
||||
"preferred_audio": "Preferred Audio Language",
|
||||
"preferred_subtitle": "Preferred Subtitle Language",
|
||||
"subtitle_source": "Subtitle Source Priority",
|
||||
"auto_select_subs": "Auto-Select Subtitles",
|
||||
"auto_select_subs_desc": "Automatically select subtitles matching your preferences",
|
||||
"show_trailers": "Show Trailers",
|
||||
"show_trailers_desc": "Display trailers in hero section",
|
||||
"enable_downloads": "Enable Downloads (Beta)",
|
||||
"enable_downloads_desc": "Show Downloads tab and enable saving streams",
|
||||
"notifications": "Notifications",
|
||||
"notifications_desc": "Episode reminders",
|
||||
"test_onboarding": "Test Onboarding",
|
||||
"reset_onboarding": "Reset Onboarding",
|
||||
"test_announcement": "Test Announcement",
|
||||
"test_announcement_desc": "Show what's new overlay",
|
||||
"reset_campaigns": "Reset Campaigns",
|
||||
"reset_campaigns_desc": "Clear campaign impressions",
|
||||
"clear_all_data": "Clear All Data",
|
||||
"clear_all_data_desc": "Reset all settings and cached data"
|
||||
},
|
||||
"options": {
|
||||
"horizontal": "Horizontal",
|
||||
"vertical": "Vertical",
|
||||
"internal_first": "Internal First",
|
||||
"internal_first_desc": "Prefer embedded subtitles, then external",
|
||||
"external_first": "External First",
|
||||
"external_first_desc": "Prefer addon subtitles, then embedded",
|
||||
"any_available": "Any Available",
|
||||
"any_available_desc": "Use first available subtitle track"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,108 @@
|
|||
"language": "Idioma",
|
||||
"select_language": "Selecionar Idioma",
|
||||
"english": "Inglês",
|
||||
"portuguese": "Português"
|
||||
"portuguese": "Português",
|
||||
"account": "Conta",
|
||||
"content_discovery": "Conteúdo e Descoberta",
|
||||
"appearance": "Aparência",
|
||||
"integrations": "Integrações",
|
||||
"playback": "Reprodução",
|
||||
"backup_restore": "Backup e Restauração",
|
||||
"updates": "Atualizações",
|
||||
"about": "Sobre",
|
||||
"developer": "Desenvolvedor",
|
||||
"cache": "Cache",
|
||||
"settings_title": "Configurações",
|
||||
"sign_in_sync": "Faça login para sincronizar",
|
||||
"add_catalogs_sources": "Addons, catálogos e fontes",
|
||||
"player_trailers_downloads": "Player, trailers, downloads",
|
||||
"mdblist_tmdb_ai": "MDBList, TMDB, IA",
|
||||
"check_updates": "Verificar atualizações",
|
||||
"developer_tools": "Opções de teste e depuração",
|
||||
"clear_mdblist_cache": "Limpar Cache do MDBList",
|
||||
"cache_management": "GERENCIAMENTO DE CACHE",
|
||||
"downloads_counter": "downloads e contando",
|
||||
"made_with_love": "Feito com ❤️ por Tapframe e amigos",
|
||||
"sections": {
|
||||
"information": "INFORMAÇÕES",
|
||||
"theme": "TEMA",
|
||||
"layout": "LAYOUT",
|
||||
"sources": "FONTES",
|
||||
"catalogs": "CATÁLOGOS",
|
||||
"discovery": "DESCOBERTA",
|
||||
"metadata": "METADADOS",
|
||||
"ai_assistant": "ASSISTENTE IA",
|
||||
"video_player": "PLAYER DE VÍDEO",
|
||||
"audio_subtitles": "ÁUDIO E LEGENDAS",
|
||||
"media": "MÍDIA",
|
||||
"notifications": "NOTIFICAÇÕES",
|
||||
"testing": "TESTES",
|
||||
"danger_zone": "AREA DE PERIGO"
|
||||
},
|
||||
"items": {
|
||||
"privacy_policy": "Política de Privacidade",
|
||||
"report_issue": "Reportar Problema",
|
||||
"version": "Versão",
|
||||
"contributors": "Contribuidores",
|
||||
"view_contributors": "Ver todos os contribuidores",
|
||||
"theme": "Tema",
|
||||
"episode_layout": "Layout de Episódios",
|
||||
"streams_backdrop": "Fundo de Streams",
|
||||
"streams_backdrop_desc": "Mostrar fundo desfocado em streams móveis",
|
||||
"addons": "Addons",
|
||||
"installed": "instalados",
|
||||
"debrid_integration": "Integração Debrid",
|
||||
"debrid_desc": "Conectar Torbox para streams premium",
|
||||
"plugins": "Plugins",
|
||||
"plugins_desc": "Gerenciar plugins e repositórios",
|
||||
"catalogs": "Catálogos",
|
||||
"active": "ativos",
|
||||
"home_screen": "Tela Inicial",
|
||||
"home_screen_desc": "Layout e conteúdo",
|
||||
"continue_watching": "Continuar Assistindo",
|
||||
"continue_watching_desc": "Cache e comportamento de reprodução",
|
||||
"show_discover": "Mostrar Seção Descobrir",
|
||||
"show_discover_desc": "Exibir conteúdo de descoberta na Pesquisa",
|
||||
"mdblist": "MDBList",
|
||||
"mdblist_connected": "Conectado",
|
||||
"mdblist_desc": "Habilitar para adicionar avaliações e resenhas",
|
||||
"tmdb": "TMDB",
|
||||
"tmdb_desc": "Provedor de metadados e logos",
|
||||
"openrouter": "OpenRouter API",
|
||||
"openrouter_connected": "Conectado",
|
||||
"openrouter_desc": "Adicione sua chave API para chat IA",
|
||||
"video_player": "Player de Vídeo",
|
||||
"built_in": "Integrado",
|
||||
"external": "Externo",
|
||||
"preferred_audio": "Idioma de Áudio Preferido",
|
||||
"preferred_subtitle": "Idioma de Legenda Preferido",
|
||||
"subtitle_source": "Prioridade de Fonte de Legenda",
|
||||
"auto_select_subs": "Auto-Selecionar Legendas",
|
||||
"auto_select_subs_desc": "Selecionar legendas automaticamente",
|
||||
"show_trailers": "Mostrar Trailers",
|
||||
"show_trailers_desc": "Exibir trailers na seção hero",
|
||||
"enable_downloads": "Habilitar Downloads (Beta)",
|
||||
"enable_downloads_desc": "Mostrar aba Downloads e permitir salvar streams",
|
||||
"notifications": "Notificações",
|
||||
"notifications_desc": "Lembretes de episódios",
|
||||
"test_onboarding": "Testar Onboarding",
|
||||
"reset_onboarding": "Resetar Onboarding",
|
||||
"test_announcement": "Testar Anúncio",
|
||||
"test_announcement_desc": "Mostrar sobreposição de novidades",
|
||||
"reset_campaigns": "Resetar Campanhas",
|
||||
"reset_campaigns_desc": "Limpar impressões de campanhas",
|
||||
"clear_all_data": "Limpar Todos os Dados",
|
||||
"clear_all_data_desc": "Resetar todas as configurações e cache"
|
||||
},
|
||||
"options": {
|
||||
"horizontal": "Horizontal",
|
||||
"vertical": "Vertical",
|
||||
"internal_first": "Interno Primeiro",
|
||||
"internal_first_desc": "Preferir legendas embutidas, depois externas",
|
||||
"external_first": "Externo Primeiro",
|
||||
"external_first_desc": "Preferir legendas de addons, depois embutidas",
|
||||
"any_available": "Qualquer Disponível",
|
||||
"any_available_desc": "Usar primeira legenda disponível"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -50,25 +50,15 @@ const { width } = Dimensions.get('window');
|
|||
const isTablet = width >= 768;
|
||||
|
||||
// Settings categories for tablet sidebar
|
||||
const SETTINGS_CATEGORIES = [
|
||||
{ id: 'account', title: 'Account', icon: 'user' as string },
|
||||
{ id: 'content', title: 'Content & Discovery', icon: 'compass' as string },
|
||||
{ id: 'appearance', title: 'Appearance', icon: 'sliders' as string },
|
||||
{ id: 'integrations', title: 'Integrations', icon: 'layers' as string },
|
||||
{ id: 'playback', title: 'Playback', icon: 'play-circle' as string },
|
||||
{ id: 'backup', title: 'Backup & Restore', icon: 'archive' as string },
|
||||
{ id: 'updates', title: 'Updates', icon: 'refresh-ccw' as string },
|
||||
{ id: 'about', title: 'About', icon: 'info' as string },
|
||||
{ id: 'developer', title: 'Developer', icon: 'code' as string },
|
||||
{ id: 'cache', title: 'Cache', icon: 'database' as string },
|
||||
];
|
||||
// Settings categories moved inside component for translation
|
||||
|
||||
|
||||
// Tablet Sidebar Component
|
||||
interface SidebarProps {
|
||||
selectedCategory: string;
|
||||
onCategorySelect: (category: string) => void;
|
||||
currentTheme: any;
|
||||
categories: typeof SETTINGS_CATEGORIES;
|
||||
categories: any[];
|
||||
extraTopPadding?: number;
|
||||
}
|
||||
|
||||
|
|
@ -143,9 +133,21 @@ const Sidebar: React.FC<SidebarProps> = ({ selectedCategory, onCategorySelect, c
|
|||
);
|
||||
};
|
||||
|
||||
|
||||
const SettingsScreen: React.FC = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
const SETTINGS_CATEGORIES = [
|
||||
{ id: 'account', title: t('settings.account'), icon: 'user' },
|
||||
{ id: 'content', title: t('settings.content_discovery'), icon: 'compass' },
|
||||
{ id: 'appearance', title: t('settings.appearance'), icon: 'sliders' },
|
||||
{ id: 'integrations', title: t('settings.integrations'), icon: 'layers' },
|
||||
{ id: 'playback', title: t('settings.playback'), icon: 'play-circle' },
|
||||
{ id: 'backup', title: t('settings.backup_restore'), icon: 'archive' },
|
||||
{ id: 'updates', title: t('settings.updates'), icon: 'refresh-ccw' },
|
||||
{ id: 'about', title: t('settings.about'), icon: 'info' },
|
||||
{ id: 'developer', title: t('settings.developer'), icon: 'code' },
|
||||
{ id: 'cache', title: t('settings.cache'), icon: 'database' },
|
||||
];
|
||||
const { settings, updateSetting } = useSettings();
|
||||
const [hasUpdateBadge, setHasUpdateBadge] = useState(false);
|
||||
const [languageModalVisible, setLanguageModalVisible] = useState(false);
|
||||
|
|
@ -333,11 +335,11 @@ const SettingsScreen: React.FC = () => {
|
|||
switch (categoryId) {
|
||||
case 'account':
|
||||
return (
|
||||
<SettingsCard title="ACCOUNT" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.account')} isTablet={isTablet}>
|
||||
{isItemVisible('trakt') && (
|
||||
<SettingItem
|
||||
title="Trakt"
|
||||
description={isAuthenticated ? `@${userProfile?.username || 'User'}` : "Sign in to sync"}
|
||||
description={isAuthenticated ? `@${userProfile?.username || 'User'}` : t('settings.sign_in_sync')}
|
||||
customIcon={<TraktIcon size={isTablet ? 24 : 20} color={currentTheme.colors.primary} />}
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('TraktSettings')}
|
||||
|
|
@ -365,16 +367,16 @@ const SettingsScreen: React.FC = () => {
|
|||
|
||||
case 'developer':
|
||||
return __DEV__ ? (
|
||||
<SettingsCard title="DEVELOPER" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.testing')} isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title="Test Onboarding"
|
||||
title={t('settings.items.test_onboarding')}
|
||||
icon="play-circle"
|
||||
onPress={() => navigation.navigate('Onboarding')}
|
||||
renderControl={() => <ChevronRight />}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Reset Onboarding"
|
||||
title={t('settings.items.reset_onboarding')}
|
||||
icon="refresh-ccw"
|
||||
onPress={async () => {
|
||||
try {
|
||||
|
|
@ -388,9 +390,9 @@ const SettingsScreen: React.FC = () => {
|
|||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Test Announcement"
|
||||
title={t('settings.items.test_announcement')}
|
||||
icon="bell"
|
||||
description="Show what's new overlay"
|
||||
description={t('settings.items.test_announcement_desc')}
|
||||
onPress={async () => {
|
||||
try {
|
||||
await mmkvStorage.removeItem('announcement_v1.0.0_shown');
|
||||
|
|
@ -403,8 +405,8 @@ const SettingsScreen: React.FC = () => {
|
|||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Reset Campaigns"
|
||||
description="Clear campaign impressions"
|
||||
title={t('settings.items.reset_campaigns')}
|
||||
description={t('settings.items.reset_campaigns_desc')}
|
||||
icon="refresh-cw"
|
||||
onPress={async () => {
|
||||
await campaignService.resetCampaigns();
|
||||
|
|
@ -414,7 +416,7 @@ const SettingsScreen: React.FC = () => {
|
|||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Clear All Data"
|
||||
title={t('settings.items.clear_all_data')}
|
||||
icon="trash-2"
|
||||
onPress={() => {
|
||||
openAlert(
|
||||
|
|
@ -444,9 +446,9 @@ const SettingsScreen: React.FC = () => {
|
|||
|
||||
case 'cache':
|
||||
return mdblistKeySet ? (
|
||||
<SettingsCard title="CACHE MANAGEMENT" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.cache_management')} isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title="Clear MDBList Cache"
|
||||
title={t('settings.clear_mdblist_cache')}
|
||||
icon="database"
|
||||
onPress={handleClearMDBListCache}
|
||||
isLast={true}
|
||||
|
|
@ -457,9 +459,9 @@ const SettingsScreen: React.FC = () => {
|
|||
|
||||
case 'backup':
|
||||
return (
|
||||
<SettingsCard title="BACKUP & RESTORE" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.backup_restore').toUpperCase()} isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title="Backup & Restore"
|
||||
title={t('settings.backup_restore')}
|
||||
description="Create and restore app backups"
|
||||
icon="archive"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -472,10 +474,10 @@ const SettingsScreen: React.FC = () => {
|
|||
|
||||
case 'updates':
|
||||
return (
|
||||
<SettingsCard title="UPDATES" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.updates').toUpperCase()} isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title="App Updates"
|
||||
description="Check for updates and manage app version"
|
||||
description={t('settings.check_updates')}
|
||||
icon="refresh-ccw"
|
||||
renderControl={() => <ChevronRight />}
|
||||
badge={Platform.OS === 'android' && hasUpdateBadge ? 1 : undefined}
|
||||
|
|
@ -549,7 +551,7 @@ const SettingsScreen: React.FC = () => {
|
|||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar barStyle={'light-content'} />
|
||||
<ScreenHeader title="Settings" />
|
||||
<ScreenHeader title={t('settings.settings_title')} />
|
||||
<View style={{ flex: 1 }}>
|
||||
<View style={styles.contentContainer}>
|
||||
<ScrollView
|
||||
|
|
@ -560,11 +562,11 @@ const SettingsScreen: React.FC = () => {
|
|||
>
|
||||
{/* Account */}
|
||||
{(settingsConfig?.categories?.['account']?.visible !== false) && isItemVisible('trakt') && (
|
||||
<SettingsCard title="ACCOUNT">
|
||||
<SettingsCard title={t('settings.account').toUpperCase()}>
|
||||
{isItemVisible('trakt') && (
|
||||
<SettingItem
|
||||
title="Trakt"
|
||||
description={isAuthenticated ? `@${userProfile?.username || 'User'}` : "Sign in to sync"}
|
||||
description={isAuthenticated ? `@${userProfile?.username || 'User'}` : t('settings.sign_in_sync')}
|
||||
customIcon={<TraktIcon size={20} color={currentTheme.colors.primary} />}
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('TraktSettings')}
|
||||
|
|
@ -591,8 +593,8 @@ const SettingsScreen: React.FC = () => {
|
|||
/>
|
||||
{(settingsConfig?.categories?.['content']?.visible !== false) && (
|
||||
<SettingItem
|
||||
title="Content & Discovery"
|
||||
description="Addons, catalogs, and sources"
|
||||
title={t('settings.content_discovery')}
|
||||
description={t('settings.add_catalogs_sources')}
|
||||
icon="compass"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('ContentDiscoverySettings')}
|
||||
|
|
@ -600,7 +602,7 @@ const SettingsScreen: React.FC = () => {
|
|||
)}
|
||||
{(settingsConfig?.categories?.['appearance']?.visible !== false) && (
|
||||
<SettingItem
|
||||
title="Appearance"
|
||||
title={t('settings.appearance')}
|
||||
description={currentTheme.name}
|
||||
icon="sliders"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -609,8 +611,8 @@ const SettingsScreen: React.FC = () => {
|
|||
)}
|
||||
{(settingsConfig?.categories?.['integrations']?.visible !== false) && (
|
||||
<SettingItem
|
||||
title="Integrations"
|
||||
description="MDBList, TMDB, AI"
|
||||
title={t('settings.integrations')}
|
||||
description={t('settings.mdblist_tmdb_ai')}
|
||||
icon="layers"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('IntegrationsSettings')}
|
||||
|
|
@ -618,8 +620,8 @@ const SettingsScreen: React.FC = () => {
|
|||
)}
|
||||
{(settingsConfig?.categories?.['playback']?.visible !== false) && (
|
||||
<SettingItem
|
||||
title="Playback"
|
||||
description="Player, trailers, downloads"
|
||||
title={t('settings.playback')}
|
||||
description={t('settings.player_trailers_downloads')}
|
||||
icon="play-circle"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('PlaybackSettings')}
|
||||
|
|
@ -637,7 +639,7 @@ const SettingsScreen: React.FC = () => {
|
|||
<SettingsCard title="DATA">
|
||||
{(settingsConfig?.categories?.['backup']?.visible !== false) && (
|
||||
<SettingItem
|
||||
title="Backup & Restore"
|
||||
title={t('settings.backup_restore')}
|
||||
description="Create and restore app backups"
|
||||
icon="archive"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -647,7 +649,7 @@ const SettingsScreen: React.FC = () => {
|
|||
{(settingsConfig?.categories?.['updates']?.visible !== false) && (
|
||||
<SettingItem
|
||||
title="App Updates"
|
||||
description="Check for updates"
|
||||
description={t('settings.check_updates')}
|
||||
icon="refresh-ccw"
|
||||
badge={Platform.OS === 'android' && hasUpdateBadge ? 1 : undefined}
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -668,7 +670,7 @@ const SettingsScreen: React.FC = () => {
|
|||
{mdblistKeySet && (
|
||||
<SettingsCard title="CACHE">
|
||||
<SettingItem
|
||||
title="Clear MDBList Cache"
|
||||
title={t('settings.clear_mdblist_cache')}
|
||||
icon="database"
|
||||
onPress={handleClearMDBListCache}
|
||||
isLast
|
||||
|
|
@ -677,7 +679,7 @@ const SettingsScreen: React.FC = () => {
|
|||
)}
|
||||
|
||||
{/* About */}
|
||||
<SettingsCard title="ABOUT">
|
||||
<SettingsCard title={t('settings.about').toUpperCase()}>
|
||||
<SettingItem
|
||||
title="About Nuvio"
|
||||
description={getDisplayedAppVersion()}
|
||||
|
|
@ -690,10 +692,10 @@ const SettingsScreen: React.FC = () => {
|
|||
|
||||
{/* Developer - only in DEV mode */}
|
||||
{__DEV__ && (
|
||||
<SettingsCard title="DEVELOPER">
|
||||
<SettingsCard title={t('settings.sections.testing')}>
|
||||
<SettingItem
|
||||
title="Developer Tools"
|
||||
description="Testing and debug options"
|
||||
title={t('settings.items.developer_tools')}
|
||||
description={t('settings.developer_tools')}
|
||||
icon="code"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('DeveloperSettings')}
|
||||
|
|
@ -709,7 +711,7 @@ const SettingsScreen: React.FC = () => {
|
|||
{displayDownloads.toLocaleString()}
|
||||
</Text>
|
||||
<Text style={[styles.downloadsLabel, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
downloads and counting
|
||||
{t('settings.downloads_counter')}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
|
@ -788,7 +790,7 @@ const SettingsScreen: React.FC = () => {
|
|||
|
||||
<View style={styles.footer}>
|
||||
<Text style={[styles.footerText, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
Made with ❤️ by Tapframe and friends
|
||||
{t('settings.made_with_love')}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { fetchTotalDownloads } from '../../services/githubReleaseService';
|
|||
import { getDisplayedAppVersion } from '../../utils/version';
|
||||
import ScreenHeader from '../../components/common/ScreenHeader';
|
||||
import { SettingsCard, SettingItem, ChevronRight } from './SettingsComponents';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
|
|
@ -29,6 +30,7 @@ export const AboutSettingsContent: React.FC<AboutSettingsContentProps> = ({
|
|||
isTablet = false,
|
||||
displayDownloads: externalDisplayDownloads
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
|
||||
|
|
@ -52,30 +54,30 @@ export const AboutSettingsContent: React.FC<AboutSettingsContentProps> = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<SettingsCard title="INFORMATION" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.information')} isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title="Privacy Policy"
|
||||
title={t('settings.items.privacy_policy')}
|
||||
icon="lock"
|
||||
onPress={() => Linking.openURL('https://tapframe.github.io/NuvioStreaming/#privacy-policy')}
|
||||
renderControl={() => <ChevronRight />}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Report Issue"
|
||||
title={t('settings.items.report_issue')}
|
||||
icon="alert-triangle"
|
||||
onPress={() => Sentry.showFeedbackWidget()}
|
||||
renderControl={() => <ChevronRight />}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Version"
|
||||
title={t('settings.items.version')}
|
||||
description={getDisplayedAppVersion()}
|
||||
icon="info"
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Contributors"
|
||||
description="View all contributors"
|
||||
title={t('settings.items.contributors')}
|
||||
description={t('settings.items.view_contributors')}
|
||||
icon="users"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('Contributors')}
|
||||
|
|
@ -92,6 +94,7 @@ export const AboutSettingsContent: React.FC<AboutSettingsContentProps> = ({
|
|||
*/
|
||||
export const AboutFooter: React.FC<{ displayDownloads: number | null }> = ({ displayDownloads }) => {
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -101,7 +104,7 @@ export const AboutFooter: React.FC<{ displayDownloads: number | null }> = ({ dis
|
|||
{displayDownloads.toLocaleString()}
|
||||
</Text>
|
||||
<Text style={[styles.downloadsLabel, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
downloads and counting
|
||||
{t('settings.downloads_counter')}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
|
@ -179,7 +182,7 @@ export const AboutFooter: React.FC<{ displayDownloads: number | null }> = ({ dis
|
|||
|
||||
<View style={styles.footer}>
|
||||
<Text style={[styles.footerText, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
Made with ❤️ by Tapframe and Friends
|
||||
{t('settings.made_with_love')}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
|
|
@ -192,13 +195,14 @@ export const AboutFooter: React.FC<{ displayDownloads: number | null }> = ({ dis
|
|||
const AboutSettingsScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const screenIsTablet = width >= 768;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScreenHeader title="About" showBackButton onBackPress={() => navigation.goBack()} />
|
||||
<ScreenHeader title={t('settings.about')} showBackButton onBackPress={() => navigation.goBack()} />
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { RootStackParamList } from '../../navigation/AppNavigator';
|
|||
import ScreenHeader from '../../components/common/ScreenHeader';
|
||||
import { SettingsCard, SettingItem, CustomSwitch, ChevronRight } from './SettingsComponents';
|
||||
import { useRealtimeConfig } from '../../hooks/useRealtimeConfig';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ export const AppearanceSettingsContent: React.FC<AppearanceSettingsContentProps>
|
|||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { settings, updateSetting } = useSettings();
|
||||
const { t } = useTranslation();
|
||||
const config = useRealtimeConfig();
|
||||
|
||||
const isItemVisible = (itemId: string) => {
|
||||
|
|
@ -43,10 +45,10 @@ export const AppearanceSettingsContent: React.FC<AppearanceSettingsContentProps>
|
|||
return (
|
||||
<>
|
||||
{hasVisibleItems(['theme']) && (
|
||||
<SettingsCard title="THEME" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.theme')} isTablet={isTablet}>
|
||||
{isItemVisible('theme') && (
|
||||
<SettingItem
|
||||
title="Theme"
|
||||
title={t('settings.items.theme')}
|
||||
description={currentTheme.name}
|
||||
icon="sliders"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -59,11 +61,11 @@ export const AppearanceSettingsContent: React.FC<AppearanceSettingsContentProps>
|
|||
)}
|
||||
|
||||
{hasVisibleItems(['episode_layout', 'streams_backdrop']) && (
|
||||
<SettingsCard title="LAYOUT" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.layout')} isTablet={isTablet}>
|
||||
{isItemVisible('episode_layout') && (
|
||||
<SettingItem
|
||||
title="Episode Layout"
|
||||
description={settings?.episodeLayoutStyle === 'horizontal' ? 'Horizontal' : 'Vertical'}
|
||||
title={t('settings.items.episode_layout')}
|
||||
description={settings?.episodeLayoutStyle === 'horizontal' ? t('settings.options.horizontal') : t('settings.options.vertical')}
|
||||
icon="grid"
|
||||
renderControl={() => (
|
||||
<CustomSwitch
|
||||
|
|
@ -77,8 +79,8 @@ export const AppearanceSettingsContent: React.FC<AppearanceSettingsContentProps>
|
|||
)}
|
||||
{!isTablet && isItemVisible('streams_backdrop') && (
|
||||
<SettingItem
|
||||
title="Streams Backdrop"
|
||||
description="Show blurred backdrop on mobile streams"
|
||||
title={t('settings.items.streams_backdrop')}
|
||||
description={t('settings.items.streams_backdrop_desc')}
|
||||
icon="image"
|
||||
renderControl={() => (
|
||||
<CustomSwitch
|
||||
|
|
@ -102,13 +104,14 @@ export const AppearanceSettingsContent: React.FC<AppearanceSettingsContentProps>
|
|||
const AppearanceSettingsScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const screenIsTablet = width >= 768;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScreenHeader title="Appearance" showBackButton onBackPress={() => navigation.goBack()} />
|
||||
<ScreenHeader title={t('settings.appearance')} showBackButton onBackPress={() => navigation.goBack()} />
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import ScreenHeader from '../../components/common/ScreenHeader';
|
|||
import PluginIcon from '../../components/icons/PluginIcon';
|
||||
import { SettingsCard, SettingItem, CustomSwitch, ChevronRight } from './SettingsComponents';
|
||||
import { useRealtimeConfig } from '../../hooks/useRealtimeConfig';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
|
|
@ -27,6 +28,7 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { settings, updateSetting } = useSettings();
|
||||
const { t } = useTranslation();
|
||||
const config = useRealtimeConfig();
|
||||
|
||||
const [addonCount, setAddonCount] = useState<number>(0);
|
||||
|
|
@ -79,11 +81,11 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
return (
|
||||
<>
|
||||
{hasVisibleItems(['addons', 'debrid', 'plugins']) && (
|
||||
<SettingsCard title="SOURCES" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.sources')} isTablet={isTablet}>
|
||||
{isItemVisible('addons') && (
|
||||
<SettingItem
|
||||
title="Addons"
|
||||
description={`${addonCount} installed`}
|
||||
title={t('settings.items.addons')}
|
||||
description={`${addonCount} ${t('settings.items.installed')}`}
|
||||
icon="layers"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('Addons')}
|
||||
|
|
@ -92,8 +94,8 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
)}
|
||||
{isItemVisible('debrid') && (
|
||||
<SettingItem
|
||||
title="Debrid Integration"
|
||||
description="Connect Torbox for premium streams"
|
||||
title={t('settings.items.debrid_integration')}
|
||||
description={t('settings.items.debrid_desc')}
|
||||
icon="link"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('DebridIntegration')}
|
||||
|
|
@ -102,8 +104,8 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
)}
|
||||
{isItemVisible('plugins') && (
|
||||
<SettingItem
|
||||
title="Plugins"
|
||||
description="Manage plugins and repositories"
|
||||
title={t('settings.items.plugins')}
|
||||
description={t('settings.items.plugins_desc')}
|
||||
customIcon={<PluginIcon size={isTablet ? 22 : 18} color={currentTheme.colors.primary} />}
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('ScraperSettings')}
|
||||
|
|
@ -115,11 +117,11 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
)}
|
||||
|
||||
{hasVisibleItems(['catalogs', 'home_screen', 'continue_watching']) && (
|
||||
<SettingsCard title="CATALOGS" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.catalogs')} isTablet={isTablet}>
|
||||
{isItemVisible('catalogs') && (
|
||||
<SettingItem
|
||||
title="Catalogs"
|
||||
description={`${catalogCount} active`}
|
||||
title={t('settings.items.catalogs')}
|
||||
description={`${catalogCount} ${t('settings.items.active')}`}
|
||||
icon="list"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('CatalogSettings')}
|
||||
|
|
@ -128,8 +130,8 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
)}
|
||||
{isItemVisible('home_screen') && (
|
||||
<SettingItem
|
||||
title="Home Screen"
|
||||
description="Layout and content"
|
||||
title={t('settings.items.home_screen')}
|
||||
description={t('settings.items.home_screen_desc')}
|
||||
icon="home"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('HomeScreenSettings')}
|
||||
|
|
@ -138,8 +140,8 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
)}
|
||||
{isItemVisible('continue_watching') && (
|
||||
<SettingItem
|
||||
title="Continue Watching"
|
||||
description="Cache and playback behavior"
|
||||
title={t('settings.items.continue_watching')}
|
||||
description={t('settings.items.continue_watching_desc')}
|
||||
icon="play-circle"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('ContinueWatchingSettings')}
|
||||
|
|
@ -151,11 +153,11 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
)}
|
||||
|
||||
{hasVisibleItems(['show_discover']) && (
|
||||
<SettingsCard title="DISCOVERY" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.discovery')} isTablet={isTablet}>
|
||||
{isItemVisible('show_discover') && (
|
||||
<SettingItem
|
||||
title="Show Discover Section"
|
||||
description="Display discover content in Search"
|
||||
title={t('settings.items.show_discover')}
|
||||
description={t('settings.items.show_discover_desc')}
|
||||
icon="compass"
|
||||
renderControl={() => (
|
||||
<CustomSwitch
|
||||
|
|
@ -179,13 +181,14 @@ export const ContentDiscoverySettingsContent: React.FC<ContentDiscoverySettingsC
|
|||
const ContentDiscoverySettingsScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const screenIsTablet = width >= 768;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScreenHeader title="Content & Discovery" showBackButton onBackPress={() => navigation.goBack()} />
|
||||
<ScreenHeader title={t('settings.content_discovery')} showBackButton onBackPress={() => navigation.goBack()} />
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,12 @@ import { RootStackParamList } from '../../navigation/AppNavigator';
|
|||
import ScreenHeader from '../../components/common/ScreenHeader';
|
||||
import CustomAlert from '../../components/CustomAlert';
|
||||
import { SettingsCard, SettingItem, ChevronRight } from './SettingsComponents';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const DeveloperSettingsScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const [alertVisible, setAlertVisible] = useState(false);
|
||||
|
|
@ -84,36 +86,36 @@ const DeveloperSettingsScreen: React.FC = () => {
|
|||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScreenHeader title="Developer" showBackButton onBackPress={() => navigation.goBack()} />
|
||||
<ScreenHeader title={t('settings.developer')} showBackButton onBackPress={() => navigation.goBack()} />
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentContainerStyle={[styles.scrollContent, { paddingBottom: insets.bottom + 24 }]}
|
||||
>
|
||||
<SettingsCard title="TESTING">
|
||||
<SettingsCard title={t('settings.sections.testing')}>
|
||||
<SettingItem
|
||||
title="Test Onboarding"
|
||||
title={t('settings.items.test_onboarding')}
|
||||
icon="play-circle"
|
||||
onPress={() => navigation.navigate('Onboarding')}
|
||||
renderControl={() => <ChevronRight />}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Reset Onboarding"
|
||||
title={t('settings.items.reset_onboarding')}
|
||||
icon="refresh-ccw"
|
||||
onPress={handleResetOnboarding}
|
||||
renderControl={() => <ChevronRight />}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Test Announcement"
|
||||
title={t('settings.items.test_announcement')}
|
||||
icon="bell"
|
||||
description="Show what's new overlay"
|
||||
description={t('settings.items.test_announcement_desc')}
|
||||
onPress={handleResetAnnouncement}
|
||||
renderControl={() => <ChevronRight />}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Reset Campaigns"
|
||||
description="Clear campaign impressions"
|
||||
title={t('settings.items.reset_campaigns')}
|
||||
description={t('settings.items.reset_campaigns_desc')}
|
||||
icon="refresh-cw"
|
||||
onPress={handleResetCampaigns}
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -121,10 +123,10 @@ const DeveloperSettingsScreen: React.FC = () => {
|
|||
/>
|
||||
</SettingsCard>
|
||||
|
||||
<SettingsCard title="DANGER ZONE">
|
||||
<SettingsCard title={t('settings.sections.danger_zone')}>
|
||||
<SettingItem
|
||||
title="Clear All Data"
|
||||
description="Reset all settings and cached data"
|
||||
title={t('settings.items.clear_all_data')}
|
||||
description={t('settings.items.clear_all_data_desc')}
|
||||
icon="trash-2"
|
||||
onPress={handleClearAllData}
|
||||
isLast
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import MDBListIcon from '../../components/icons/MDBListIcon';
|
|||
import TMDBIcon from '../../components/icons/TMDBIcon';
|
||||
import { SettingsCard, SettingItem, ChevronRight } from './SettingsComponents';
|
||||
import { useRealtimeConfig } from '../../hooks/useRealtimeConfig';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
|
|
@ -26,6 +27,7 @@ export const IntegrationsSettingsContent: React.FC<IntegrationsSettingsContentPr
|
|||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const config = useRealtimeConfig();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [mdblistKeySet, setMdblistKeySet] = useState<boolean>(false);
|
||||
const [openRouterKeySet, setOpenRouterKeySet] = useState<boolean>(false);
|
||||
|
|
@ -62,11 +64,11 @@ export const IntegrationsSettingsContent: React.FC<IntegrationsSettingsContentPr
|
|||
return (
|
||||
<>
|
||||
{hasVisibleItems(['mdblist', 'tmdb']) && (
|
||||
<SettingsCard title="METADATA" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.metadata')} isTablet={isTablet}>
|
||||
{isItemVisible('mdblist') && (
|
||||
<SettingItem
|
||||
title="MDBList"
|
||||
description={mdblistKeySet ? "Connected" : "Enable to add ratings & reviews"}
|
||||
title={t('settings.items.mdblist')}
|
||||
description={mdblistKeySet ? t('settings.items.mdblist_connected') : t('settings.items.mdblist_desc')}
|
||||
customIcon={<MDBListIcon size={isTablet ? 22 : 18} colorPrimary={currentTheme.colors.primary} colorSecondary={currentTheme.colors.white} />}
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('MDBListSettings')}
|
||||
|
|
@ -75,8 +77,8 @@ export const IntegrationsSettingsContent: React.FC<IntegrationsSettingsContentPr
|
|||
)}
|
||||
{isItemVisible('tmdb') && (
|
||||
<SettingItem
|
||||
title="TMDB"
|
||||
description="Metadata & logo source provider"
|
||||
title={t('settings.items.tmdb')}
|
||||
description={t('settings.items.tmdb_desc')}
|
||||
customIcon={<TMDBIcon size={isTablet ? 22 : 18} color={currentTheme.colors.primary} />}
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('TMDBSettings')}
|
||||
|
|
@ -88,11 +90,11 @@ export const IntegrationsSettingsContent: React.FC<IntegrationsSettingsContentPr
|
|||
)}
|
||||
|
||||
{hasVisibleItems(['openrouter']) && (
|
||||
<SettingsCard title="AI ASSISTANT" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.ai_assistant')} isTablet={isTablet}>
|
||||
{isItemVisible('openrouter') && (
|
||||
<SettingItem
|
||||
title="OpenRouter API"
|
||||
description={openRouterKeySet ? "Connected" : "Add your API key to enable AI chat"}
|
||||
title={t('settings.items.openrouter')}
|
||||
description={openRouterKeySet ? t('settings.items.openrouter_connected') : t('settings.items.openrouter_desc')}
|
||||
icon="cpu"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('AISettings')}
|
||||
|
|
@ -112,13 +114,14 @@ export const IntegrationsSettingsContent: React.FC<IntegrationsSettingsContentPr
|
|||
const IntegrationsSettingsScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const screenIsTablet = width >= 768;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScreenHeader title="Integrations" showBackButton onBackPress={() => navigation.goBack()} />
|
||||
<ScreenHeader title={t('settings.integrations')} showBackButton onBackPress={() => navigation.goBack()} />
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { SettingsCard, SettingItem, CustomSwitch, ChevronRight } from './Setting
|
|||
import { useRealtimeConfig } from '../../hooks/useRealtimeConfig';
|
||||
import { MaterialIcons } from '@expo/vector-icons';
|
||||
import { BottomSheetModal, BottomSheetScrollView, BottomSheetBackdrop } from '@gorhom/bottom-sheet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
|
|
@ -69,6 +70,7 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { settings, updateSetting } = useSettings();
|
||||
const { t } = useTranslation();
|
||||
const config = useRealtimeConfig();
|
||||
|
||||
// Bottom sheet refs
|
||||
|
|
@ -116,8 +118,10 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
};
|
||||
|
||||
const getSourceLabel = (value: string) => {
|
||||
const option = SUBTITLE_SOURCE_OPTIONS.find(o => o.value === value);
|
||||
return option ? option.label : 'Internal First';
|
||||
if (value === 'internal') return t('settings.options.internal_first');
|
||||
if (value === 'external') return t('settings.options.external_first');
|
||||
if (value === 'any') return t('settings.options.any_available');
|
||||
return t('settings.options.internal_first');
|
||||
};
|
||||
|
||||
// Render backdrop for bottom sheets
|
||||
|
|
@ -151,13 +155,13 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
return (
|
||||
<>
|
||||
{hasVisibleItems(['video_player']) && (
|
||||
<SettingsCard title="VIDEO PLAYER" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.video_player')} isTablet={isTablet}>
|
||||
{isItemVisible('video_player') && (
|
||||
<SettingItem
|
||||
title="Video Player"
|
||||
title={t('settings.items.video_player')}
|
||||
description={Platform.OS === 'ios'
|
||||
? (settings?.preferredPlayer === 'internal' ? 'Built-in' : settings?.preferredPlayer?.toUpperCase() || 'Built-in')
|
||||
: (settings?.useExternalPlayer ? 'External' : 'Built-in')
|
||||
? (settings?.preferredPlayer === 'internal' ? t('settings.items.built_in') : settings?.preferredPlayer?.toUpperCase() || t('settings.items.built_in'))
|
||||
: (settings?.useExternalPlayer ? t('settings.items.external') : t('settings.items.built_in'))
|
||||
}
|
||||
icon="play-circle"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -170,9 +174,9 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
)}
|
||||
|
||||
{/* Audio & Subtitle Preferences */}
|
||||
<SettingsCard title="AUDIO & SUBTITLES" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.audio_subtitles')} isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title="Preferred Audio Language"
|
||||
title={t('settings.items.preferred_audio')}
|
||||
description={getLanguageName(settings?.preferredAudioLanguage || 'en')}
|
||||
icon="volume-2"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -180,7 +184,7 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Preferred Subtitle Language"
|
||||
title={t('settings.items.preferred_subtitle')}
|
||||
description={getLanguageName(settings?.preferredSubtitleLanguage || 'en')}
|
||||
icon="type"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -188,7 +192,7 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Subtitle Source Priority"
|
||||
title={t('settings.items.subtitle_source')}
|
||||
description={getSourceLabel(settings?.subtitleSourcePreference || 'internal')}
|
||||
icon="layers"
|
||||
renderControl={() => <ChevronRight />}
|
||||
|
|
@ -196,8 +200,8 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
isTablet={isTablet}
|
||||
/>
|
||||
<SettingItem
|
||||
title="Auto-Select Subtitles"
|
||||
description="Automatically select subtitles matching your preferences"
|
||||
title={t('settings.items.auto_select_subs')}
|
||||
description={t('settings.items.auto_select_subs_desc')}
|
||||
icon="zap"
|
||||
renderControl={() => (
|
||||
<CustomSwitch
|
||||
|
|
@ -211,11 +215,11 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
</SettingsCard>
|
||||
|
||||
{hasVisibleItems(['show_trailers', 'enable_downloads']) && (
|
||||
<SettingsCard title="MEDIA" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.media')} isTablet={isTablet}>
|
||||
{isItemVisible('show_trailers') && (
|
||||
<SettingItem
|
||||
title="Show Trailers"
|
||||
description="Display trailers in hero section"
|
||||
title={t('settings.items.show_trailers')}
|
||||
description={t('settings.items.show_trailers_desc')}
|
||||
icon="film"
|
||||
renderControl={() => (
|
||||
<CustomSwitch
|
||||
|
|
@ -228,8 +232,8 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
)}
|
||||
{isItemVisible('enable_downloads') && (
|
||||
<SettingItem
|
||||
title="Enable Downloads (Beta)"
|
||||
description="Show Downloads tab and enable saving streams"
|
||||
title={t('settings.items.enable_downloads')}
|
||||
description={t('settings.items.enable_downloads_desc')}
|
||||
icon="download"
|
||||
renderControl={() => (
|
||||
<CustomSwitch
|
||||
|
|
@ -245,11 +249,11 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
)}
|
||||
|
||||
{hasVisibleItems(['notifications']) && (
|
||||
<SettingsCard title="NOTIFICATIONS" isTablet={isTablet}>
|
||||
<SettingsCard title={t('settings.sections.notifications')} isTablet={isTablet}>
|
||||
{isItemVisible('notifications') && (
|
||||
<SettingItem
|
||||
title="Notifications"
|
||||
description="Episode reminders"
|
||||
title={t('settings.items.notifications')}
|
||||
description={t('settings.items.notifications_desc')}
|
||||
icon="bell"
|
||||
renderControl={() => <ChevronRight />}
|
||||
onPress={() => navigation.navigate('NotificationSettings')}
|
||||
|
|
@ -272,7 +276,7 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
handleIndicatorStyle={{ backgroundColor: 'rgba(255,255,255,0.3)' }}
|
||||
>
|
||||
<View style={styles.sheetHeader}>
|
||||
<Text style={styles.sheetTitle}>Preferred Audio Language</Text>
|
||||
<Text style={styles.sheetTitle}>{t('settings.items.preferred_audio')}</Text>
|
||||
</View>
|
||||
<BottomSheetScrollView contentContainerStyle={styles.sheetContent}>
|
||||
{AVAILABLE_LANGUAGES.map((lang) => {
|
||||
|
|
@ -313,7 +317,7 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
handleIndicatorStyle={{ backgroundColor: 'rgba(255,255,255,0.3)' }}
|
||||
>
|
||||
<View style={styles.sheetHeader}>
|
||||
<Text style={styles.sheetTitle}>Preferred Subtitle Language</Text>
|
||||
<Text style={styles.sheetTitle}>{t('settings.items.preferred_subtitle')}</Text>
|
||||
</View>
|
||||
<BottomSheetScrollView contentContainerStyle={styles.sheetContent}>
|
||||
{AVAILABLE_LANGUAGES.map((lang) => {
|
||||
|
|
@ -354,7 +358,7 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
handleIndicatorStyle={{ backgroundColor: 'rgba(255,255,255,0.3)' }}
|
||||
>
|
||||
<View style={styles.sheetHeader}>
|
||||
<Text style={styles.sheetTitle}>Subtitle Source Priority</Text>
|
||||
<Text style={styles.sheetTitle}>{t('settings.items.subtitle_source')}</Text>
|
||||
</View>
|
||||
<BottomSheetScrollView contentContainerStyle={styles.sheetContent}>
|
||||
{SUBTITLE_SOURCE_OPTIONS.map((option) => {
|
||||
|
|
@ -370,10 +374,12 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
>
|
||||
<View style={styles.sourceItemContent}>
|
||||
<Text style={[styles.sourceLabel, { color: isSelected ? currentTheme.colors.primary : '#fff' }]}>
|
||||
{option.label}
|
||||
{getSourceLabel(option.value)}
|
||||
</Text>
|
||||
<Text style={styles.sourceDescription}>
|
||||
{option.description}
|
||||
{option.value === 'internal' && t('settings.options.internal_first_desc')}
|
||||
{option.value === 'external' && t('settings.options.external_first_desc')}
|
||||
{option.value === 'any' && t('settings.options.any_available_desc')}
|
||||
</Text>
|
||||
</View>
|
||||
{isSelected && (
|
||||
|
|
@ -395,13 +401,14 @@ export const PlaybackSettingsContent: React.FC<PlaybackSettingsContentProps> = (
|
|||
const PlaybackSettingsScreen: React.FC = () => {
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
const { currentTheme } = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const screenIsTablet = width >= 768;
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { backgroundColor: currentTheme.colors.darkBackground }]}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<ScreenHeader title="Playback" showBackButton onBackPress={() => navigation.goBack()} />
|
||||
<ScreenHeader title={t('settings.playback')} showBackButton onBackPress={() => navigation.goBack()} />
|
||||
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
|
|
|
|||
Loading…
Reference in a new issue