From ae66ec1c239e7fd2d9cdbb95acea3c9606756a1b Mon Sep 17 00:00:00 2001 From: tapframe Date: Sun, 27 Jul 2025 18:27:58 +0530 Subject: [PATCH] ui fixes --- src/screens/ScraperSettingsScreen.tsx | 509 +++++++++++++++++++++----- 1 file changed, 415 insertions(+), 94 deletions(-) diff --git a/src/screens/ScraperSettingsScreen.tsx b/src/screens/ScraperSettingsScreen.tsx index 9a135adf..a65ad9b9 100644 --- a/src/screens/ScraperSettingsScreen.tsx +++ b/src/screens/ScraperSettingsScreen.tsx @@ -3,14 +3,16 @@ import { View, Text, StyleSheet, - ScrollView, - TextInput, TouchableOpacity, Alert, Switch, - ActivityIndicator, + TextInput, + ScrollView, RefreshControl, + StatusBar, + Platform, Image, + ActivityIndicator, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { Ionicons } from '@expo/vector-icons'; @@ -18,10 +20,309 @@ import { useNavigation } from '@react-navigation/native'; import { useSettings } from '../hooks/useSettings'; import { localScraperService, ScraperInfo } from '../services/localScraperService'; import { logger } from '../utils/logger'; +import { useTheme } from '../contexts/ThemeContext'; + +const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0; + +// Create a styles creator function that accepts the theme colors +const createStyles = (colors: any) => StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background, + }, + header: { + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 16, + paddingTop: Platform.OS === 'ios' ? 44 : ANDROID_STATUSBAR_HEIGHT + 16, + paddingBottom: 16, + }, + backButton: { + flexDirection: 'row', + alignItems: 'center', + }, + backText: { + fontSize: 17, + color: colors.primary, + marginLeft: 8, + }, + headerTitle: { + fontSize: 34, + fontWeight: 'bold', + color: colors.white, + paddingHorizontal: 16, + marginBottom: 24, + }, + scrollView: { + flex: 1, + }, + section: { + backgroundColor: colors.elevation1, + marginBottom: 16, + borderRadius: 12, + padding: 16, + }, + sectionTitle: { + fontSize: 20, + fontWeight: '600', + color: colors.white, + marginBottom: 8, + }, + sectionHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 16, + paddingHorizontal: 0, + }, + sectionDescription: { + fontSize: 14, + color: colors.mediumGray, + marginBottom: 16, + lineHeight: 20, + }, + emptyContainer: { + backgroundColor: colors.elevation2, + borderRadius: 12, + padding: 32, + alignItems: 'center', + justifyContent: 'center', + marginHorizontal: 16, + marginBottom: 24, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.1, + shadowRadius: 4, + elevation: 2, + }, + emptyText: { + marginTop: 8, + color: colors.mediumGray, + fontSize: 15, + }, + scraperItem: { + flexDirection: 'row', + alignItems: 'center', + backgroundColor: colors.elevation2, + padding: 12, + marginHorizontal: 16, + marginBottom: 8, + borderRadius: 8, + shadowColor: '#000', + shadowOffset: { width: 0, height: 1 }, + shadowOpacity: 0.05, + shadowRadius: 2, + elevation: 1, + }, + scraperLogo: { + width: 40, + height: 40, + marginRight: 12, + borderRadius: 6, + backgroundColor: colors.elevation3, + }, + scraperInfo: { + flex: 1, + }, + scraperName: { + fontSize: 15, + fontWeight: '600', + color: colors.white, + marginBottom: 2, + }, + scraperDescription: { + fontSize: 13, + color: colors.mediumGray, + marginBottom: 4, + lineHeight: 18, + }, + scraperMeta: { + flexDirection: 'row', + alignItems: 'center', + }, + scraperVersion: { + fontSize: 12, + color: colors.mediumGray, + }, + scraperDot: { + fontSize: 12, + color: colors.mediumGray, + marginHorizontal: 8, + }, + scraperTypes: { + fontSize: 12, + color: colors.mediumGray, + }, + settingRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 16, + }, + settingInfo: { + flex: 1, + marginRight: 16, + }, + settingTitle: { + fontSize: 17, + fontWeight: '600', + color: colors.white, + marginBottom: 2, + }, + settingDescription: { + fontSize: 14, + color: colors.mediumEmphasis, + lineHeight: 20, + }, + textInput: { + backgroundColor: colors.elevation1, + borderRadius: 8, + padding: 12, + color: colors.white, + marginBottom: 16, + fontSize: 15, + }, + button: { + backgroundColor: colors.elevation2, + paddingVertical: 12, + paddingHorizontal: 16, + borderRadius: 8, + marginRight: 8, + }, + primaryButton: { + backgroundColor: colors.primary, + }, + secondaryButton: { + backgroundColor: colors.elevation2, + }, + buttonText: { + fontSize: 16, + fontWeight: '600', + color: colors.white, + textAlign: 'center', + }, + secondaryButtonText: { + fontSize: 16, + fontWeight: '600', + color: colors.mediumGray, + textAlign: 'center', + }, + clearButton: { + backgroundColor: '#ff3b30', + paddingVertical: 8, + paddingHorizontal: 12, + borderRadius: 8, + }, + clearButtonText: { + fontSize: 14, + fontWeight: '600', + color: colors.white, + }, + currentRepoContainer: { + backgroundColor: colors.elevation1, + borderRadius: 8, + padding: 12, + marginBottom: 16, + }, + currentRepoLabel: { + fontSize: 14, + fontWeight: '600', + color: colors.primary, + marginBottom: 4, + }, + currentRepoUrl: { + fontSize: 14, + color: colors.white, + fontFamily: Platform.OS === 'ios' ? 'Courier' : 'monospace', + lineHeight: 18, + }, + urlHint: { + fontSize: 12, + color: colors.mediumGray, + marginBottom: 8, + lineHeight: 16, + }, + defaultRepoButton: { + backgroundColor: colors.elevation3, + borderRadius: 6, + paddingVertical: 8, + paddingHorizontal: 12, + marginBottom: 16, + alignItems: 'center', + }, + defaultRepoButtonText: { + color: colors.primary, + fontSize: 14, + fontWeight: '500', + }, + buttonRow: { + flexDirection: 'row', + gap: 12, + }, + infoText: { + fontSize: 14, + color: colors.mediumEmphasis, + lineHeight: 20, + }, + content: { + flex: 1, + }, + emptyState: { + alignItems: 'center', + paddingVertical: 32, + }, + emptyStateTitle: { + fontSize: 18, + fontWeight: '600', + color: colors.white, + marginTop: 16, + marginBottom: 8, + }, + emptyStateDescription: { + fontSize: 14, + color: colors.mediumGray, + textAlign: 'center', + lineHeight: 20, + }, + scrapersList: { + gap: 12, + }, + scrapersContainer: { + marginBottom: 24, + }, + inputContainer: { + marginBottom: 16, + }, + lastSection: { + borderBottomWidth: 0, + }, + disabledSection: { + opacity: 0.5, + }, + disabledText: { + color: colors.elevation3, + }, + disabledContainer: { + opacity: 0.5, + }, + disabledInput: { + backgroundColor: colors.elevation1, + opacity: 0.5, + }, + disabledButton: { + opacity: 0.5, + }, + disabledImage: { + opacity: 0.3, + }, + }); const ScraperSettingsScreen: React.FC = () => { const navigation = useNavigation(); const { settings, updateSetting } = useSettings(); + const { currentTheme } = useTheme(); + const colors = currentTheme.colors; + const styles = createStyles(colors); const [repositoryUrl, setRepositoryUrl] = useState(settings.scraperRepositoryUrl); const [installedScrapers, setInstalledScrapers] = useState([]); const [isLoading, setIsLoading] = useState(false); @@ -182,53 +483,33 @@ const ScraperSettingsScreen: React.FC = () => { await updateSetting('enableScraperUrlValidation', enabled); }; - const renderScraperItem = (scraper: ScraperInfo) => ( - - {scraper.logo && ( - - )} - - {scraper.name} - {scraper.description} - - v{scraper.version} - - {scraper.supportedTypes.join(', ')} - - - - handleToggleScraper(scraper.id, enabled)} - trackColor={{ false: '#767577', true: '#007AFF' }} - thumbColor={scraper.enabled ? '#ffffff' : '#f4f3f4'} - /> - - ); + return ( - + + navigation.goBack()} > - + + Settings - Local Scrapers + + Local Scrapers } > - {/* Enable/Disable Local Scrapers */} + {/* Enable Local Scrapers - Top Priority */} @@ -240,33 +521,17 @@ const ScraperSettingsScreen: React.FC = () => { - - - {/* URL Validation Toggle */} - - - Enable URL Validation - - Validate streaming URLs before returning them (may slow down results but improves reliability) - - - - {/* Repository Configuration */} - + {/* Repository Configuration - Moved up for better UX */} + - Repository Configuration - {hasRepository && ( + Repository Configuration + {hasRepository && settings.enableLocalScrapers && ( { )} - + Enter the URL of a Nuvio scraper repository to download and install scrapers. {hasRepository && repositoryUrl && ( - - Current Repository: - {repositoryUrl} + + Current Repository: + {repositoryUrl} )} - + 💡 Use GitHub raw URL format. Default: https://raw.githubusercontent.com/tapframe/nuvio-providers/main - Use Default Repository + Use Default Repository {isLoading ? ( ) : ( - Save Repository + Save Repository )} {hasRepository && ( {isRefreshing ? ( - + ) : ( - Refresh + Refresh )} )} @@ -339,10 +606,10 @@ const ScraperSettingsScreen: React.FC = () => { {/* Installed Scrapers */} - + - Installed Scrapers - {installedScrapers.length > 0 && ( + Installed Scrapers + {installedScrapers.length > 0 && settings.enableLocalScrapers && ( { {installedScrapers.length === 0 ? ( - - - No Scrapers Installed - - Add a repository URL above and refresh to install scrapers. - - - ) : ( - - {installedScrapers.map(renderScraperItem)} - - )} + + + No Scrapers Installed + + Configure a repository above to install scrapers. + + + ) : ( + + {installedScrapers.map((scraper) => ( + + {scraper.logo ? ( + + ) : ( + + )} + + {scraper.name} + {scraper.description} + + v{scraper.version} + + + {scraper.supportedTypes.join(', ')} + + + + handleToggleScraper(scraper.id, enabled)} + trackColor={{ false: colors.elevation3, true: colors.primary }} + thumbColor={scraper.enabled && settings.enableLocalScrapers ? colors.white : '#f4f3f4'} + disabled={!settings.enableLocalScrapers} + /> + + ))} + + )} - {/* Information */} - + {/* Additional Scraper Settings */} + + Additional Settings + + + Enable URL Validation + + Validate streaming URLs before returning them (may slow down results but improves reliability) + + + + + + + + {/* About */} + About Local Scrapers Local scrapers are JavaScript modules that can search for streaming links from various sources. They run locally on your device and can be installed from trusted repositories. - - ⚠️ Only install scrapers from trusted sources. Malicious scrapers could potentially access your data. - - + ); }; @@ -412,11 +727,16 @@ const styles = StyleSheet.create({ borderBottomWidth: 1, borderBottomColor: '#333', }, + lastSection: { + borderBottomWidth: 0, + }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12, + marginHorizontal: -16, + paddingHorizontal: 16, }, sectionTitle: { fontSize: 18, @@ -498,6 +818,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 12, borderRadius: 6, backgroundColor: '#ff3b30', + marginLeft: 0, }, clearButtonText: { color: '#ffffff',